process.platform

Identifies the operating system the Node.js binary was built for, such as 'linux', 'darwin' or 'win32'.

Signature
process.platform
  • Added in Node.js v0.1.16

Return value

stringOne of 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos' or 'win32'; 'android' is also possible for experimental Android builds.

process.platform is a string naming the operating system the running Node binary was compiled for. The documented values are 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos' and 'win32', plus 'android' for experimental Android builds.

When to reach for it

Branch on it when the difference is genuinely at the OS level: where user configuration lives, which system binary to invoke, whether a test that depends on file permissions can run at all, or which prebuilt native asset to download.

What trips people up

  • The names are historical. macOS is 'darwin', not 'macos' or 'osx'. Windows is 'win32' on 64-bit machines too — the string describes the API family, not the word size. Check process.arch for that.
  • It is not a capability test. Branching on the platform to guess whether a feature exists is fragile; prefer testing for the feature. Reach for path.sep, path.delimiter and os.tmpdir() rather than assembling paths by hand from a platform check.
  • Linux is not one thing. Alpine, glibc distributions and WSL all report 'linux' while differing in ways that break native modules.

os.platform() returns the same value; the property just avoids the module import.

Example

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

When to use it

  • Choose the per-user configuration directory: AppData on Windows, Library/Application Support on macOS, XDG paths on Linux.
  • Skip a test that relies on POSIX file permissions when running on Windows.
  • Pick the right prebuilt binary or shell to invoke for the host system.
  • Print the platform in a bug report template so issues can be reproduced.

Frequently asked questions

What value does process.platform return on macOS?

'darwin', after the Darwin kernel — never 'macos' or 'osx'. The documented set is 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos' and 'win32', with 'android' possible for experimental builds.

How do I check if Node is running on Windows?

Compare `process.platform === 'win32'`, which is correct on both 32-bit and 64-bit Windows because the string names the API family rather than the word size. Use process.arch if you need to know whether the build is 64-bit.

What is the difference between process.platform and os.platform()?

Nothing — os.platform() returns the same string, so the property simply saves importing the os module. Both report the platform the Node binary was compiled for, which under emulation may differ from the hardware underneath.

More examples

Locating the per-user config directory

The three commented outputs show the same call producing the conventional location on each system. The `default` branch covers Linux and the BSDs together, which is deliberate: they share the XDG convention, and listing every platform name explicitly would break the first time the code meets 'freebsd' or 'sunos'. Note the environment variables take priority, so a user who has set XDG_CONFIG_HOME is respected.

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

function configDir(appName) {
  switch (process.platform) {
    case 'win32':
      return path.join(process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming'), appName);
    case 'darwin':
      return path.join(os.homedir(), 'Library', 'Application Support', appName);
    default:
      return path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config'), appName);
  }
}

console.log(configDir('my-cli'));
// Windows: C:\Users\ada\AppData\Roaming\my-cli
// macOS  : /Users/ada/Library/Application Support/my-cli
// Linux  : /home/ada/.config/my-cli

Guarding a POSIX-only test

The output shows the same test reported as passing on POSIX systems and as an annotated skip on Windows. That distinction matters in CI: a skip with a stated reason still shows in the report, whereas wrapping the body in `if (process.platform !== 'win32')` would make the test appear to pass on Windows while asserting nothing at all.

Example · javascript
const fs = require('node:fs');
const { test } = require('node:test');
const assert = require('node:assert');

test('secrets file is not world-readable', { skip: process.platform === 'win32' && 'POSIX permissions only' }, () => {
  fs.writeFileSync('secret.tmp', 'token', { mode: 0o600 });
  const mode = fs.statSync('secret.tmp').mode & 0o777;
  fs.unlinkSync('secret.tmp');
  assert.strictEqual(mode, 0o600);
});
// On Linux/macOS: ok 1 - secrets file is not world-readable
// On Windows    : ok 1 - secrets file is not world-readable # SKIP POSIX permissions only

Discussion

  • Be the first to comment on this lesson.