Illustration showing JavaScript console log statements

JavaScript developers are familiar with the humble console.log() function. Although console logging may appear straightforward, there’s much more available within the console object. Let’s look at how you can enhance your log messages with advanced formatting.

The Basics

Let’s recap the most-used console functions:

  • console.log(data, ...args) – Logs data to the console. Any other arguments passed will also be emitted on the same line.
  •, ...args) – Equivalent to console.log() but normally with emphasised formatting – Chrome, for example, adds a blue background and an information “i” icon.
  • console.error(data ...args) – The same as console.log(), except the output is directed to the stderr (error) stream. Most browsers automatically format the output with a red background to convey that an error occurred.
  • console.warn(data, ...args) – The same as console.error(), except a yellow background is normally applied to indicate the less severe warning status.

image of JavaScript browser console logs

Format Specifiers

Developers usually only pass a single argument to the above commands. Nonetheless, they all accept multiple arguments, which are automatically concatenated in the final output.

You can also use arguments with printf-compatible format specifiers defined by a string in data:

const value = 10;
const available = "available";
console.log("There are %d options", value, available);
// Logs "There are 10 options available"

The available format specifiers are as follows:

  • %s – Format as a string.
  • %i – Format as an integer.
  • %f – Format as a floating point value.
  • %O – Format as a JavaScript object.
  • %o – Format as a DOM element.
  • %c – Format as a CSS rule, which is applied to the emitted log line.

image of JavaScript format specifiers being used to format an object and DOM element in the browser console

Support for the last two varies by JavaScript engine. They’re available in modern browsers but not necessarily in other execution contexts.

Adding Images

Using the CSS format specifier, it’s possible to include images in console output! This works in browsers but won’t be supported in CLI environments such as Node.js.

const css = [
    "background-image: url(",
    "background-size: cover",
    "height: 100px",
    "padding: 15px",
    "width: 100px"
console.log("%cI'm An Image!", css.join(";"));

image of browser console log with an image

We hijack CSS’ background-image rule to render the image. While it may seem lighthearted, this could have practical use cases if your debugging involves working with images. You can check the images being retrieved without actually emitting them to the page.

Tabulated Output

JavaScript includes built-in support for emitting tabulated data to the console. Use console.table() with an array of uniform objects. The column headers will be determined automatically, based on the properties common to each object.

const objects = [{a: 1, x: "a"}, {a: 2, x: "b"}];

image of tabulated JavaScript console output

This can be extremely useful when you’re working with objects in bulk. Instead of having to iterate an array and call console.log() with each item, just use console.table() and benefit from the automatically formatted output.

Conditional Output

You can use the console.assert() function to condition output on the value of an expression. This reduces the code you need to write compared with prefacing a console.log() with an if statement.

Your message will only be logged if the expression evaluates to false. An expression evaluting to true will result in nothing being emitted.

console.assert(true, "I never appear");
console.assert(false, "I will be logged");

The console.assert() function does not affect runtime. No error will be thrown if the assertion fails; your expression is used solely to determine whether to log to the console.

Message Groups

You can visually group sections of output together with This will apply an automatic indent to subsequent lines using a predefined number of spaces.

image of indented JavaScript console output

To close the group, call console.groupEnd(). This restores the previous indentation.

You may call multiple times before console.groupEnd() to create deeply nested output. console.groupEnd() reverts the indentation by one step at a time, so you’ll need to match the number of group() and groupEnd() calls before you get back to the default level.


Use console.count(label) to create an internal counter with a given name:

// my-counter: 1
// my-counter: 2

This gives you a straightforward way to emit incrementing values. You don’t have to specify a name – the default counter will be used automatically. You can reset counters to 0 using console.countReset(label).


The console has built-in support for operation timing. Elapsed time is measured in milliseconds and emitted in seconds (e.g. “1.234s”); it’s not guaranteed to be high-accuracy.

// ...some time later...
// Emits the elapsed time ("1.234s")

Timers support optional labels in the same way as counters. This lets you manage multiple timers simultaneously when timing different aspects of your code.

Utility Methods

The console object includes several utility methods which help you manage your output.

  • console.clear() – Clears the console of all visible output. The effects will vary by execution environment.
  • console.dir(obj, options) – Emits a list of all the enumerable property/value pairs of the object obj. You can customise the recursion depth using the depth property of the options object.
  • console.trace() – Emits a stack trace to the current point in your code, enabling straightforward debugging of the execution path taken.

There are other non-standardised methods which are engine-dependent. An example is console.profile(), which is widely available but with differing implementations. In browsers, it generally invokes high-accuracy profiling to help you diagnose performance issues.


There’s much more to JavaScript’s console than the basic console.log()! Taking the time to learn the available functions can drastically accelerate debugging, particularly when working with complex objects or fast-moving output.

image of browser console log with CSS applied

The available features do depend on the JavaScript engine you’re working with. Generally, you’ll get the most advanced styling from an up-to-date browser, although Node.js also supports most of the techniques we’ve described here.

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »