util.inspect()

Renders any value as the readable debug string Node prints for objects in console.log.

Signature
util.inspect(object[, options])
  • Added in Node.js v0.3.0

Parameters

ParameterTypeDescription
$objectanyAny JavaScript primitive or Object.
$options.showHiddenoptionalboolean= falseInclude non-enumerable properties and symbols, WeakMap/WeakSet entries, and user-defined prototype properties.
$options.depthoptionalnumber= 2How many times to recurse. Pass Infinity or null to recurse up to the maximum call stack size.
$options.colorsoptionalboolean= falseStyle the output with ANSI colour codes.
$options.customInspectoptionalboolean= trueWhen false, [util.inspect.custom](depth, opts, inspect) functions are not invoked.
$options.showProxyoptionalboolean= falseShow a Proxy's target and handler objects instead of the proxy's apparent value.
$options.maxArrayLengthoptionalinteger= 100Maximum Array, TypedArray, Map, WeakMap and WeakSet elements to include. null or Infinity shows all.
$options.maxStringLengthoptionalinteger= 10000Maximum characters of a string to include. null or Infinity shows all.
$options.breakLengthoptionalinteger= 80Column width at which values are split across lines.
$options.compactoptionalboolean | integer= 3false puts each key on its own line; a number unites up to that many inner elements on one line when they fit within breakLength.
$options.sortedoptionalboolean | Function= falseSort object properties and Set/Map entries; a function is used as the comparator.
$options.gettersoptionalboolean | string= falseInvoke getters during inspection. Accepts true, 'get' or 'set'.
$options.numericSeparatoroptionalboolean= falseSeparate every three digits of a number or BigInt with an underscore.

Return value

stringA string representation of `object`, intended for debugging.

Errors

Does not throw for ordinary values; with getters: true a throwing getter is reported inline as its error rather than propagating.

Changelog

  • PHP v17.3.0, v16.14.0The numericSeparator option was added.
  • PHP v16.18.0maxArrayLength now also applies to Set and Map.
  • PHP v13.13.0, v12.17.0The maxStringLength option was added.
  • PHP v13.0.0Circular references now include a marker pointing at the reference, e.g. <ref *1>.
  • PHP v12.0.0compact defaults to 3 and breakLength defaults to 80, changing multi-line layout.
  • PHP v11.4.0depth went back to a default of 2 after briefly defaulting to 20 in v11.0.0.

util.inspect() produces the string Node itself prints when you console.log() an object. Reaching for it directly matters the moment the defaults get in your way — and the default that bites hardest is depth: 2.

When to reach for it

Use it whenever you need the debug rendering as a value: writing a structured log, embedding an object in an Error message, or snapshotting a value in a test. It also succeeds where JSON.stringify() fails — circular references, Map, Set, BigInt, symbols, class instances, getters and undefined all render instead of throwing or vanishing.

What trips people up

  • [Object] and [Array] are truncation, not a bug. Anything more than two levels deep collapses. Pass { depth: null } to see all of it, or raise util.inspect.defaultOptions.depth once at startup to change it for console.log too.
  • Arrays stop at 100 items and strings at 10 000 characters, with a ... n more items suffix. Raise maxArrayLength and maxStringLength.
  • Output is not stable across values. Line breaks depend on breakLength and compact, and key order follows insertion order. For snapshots pin { depth: null, breakLength: Infinity, sorted: true, colors: false }.
  • It is not a serialiser. The output is for humans; never parse it back.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Log a deeply nested configuration object without it collapsing to [Object].
  • Embed an offending value in an Error message when JSON.stringify would throw on a cycle or a BigInt.
  • Produce a deterministic string form of a value to assert against in a snapshot test.

Frequently asked questions

Why does console.log print [Object] instead of my nested object?

Because `util.inspect()` defaults to `depth: 2` and collapses anything deeper. Log `util.inspect(value, { depth: null })` for that one call, or set `util.inspect.defaultOptions.depth = null` once at startup to change it for every `console.log` in the process.

How do I print an object with circular references in Node?

Use `util.inspect(value, { depth: null })`. It renders cycles as `<ref *1>` and `[Circular *1]` instead of throwing the way `JSON.stringify` does, and it also handles `Map`, `Set`, `BigInt`, symbols and `undefined`, none of which survive JSON.

