How to log an object in Node
By Flavio Copes
Learn how to log a full object in Node.js, getting past the [Object] placeholder after two levels of nesting using JSON.stringify or util.inspect.
To log a deeply nested object in Node, use console.log(JSON.stringify(obj, null, 2)), or raise the inspection depth with the util module. Plain console.log() cuts the output off after two levels of nesting.
Let’s see why.
When you type console.log() into a JavaScript program that runs in the browser, that is going to create a nice entry in the Browser Console:

Once you click the arrow, the log is expanded, and you can clearly see the object properties:

We don’t have such luxury in Node. The object goes to the terminal, or to a log file, as a string. There’s nothing to click and expand.
So Node has to decide how much of the object to print. All is fine until a certain level of nesting. After two levels, Node gives up and prints [Object] as a placeholder:
const obj = {
name: 'Flavio',
age: 35,
person1: {
name: 'Tony',
age: 50,
person2: {
name: 'Albert',
age: 21,
person3: {
name: 'Peter',
age: 23
}
}
}
}
console.log(obj)
prints:
{
name: 'Flavio',
age: 35,
person1: {
name: 'Tony',
age: 50,
person2: { name: 'Albert', age: 21, person3: [Object] }
}
}
Peter is gone. The data is still there, of course. Node just refuses to print it, to keep logs from exploding when objects reference big structures.
How can you print the whole object?
Use JSON.stringify()
The best way to do so, while preserving the pretty print, is to use
console.log(JSON.stringify(obj, null, 2))
where 2 is the number of spaces to use for indentation. Every level gets printed, no matter how deep.
Use util.inspect()
Another option is to raise the depth limit Node uses when formatting objects:
require('util').inspect.defaultOptions.depth = null
console.log(obj)
null means no limit. This changes the default for every console.log() in the program, and you keep Node’s native formatting with colors in the terminal.
If you only want the full depth for one specific log, console.dir() accepts the same option without changing any global:
console.dir(obj, { depth: null })
One thing to watch out for
JSON.stringify() throws when the object contains a circular reference, an object that points back to itself somewhere in the tree:
const invoice = { total: 100 }
invoice.self = invoice
JSON.stringify(invoice)
// TypeError: Converting circular structure to JSON
It also silently drops functions and undefined values. If your object has any of that, use the util.inspect() route instead: it prints circular references as [Circular] without crashing.
Related posts about node: