os.EOL

Holds the platform's end-of-line marker: '\n' on POSIX and '\r\n' on Windows.

Signature
os.EOL
  • Added in Node.js v0.7.8

Return value

stringThe operating system-specific end-of-line marker: '\n' on POSIX and '\r\n' on Windows.

os.EOL is a string constant, not a function — no parentheses. It is '\n' on every POSIX platform and '\r\n' on Windows, resolved when Node starts.

When to reach for it

Writing text a native tool on the same machine will read: a CSV opened in Excel, a log a Windows admin will tail in Notepad, a generated .bat file. In those cases matching the platform convention is the point.

What trips people up

Using it to split input. text.split(os.EOL) is a bug on Linux the moment the file was authored on Windows: the marker is '\n', so every line keeps a trailing '\r' and comparisons like line === 'END' quietly fail. Split on /\r?\n/ instead, which handles both. When parsing, accept either ending; only use os.EOL when producing output.

It is equally wrong for anything with a specified format. HTTP headers require \r\n, and Git, JSON, YAML and most source files want \n everywhere — writing os.EOL into those produces files that differ by platform and churn in diffs. console.log() already appends '\n', not os.EOL, so do not add one.

Example

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

When to use it

  • Join generated CSV or report rows so Windows tools display them correctly
  • Append a line to a plain-text log file the OS's own viewer will open
  • Emit a platform-native shell or batch script from a generator

Frequently asked questions

Should I split file contents on os.EOL?

No. Split on /\r?\n/ so the code handles both CRLF and LF input, because os.EOL reflects the machine running Node rather than the machine that wrote the file. Reserve os.EOL for output you are generating for local native tools.

Is os.EOL a function or a property?

It is a string property, so write os.EOL with no parentheses. Calling os.EOL() throws a TypeError saying it is not a function, which is the most common mistake given every other os export is callable.

Does console.log use os.EOL?

No, console.log always appends '\n' even on Windows, and the terminal renders it correctly. Adding os.EOL yourself produces a blank line on POSIX and a stray carriage return plus blank line on Windows.

More examples

Why splitting on os.EOL breaks

On POSIX, os.EOL is '\n', so the first split leaves a trailing \r on every line — invisible in most terminals but fatal to any equality check or Number() conversion. The regex split produces clean fields, which is why parsers should always accept both endings regardless of the host platform.

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

// A file authored on Windows, being read on Linux.
const crlfText = 'id,name\r\n1,ada\r\n2,alan\r\n';

const wrong = crlfText.split(os.EOL).filter(Boolean);
const right = crlfText.split(/\r?\n/).filter(Boolean);

console.log('split on os.EOL:', JSON.stringify(wrong));
console.log('split on /\\r?\\n/:', JSON.stringify(right));
console.log('stray carriage returns:', wrong.some((l) => l.endsWith('\r')));
console.log('last field compares equal:', right.at(-1).split(',')[1] === 'alan');

Write a CSV the platform's tools will open

The byte count is the visible difference: the same rows occupy three more bytes on Windows because each CRLF is two bytes. Writing with os.EOL is right here because a spreadsheet on that machine reads the file, while the read-back check still uses the tolerant regex.

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

const rows = [
  ['id', 'name', 'score'],
  [1, 'ada', 99],
  [2, 'alan', 97]
];

const csv = rows.map((r) => r.join(',')).join(os.EOL) + os.EOL;
const file = './report.csv';
fs.writeFileSync(file, csv);

const bytes = fs.statSync(file).size;
console.log('bytes written:', bytes);
console.log('ends with a terminator:', csv.endsWith(os.EOL));
console.log('data rows:', csv.split(/\r?\n/).filter(Boolean).length - 1);

fs.rmSync(file);

When NOT to use os.EOL

Every line here is a place where the platform constant would be wrong: protocols pin CRLF, structured formats and version-controlled files want plain \n, and console.log already terminates with \n so adding os.EOL yields a blank line on POSIX and a stray \r\n\n on Windows.

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

// HTTP requires CRLF regardless of platform.
const headers = ['GET / HTTP/1.1', 'Host: example.com', ''].join('\r\n');
console.log('http uses literal CRLF:', JSON.stringify(headers.slice(-4)));

// JSON, YAML and source files should use \n everywhere so diffs stay stable.
const json = JSON.stringify({ a: 1, b: 2 }, null, 2);
console.log('JSON.stringify newline:', JSON.stringify(json.slice(1, 2)));
console.log('contains CR:', json.includes('\r'));

// console.log appends \n, not os.EOL.
process.stdout.write('written with an explicit newline\n');
console.log('os.EOL here:', JSON.stringify(os.EOL));

Discussion

  • Be the first to comment on this lesson.