Why is my array cut off with "... 50 more items"?

`maxArrayLength` defaults to 100. Pass `{ maxArrayLength: null }` (or a larger number) to show every element. The equivalent limit for strings is `maxStringLength`, which defaults to 10000 characters.

More examples

Where JSON.stringify gives up

Every one of these values either throws or silently disappears under `JSON.stringify`: the cycle throws, the BigInt throws, `undefined` and the symbol key are dropped, and the `Set` and `Map` serialise as empty objects. `util.inspect()` renders all of them, tagging the cycle with `<ref *1>` / `[Circular *1]` so you can see where it points back to. This is why debug logging should use `util.inspect()`, not JSON.

Example · javascript
const util = require('node:util');

const node = { name: 'root', tags: new Set(['a', 'b']) };
node.self = node;

const value = {
  node,
  seen: new Map([['k', 1]]),
  big: 9007199254740993n,
  missing: undefined,
  [Symbol('hidden')]: true,
  when: new Date('2020-01-01T00:00:00.000Z'),
};

// JSON.stringify(value) throws:
//   TypeError: Converting circular structure to JSON
//   (and BigInt would throw too)

console.log(util.inspect(value, { depth: null, showHidden: false }));
// <ref *1> {
//   node: { name: 'root', tags: Set(2) { 'a', 'b' }, self: [Circular *1] },
//   seen: Map(1) { 'k' => 1 },
//   big: 9007199254740993n,
//   missing: undefined,
//   when: 2020-01-01T00:00:00.000Z,
//   [Symbol(hidden)]: true
// }

Changing the defaults globally, and a custom renderer

`util.inspect.defaultOptions` is the one-line fix for `[Object]` appearing throughout an application's logs, because `console.log` reads the same defaults. The `util.inspect.custom` symbol lets a domain type present itself readably everywhere it is logged; the third argument passed to it is the `inspect` function itself, so nested values can be rendered with the caller's options. Setting `customInspect: false` bypasses the hook when you need to see the real fields.

Example · javascript
const util = require('node:util');

// Applies to console.log() as well, for the whole process.
util.inspect.defaultOptions.depth = 5;
util.inspect.defaultOptions.maxArrayLength = 200;

console.log({ a: { b: { c: { d: { e: 1 } } } } });
// { a: { b: { c: { d: { e: 1 } } } } }

// A class can decide how it renders.
class Money {
  constructor(cents, currency) {
    this.cents = cents;
    this.currency = currency;
  }

  [util.inspect.custom](depth, options, inspect) {
    const amount = (this.cents / 100).toFixed(2);
    return `Money<${amount} ${this.currency}>`;
  }
}

console.log(util.inspect(new Money(1999, 'EUR'))); // Money<19.99 EUR>
console.log([new Money(500, 'USD')]);              // [ Money<5.00 USD> ]

// Opt out when you want the raw shape back.
console.log(util.inspect(new Money(500, 'USD'), { customInspect: false }));
// Money { cents: 500, currency: 'USD' }

Truncation limits and a stable snapshot form

The default limits are there to stop a stray 10-million-element array from freezing a terminal, and they announce themselves with `... n more items` / `... n more characters` rather than failing quietly. The `SNAPSHOT` options object is the combination worth remembering for tests: `breakLength: Infinity` removes width-dependent line breaks, `sorted: true` removes key-order dependence, and disabling the caps removes length dependence, so the same value always yields the same string.

Example · javascript
const util = require('node:util');

const big = Array.from({ length: 150 }, (_, i) => i);

console.log(util.inspect(big).endsWith('... 50 more items ]')); // true
console.log(util.inspect(big, { maxArrayLength: null }).endsWith('149 ]')); // true

const longString = 'x'.repeat(12000);
console.log(util.inspect(longString).includes('... 2000 more characters')); // true

// A form whose output depends only on the value, not on terminal width
// or key insertion order — safe to assert against in a test.
const SNAPSHOT = {
  depth: null,
  colors: false,
  breakLength: Infinity,
  sorted: true,
  maxArrayLength: null,
  maxStringLength: null,
};

console.log(util.inspect({ z: 1, a: [3, 1, 2] }, SNAPSHOT));
// { a: [ 3, 1, 2 ], z: 1 }

Discussion

  • Be the first to comment on this lesson.