Print without a newline in Node.js

Use stdout.write for inline output, update terminal progress safely, and account for redirected output and stream backpressure.

Best practices
Illustration accompanying a Node.js development guide

Use process.stdout.write() when you need output without an automatically appended newline:

process.stdout.write('Hello, ');
process.stdout.write('world!');
process.stdout.write('\n');

Unlike console.log(), write() does not add a line ending. It accepts a string or supported byte data, not console-style formatting arguments. Convert a number with String(value) or interpolate it into a string.

Update a progress line

A carriage return, \r, moves the cursor to the beginning of the current line on a typical terminal. It does not erase text left over from a longer previous message. Node's readline helpers make clearing and repositioning explicit:

// progress.mjs
import { cursorTo, clearLine } from 'node:readline';
import { setTimeout as delay } from 'node:timers/promises';

for (let percent = 0; percent <= 100; percent += 20) {
  const message = `Progress: ${percent}%`;
  if (process.stdout.isTTY) {
    cursorTo(process.stdout, 0);
    clearLine(process.stdout, 0);
    process.stdout.write(message);
  } else {
    process.stdout.write(message + '\n');
  }
  await delay(100);
}
if (process.stdout.isTTY) process.stdout.write('\n');

The TTY check keeps terminal-control sequences out of an ordinary redirected log. Terminal capabilities still vary, including on Windows, so use a terminal-aware progress library when you need richer interaction.

stdout, stderr, and shell redirection

Use process.stderr.write() for diagnostic output that should remain separate from the program's normal result. Both streams follow the destination supplied by the process launcher. For example, node progress.mjs > progress.log sends stdout to a file, where a sequence of plain progress lines is more useful than cursor movement.

console.log() remains convenient for ordinary log lines and object formatting. console.error() writes through stderr. Switching to stdout.write is about controlling output, not a guarantee of better performance.

Backpressure and process exit

For a few short messages, direct writes are straightforward. For sustained output, write() returning false means the producer should wait for the stream's drain event before continuing. Handle stream errors as well; a downstream process may close its pipe early.

Avoid forcing process.exit() immediately after buffered output. Setting process.exitCode and letting the event loop finish gives pending work a chance to complete. This does not protect against abrupt termination or destination errors. stdout and stderr can perform synchronous or asynchronous writes depending on the operating system and destination, so a large volume of output can affect application latency.

See process I/O and readline cursor helpers.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting