Sign in with Google

How to Install Node.js (macOS, Windows, Linux)

Pick the right version, install it with a version manager, and understand what npm just did to your folder.

beginner9 min read
dev-setupnode-jsnpmjavascriptdeveloper-tools

You need Node for something specific — a tutorial, a build tool, a job that says "JavaScript" — and the download page immediately asks you to choose between two big green buttons with different version numbers. Then you install it, and six months later a project refuses to build because it wants a Node version you do not have. This guide gets Node and npm working today and sets you up so the second version is a one-line problem instead of a reinstall.
iWhat you need
A terminal you are comfortable opening, about 200 MB of disk space, and administrator rights on the machine. If the command line still feels foreign, read How to Use the Command Line first — everything below happens there.
Node.js is a program that runs JavaScript outside a browser. Before it existed, JavaScript only ran on a web page. Node lets you point it at a file and execute it the same way you would run a Python or Ruby script, which is why it became the engine for servers, command-line tools, and nearly every frontend build step.
npm is the package manager that ships with Node. You do not install it separately, and you should not try to. When you install Node you get three commands: node to run JavaScript, npm to install and manage third-party packages, and npx to run a package once without permanently installing it. Almost every instruction you will read online assumes all three exist.
Node ships two tracks. Active LTS is the boring, supported one — bugfixes and security patches for years, and the version every hosting provider and CI system is tested against. Current gets new language and runtime features first, and also gets breaking changes first.

The version numbers as of July 2026

  1. 1Node 24 is Active LTS, supported until April 2028. This is what you want unless you have a concrete reason otherwise.
  2. 2Node 22 is in Maintenance LTS — still patched, but no longer the recommended default for new work.
  3. 3Node 26 is Current. Install it deliberately, to test something or use a brand-new feature, not as your everyday runtime.
  4. 4Node now cuts one major release per year starting with Node 27, so the treadmill is slower than the old six-month cadence you may have read about.
Even numbers are the LTS ones
Only even-numbered major versions ever become LTS. If a version number is odd, it is a Current release and will never be promoted — useful shorthand when you are staring at a list of available versions.
There are three ways to get Node onto a machine, and they are genuinely different in how much pain they cause later.

The three routes

  1. 1The official installer from nodejs.org. Download, double-click, done. It installs exactly one version, system-wide, and changing versions means downloading a different installer over the top.
  2. 2A system package manager — Homebrew on macOS, winget on Windows, apt on Debian and Ubuntu. Convenient if you already use one, but it ties your Node version to whatever the package maintainers ship, and apt in particular is often badly out of date.
  3. 3A version manager — nvm on macOS and Linux, nvm-windows or fnm on Windows. It installs Node into your home directory and lets you keep several versions side by side, switching per project with one command.
