console
console is a global object in Node.js that provides output to the terminal, display of debug information, timer measurements, and more. It shares the same API as the browser DevTools console, but has some Node.js-specific behaviors.
Key Methods
| Method | Overview |
|---|---|
| console.log() | Outputs to standard output (stdout). The most commonly used method. |
| console.error() | Outputs to standard error (stderr). Used for error messages. |
| console.warn() | Outputs a warning to standard error (stderr). In Node.js, the destination is the same as console.error. |
| console.info() | Outputs to standard output (stdout). Behaves the same as console.log. |
| console.table() | Outputs arrays or objects in table format. Useful for visually reviewing data. |
| console.dir(obj, options) | Outputs an object in util.inspect format. Used for debugging deeply nested objects. |
| console.time(label) | Starts a labeled timer. Used together with console.timeEnd(). |
| console.timeEnd(label) | Ends a labeled timer and outputs the elapsed time in ms. |
| console.timeLog(label) | Outputs the current elapsed time without stopping the timer. |
| console.trace() | Outputs the current stack trace. Used to inspect the call chain of a function. |
| console.count(label) | Counts and outputs how many times the same label has been called. |
| console.countReset(label) | Resets the count for the specified label. |
| console.group(label) | Indents subsequent output. Returns with console.groupEnd(). |
| console.groupEnd() | Removes one level of indentation set by console.group(). |
| console.assert(condition, msg) | Outputs an error message if the condition is false. Useful for test-like checks. |
| console.clear() | Clears the terminal (if the terminal supports it). |
console.log, console.error, and console.warn
These are the most basic methods. console.log writes to standard output (stdout), while console.error and console.warn write to standard error (stderr). This distinction matters when using redirects (> or 2>) in the shell.
basic_output.js
// console.log: standard output (stdout)
console.log('Kiryu Kazuma returned to Kamurocho.');
// Multiple arguments are output separated by spaces
console.log('Name:', 'Kiryu Kazuma', '/ Affiliation:', 'Dojima Family');
// Objects can be passed directly (converted with util.inspect)
var profile = { name: 'Kiryu Kazuma', age: 37, title: 'Dragon of Dojima' };
console.log('Profile:', profile);
// Format string (printf-style)
console.log('%s has a combat rating of %d.', 'Majima Goro', 9800);
// console.error: standard error (stderr)
console.error('[ERROR] File not found: kiryu_data.json');
// console.warn: standard error (stderr) — same destination as console.error in Node.js
console.warn('[WARN] Memory usage has exceeded 90%.');
// console.info: standard output (stdout) — same behavior as console.log
console.info('[INFO] Server has started.');
node basic_output.js
Kiryu Kazuma returned to Kamurocho.
Name: Kiryu Kazuma / Affiliation: Dojima Family
Profile: { name: 'Kiryu Kazuma', age: 37, title: 'Dragon of Dojima' }
Majima Goro has a combat rating of 9800.
[ERROR] File not found: kiryu_data.json
[WARN] Memory usage has exceeded 90%.
[INFO] Server has started.
Separating standard output and standard error lets you redirect normal output and errors to different files when running commands in the shell — for example, node app.js > out.log 2> err.log.
console.table — Tabular Output
Outputs arrays or arrays of objects in table format. Useful when you want to review data at a glance.
table_example.js
// Display an array of objects as a table
var fighters = [
{ name: 'Kiryu Kazuma', age: 37, style: 'Brawler' },
{ name: 'Majima Goro', age: 39, style: 'Mad Dog' },
{ name: 'Kasuga Ichiban', age: 42, style: 'Hero' },
{ name: 'Nishikiyama Akira', age: 27, style: 'Nishikiyama Family Boss' },
{ name: 'Sawamura Haruka', age: 20, style: 'Civilian' },
];
console.table(fighters);
// Display only specific columns (pass an array of column names as the second argument)
console.log('\nName and style only:');
console.table(fighters, ['name', 'style']);
// A plain array can also be displayed as a table
var scores = [850, 720, 690, 940, 510];
console.log('\nScore list:');
console.table(scores);
node table_example.js ┌─────────┬────────────────────────┬─────┬────────────────────────┐ │ (index) │ name │ age │ style │ ├─────────┼────────────────────────┼─────┼────────────────────────┤ │ 0 │ 'Kiryu Kazuma' │ 37 │ 'Brawler' │ │ 1 │ 'Majima Goro' │ 39 │ 'Mad Dog' │ │ 2 │ 'Kasuga Ichiban' │ 42 │ 'Hero' │ │ 3 │ 'Nishikiyama Akira' │ 27 │ 'Nishikiyama Family Boss' │ │ 4 │ 'Sawamura Haruka' │ 20 │ 'Civilian' │ └─────────┴────────────────────────┴─────┴────────────────────────┘ Name and style only: ┌─────────┬────────────────────────┬────────────────────────┐ │ (index) │ name │ style │ ├─────────┼────────────────────────┼────────────────────────┤ │ 0 │ 'Kiryu Kazuma' │ 'Brawler' │ │ 1 │ 'Majima Goro' │ 'Mad Dog' │ │ 2 │ 'Kasuga Ichiban' │ 'Hero' │ │ 3 │ 'Nishikiyama Akira' │ 'Nishikiyama Family Boss' │ │ 4 │ 'Sawamura Haruka' │ 'Civilian' │ └─────────┴────────────────────────┴────────────────────────┘
console.time, console.timeEnd, and console.timeLog
A timer feature for measuring how long a process takes. Multiple timers can be managed simultaneously using labels.
timer_example.js
// Start timers
console.time('total time');
console.time('data preparation');
// Simulate data preparation
var data = [];
for (var i = 0; i < 100000; i++) {
data.push({ id: i, value: Math.random() });
}
console.timeEnd('data preparation'); // data preparation: X.Xms
// Record an intermediate checkpoint (timer keeps running)
console.time('sort');
data.sort(function(a, b) { return a.value - b.value; });
console.timeLog('total time', '(sort complete)');
console.timeEnd('sort');
// Simulate filtering
console.time('filter');
var filtered = data.filter(function(item) { return item.value > 0.5; });
console.timeEnd('filter');
// Measure total time
console.timeEnd('total time');
console.log('Filtered item count:', filtered.length);
console.log('[Majima Goro] All done, yeah!');
node timer_example.js data preparation: 8.231ms total time: 18.445ms (sort complete) sort: 12.108ms filter: 2.334ms total time: 22.891ms Filtered item count: 49987 [Majima Goro] All done, yeah!
console.dir — Detailed Object Inspection
console.dir() outputs an object converted with util.inspect. Unlike console.log, it also shows method (function property) values and lets you control the expansion depth with the depth option.
dir_example.js
var profile = {
name: 'Kasuga Ichiban',
job: 'Hero (self-proclaimed)',
party: ['Kiryu Kazuma', 'Sawamura Haruka', 'Nishikiyama Akira'],
stats: {
level: 99,
hp: 9999,
mp: 999,
},
greet: function() {
return "Yo, Kasuga Ichiban here!";
},
};
// console.log shows functions as [Function: greet] by default
console.log('console.log:');
console.log(profile);
// console.dir shows function presence and lets you control depth
console.log('\nconsole.dir:');
console.dir(profile, { depth: 2, colors: true });
// Expand a deeply nested object
var deep = { a: { b: { c: { d: { name: 'Nishikiyama Akira' } } } } };
console.log('\ndepth: 1');
console.dir(deep, { depth: 1 });
console.log('\ndepth: 4');
console.dir(deep, { depth: 4 });
node dir_example.js
console.log:
{
name: 'Kasuga Ichiban',
job: 'Hero (self-proclaimed)',
party: [ 'Kiryu Kazuma', 'Sawamura Haruka', 'Nishikiyama Akira' ],
stats: { level: 99, hp: 9999, mp: 999 },
greet: [Function: greet]
}
console.dir:
{
name: 'Kasuga Ichiban',
job: 'Hero (self-proclaimed)',
party: [ 'Kiryu Kazuma', 'Sawamura Haruka', 'Nishikiyama Akira' ],
stats: { level: 99, hp: 9999, mp: 999 },
greet: [Function: greet]
}
depth: 1
{ a: { b: [Object] } }
depth: 4
{ a: { b: { c: { d: [Object] } } } }
console.trace — Display a Stack Trace
console.trace() outputs the current stack trace (the chain of function calls) to stderr. Use it when you want to trace where a function was called from.
trace_example.js
function kiryu() {
console.trace('Kiryu Kazuma was called'); // Output a stack trace
}
function majima() {
kiryu(); // Calls kiryu
}
function yakuzaBoss() {
majima(); // Calls majima
}
yakuzaBoss();
node trace_example.js
Trace: Kiryu Kazuma was called
at kiryu (/path/to/trace_example.js:2:13)
at majima (/path/to/trace_example.js:6:5)
at yakuzaBoss (/path/to/trace_example.js:10:5)
at Object.<anonymous> (/path/to/trace_example.js:13:1)
at Module._compile (node:internal/modules/cjs/loader:1376:14)
console.count and console.group
console.count() counts and outputs how many times the same label has been called. console.group() indents output and groups it visually.
count_group.js
// console.count: count how many times each label is called
var events = ['attack', 'defend', 'attack', 'dodge', 'attack', 'defend', 'attack'];
events.forEach(function(event) {
console.count(event);
});
// Reset a counter
console.countReset('attack');
console.count('attack'); // After reset, starts from attack: 1
// console.group: indent and group output
console.group('Dojima Family — Member Info');
console.log('Boss: Kiryu Kazuma');
console.log('Combat rating: S');
console.group('Direct subordinates');
console.log('Majima Goro (Majima Family boss)');
console.log('Nishikiyama Akira (Nishikiyama Family boss)');
console.groupEnd(); // Close the subordinates group
console.log('Affiliated organizations: multiple');
console.groupEnd(); // Close the Dojima Family group
// console.assert: only outputs when the condition is false
var hp = 100;
console.assert(hp > 0, 'Kasuga HP is 0 or below!'); // No output (condition is true)
console.assert(hp > 200, 'Kasuga HP is 200 or below!'); // Output (condition is false)
node count_group.js
attack: 1
defend: 1
attack: 2
dodge: 1
attack: 3
defend: 2
attack: 4
attack: 1
Dojima Family — Member Info
Boss: Kiryu Kazuma
Combat rating: S
Direct subordinates
Majima Goro (Majima Family boss)
Nishikiyama Akira (Nishikiyama Family boss)
Affiliated organizations: multiple
Assertion failed: Kasuga HP is 200 or below!
The Console Class — Custom Output Destinations
Node.js provides a Console class that lets you change the output destination to any stream. Use it when you want to write logs to a file.
custom_console.js
var fs = require('fs');
var Console = require('console').Console;
// Create a custom console that writes to log files
var outStream = fs.createWriteStream('yakuza.log');
var errStream = fs.createWriteStream('yakuza_error.log');
var logger = new Console({
stdout: outStream,
stderr: errStream,
});
// logger uses the same API as console (output goes to the files)
logger.log('[INFO] Kiryu Kazuma has returned to Kamurocho.');
logger.log('[INFO] Contact confirmed with Majima Goro.');
logger.error('[ERROR] Nishikiyama Akira whereabouts unknown.');
logger.table([
{ name: 'Kiryu Kazuma', status: 'active' },
{ name: 'Majima Goro', status: 'missing' },
]);
console.log('Logs written to yakuza.log and yakuza_error.log.');
node custom_console.js Logs written to yakuza.log and yakuza_error.log.
Overview
Node.js's console object shares nearly the same interface as the browser Console API. One important distinction is that console.log writes to standard output, while console.error and console.warn write to standard error. This affects output routing when using shell redirects.
For performance measurement, combine console.time and console.timeEnd. When inspecting complex objects, the depth option of console.dir is useful. console.table presents array data in a readable table format.
To write output to a file, use the Console class. In production, more feature-rich logging libraries such as Winston or Pino are also used, but they are built on the same mechanism as the Console class.
Common Mistakes
Common Mistake 1: Leaving console.log in production code
Leaving debug-time console.log calls in production causes performance degradation and security issues. Every console.log call has a cost, and a large volume of log output increases I/O load. There is also the risk that internal data such as passwords, API keys, or user data gets written to logs.
// NG: debug logs left in production code
function processOrder(order) {
console.log('Order data:', order); // User data ends up in logs
console.log('API key:', process.env.API_KEY); // Sensitive data is logged
var result = doSomething(order);
console.log('Result:', result);
return result;
}
Control output level with an environment variable, or use a logging library such as Winston or Pino:
// OK: control debug output with an environment variable
var isDev = process.env.NODE_ENV !== 'production';
function processOrder(order) {
if (isDev) {
console.log('Order data:', order); // Only output in development
}
var result = doSomething(order);
// When logging in production, keep content minimal (no sensitive data)
console.log('Order processed: orderID=' + order.id);
return result;
}
Common Mistake 2: Mismatched labels between console.time and console.timeEnd
console.time() and console.timeEnd() are paired by the same label string. If the labels differ, the timer is never stopped and a "No such label" warning appears. Watch out for typos and case differences.
// NG: labels do not match
console.time('data load');
var data = loadData();
// Spelling differs ('data load' vs 'data load ')
console.timeEnd('data load '); // Trailing space
// Warning: No such label 'data load ' for console.timeEnd()
// OK: use the same label string (storing it in a constant prevents typos) var LABEL = 'data load'; console.time(LABEL); var data = loadData(); console.timeEnd(LABEL); // References the same constant
Common Mistake 3: Passing a circular-reference object to console.log
When an object contains a circular reference to itself, console.log displays the circular part as [Circular *1]. This is not an error on its own, but passing such an object to JSON.stringify() throws an exception.
// Example of an object with a circular reference
var kiryu = { name: 'Kiryu Kazuma' };
var majima = { name: 'Majima Goro' };
kiryu.partner = majima;
majima.partner = kiryu; // kiryu → majima → kiryu cycle
// console.log displays [Circular *1] (no error)
console.log(kiryu);
// <ref *1> { name: 'Kiryu Kazuma', partner: { name: 'Majima Goro', partner: [Circular *1] } }
// NG: JSON.stringify() throws on circular references
try {
var json = JSON.stringify(kiryu);
} catch (err) {
console.error(err.message);
// TypeError: Converting circular structure to JSON
}
When converting an object with circular references to JSON, use a replacer function to skip the circular parts:
// OK: use a replacer to skip circular references
function safeStringify(obj) {
var seen = [];
return JSON.stringify(obj, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.indexOf(value) !== -1) {
return '[Circular]'; // Skip circular reference
}
seen.push(value);
}
return value;
});
}
console.log(safeStringify(kiryu));
// {"name":"Kiryu Kazuma","partner":{"name":"Majima Goro","partner":"[Circular]"}}
If you find any errors or copyright issues, please contact us.