Use a version manager. That is not a stylistic preference — it is because real projects pin Node versions. You will clone a repo that needs Node 20, while the one you are actively working on needs 24, and with a single system-wide install your only option is to uninstall and reinstall each time you switch tasks. A version manager also installs into a directory you own, which quietly eliminates the permissions problem covered further down.
On macOS and Linux, nvm is the standard choice. The install script clones nvm into ~/.nvm and appends two lines to your shell profile — ~/.zshrc on modern macOS, ~/.bashrc on most Linux setups.
macOS
$curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh | bash
Close your terminal and open a new one so the profile is re-read, then confirm nvm is on your PATH with nvm --version. Now install the LTS release and make it your default:
macOS
$nvm install --lts
macOS
$nvm alias default lts/*
On Windows, nvm-windows is a separate project with its own installer, and fnm is the faster modern alternative that works identically across all three operating systems. Install fnm with winget, then add its shell hook to your PowerShell profile.
Windows
$winget install Schniz.fnm
powershell
fnm env --use-on-cd --shell powershell | Out-String | Invoke-Expression

Add this to your PowerShell profile — open it with notepad $PROFILE

!Uninstall the old Node first
If you previously installed Node with the official installer or Homebrew, remove it before installing a version manager. Two installs on the same PATH produce the single most confusing symptom in this whole area: node -v reports a version you did not ask for and no amount of switching changes it.
Two commands prove the install worked. Both should print a version number, and neither should say "command not found".
macOS
$node -v && npm -v
On a fresh Node 24 install you will see something like v24.4.1 and 11.3.0. The npm number is always much lower than the Node number — npm versions independently, and that mismatch confuses people constantly. Now make a project.

Your first project in four commands

  1. 1Make and enter a folder: mkdir hello-node, then cd hello-node.
  2. 2Run npm init -y to create a package.json with sensible defaults. The -y flag skips the interactive questions.
  3. 3Create a file called index.js containing one line: console.log('it runs')
  4. 4Run node index.js and watch it print. That is the whole loop — write a file, hand it to node.
Now add a script. Open package.json and put "start": "node index.js" inside the scripts object, then run npm start. Named scripts are how every real project exposes its commands, so npm run build and npm test work in a codebase you have never seen before.
Install one package — try npm install dayjs — and two things appear. A node_modules folder, which holds the actual downloaded code, and a package-lock.json file, which records the exact version of every package and every package those packages depend on.
The rule that follows from this: commit the lockfile, never commit node_modules. The lockfile is small, meaningful, and the only thing guaranteeing your teammate gets byte-identical dependencies. node_modules is tens of thousands of files that are fully reproducible from the lockfile, and it belongs in .gitignore forever.
That distinction is also the difference between the two install commands. npm install resolves versions and may update the lockfile. npm ci installs strictly what the lockfile says, deletes node_modules first, and fails loudly if the lockfile and package.json disagree. Use install when you are adding a dependency and ci everywhere reproducibility matters, which means every CI pipeline and every deploy.
Some packages are tools rather than libraries. npx runs one without installing it at all — npx create-next-app@latest downloads the tool, runs it once, and leaves nothing behind. For a scaffolding tool you use twice a year, this is strictly better than a global install.
When you do want a tool permanently, npm install -g puts it on your PATH globally. With a system-wide Node install this is where people hit EACCES: permission denied, because the global directory sits somewhere your user account cannot write.
Do not fix EACCES with sudo
Running sudo npm install -g executes an untrusted package's install scripts as root and leaves root-owned files in your cache that break later installs. If you installed Node with nvm or fnm, the global directory is already inside your home folder and this error cannot happen — that alone justifies the version manager.
Create a file called .nvmrc in the project root containing just the version — 24, or lts/* to track whatever the current LTS is. Commit it. Now anyone in the repo can run nvm use with no arguments and land on the right version, and fnm reads the same file.

Day-to-day version switching

  1. 1nvm ls lists every version you have installed and marks the active one with an arrow.
  2. 2nvm install 20 adds another version without touching the one you are using.
  3. 3nvm use 20 switches the current terminal session only. Open a new tab and you are back to your default.
  4. 4nvm alias default 24 changes what every new terminal starts with.
  5. 5fnm with the --use-on-cd hook switches automatically the moment you cd into a folder containing a .nvmrc file.

Symptom, cause, fix

  1. 1command not found: node in a new terminal. The nvm shell lines are missing from the profile your shell actually loads. Check whether you are in zsh or bash with echo $SHELL, then confirm the two nvm lines are in the matching rc file.
  2. 2node -v prints an old version no matter what you switch to. You have a leftover system install ahead of nvm on your PATH. Run which -a node to see every match, then uninstall the one you do not want.
  3. 3EACCES: permission denied during a global install. Node is installed system-wide. Reinstall via nvm or fnm rather than reaching for sudo.
  4. 4npm ci fails with a lockfile-out-of-sync error. Someone edited package.json without running an install. Run npm install once, commit the updated lockfile, and ci will pass again.
  5. 5A project errors on an unsupported engine. Read the engines field in its package.json, install that major version, and switch to it.
  6. 6nvm use says the version is not installed. nvm does not auto-install. Run nvm install with the version number first.
With a runtime in place, the next two pieces of the setup are an editor configured for JavaScript and version control for the project you just made — How to Set Up VS Code and How to Use Git cover both, and the lockfile rule above only matters once Git is in the picture. If you installed via Homebrew and want to understand what it actually did, How to Install and Use Homebrew on a Mac is worth a read. When you are ready to package an app so it runs identically on your laptop and a server, How to Set Up Docker is the natural follow-on. For the full sequence rather than one tool at a time, the Becoming a Software Engineer roadmap puts the runtime, the language, and the fundamentals in the order they build on each other.