Installing Node.js and npm (Node Package Manager) on your Mac is super simple. With these tools, you can manage Javascript packages, create powerful web applications, and dive deep into modern web development. Start by following these steps:
Step 1: Verify that npm is installed#
Open your terminal and type
node -v
npm -v- If you see version numbers (e.g.,
v16.13.0for Node.js and8.1.0for npm), they’re already installed. - If you see errors or no versions, continue to the next step.
Step 2: Install Node.js (includes npm)#
The easiest way to install Node.js and npm is by using Homebrew. If you don’t have Homebrew installed, install it first.
Then run:
brew install nodeStep 3: Verify the Installation#
After the installation completes, type the following command to check the versions and ensure everything is installed properly:
node -v
npm -vYou should see version numbers for both. 🎉
Step 4: Update npm (Optional)#
npm updates frequently, so ensure you have the latest version:
npm install -g npm@latest🎉 You’re all set! Now, you can use Node.js and npm to manage and build amazing projects. Happy coding! 😊
Why Use Node.js and npm?
- Fast & Scalable: Node.js enables fast, scalable network applications with non-blocking I/O.
- Massive Ecosystem: npm offers access to over 1 million open-source packages.
- Cross-Platform: Develop once and deploy anywhere.
These tools are essential for any web developer aiming to build modern, high-performance applications.
Hold on — why didn’t we install npm? 🤔#
Because you can’t, and you don’t need to. npm ships inside Node.js. One download, two commands on your machine. That’s why Step 2 only installs node and Step 3 checks both versions.
The two do completely different jobs, which is worth getting straight early:
- Node.js is the runtime. It’s the thing that runs your Javascript outside a browser.
- npm is the package manager. It downloads other people’s code into
node_modulesand records it in yourpackage.json.
There’s a third command you also just got for free: npx, which runs a package without installing it. npx create-next-app@latest is the everyday example — you use it once and you don’t want it living on your machine forever.
The mistake almost everyone makes: brew install node isn’t the LTS 😬#
This one bites people weeks later, so it’s worth thirty seconds now.
The Homebrew formula called node tracks the newest Node release, not the Long Term Support one. Node’s release policy is that even-numbered major versions become LTS and odd-numbered versions never do — so depending on the month, plain brew install node can hand you a release that hosting providers and CI images don’t support yet.
Check what you got:
node -vIf that’s an odd major number (or just newer than you want), install a specific line instead:
brew install node@22The versioned formulas are keg-only, which is Homebrew’s way of saying “installed, but deliberately not wired into your PATH”, so two Node versions can coexist without fighting. Homebrew prints the exact export PATH line to add to your ~/.zshrc when the install finishes — read that output instead of guessing, because the path differs between Apple Silicon (/opt/homebrew) and Intel (/usr/local) Macs.
If you juggle Node versions per project all day, a version manager like nvm or fnm is the better tool and Homebrew is the wrong one. If you have one machine and one Node, Homebrew is genuinely fine.
“zsh: command not found: npm” after a successful install#
The install worked. Your shell just doesn’t know where to look yet.
First, find out what your shell is actually finding:
which -a node
brew --prefixNearly every time, it’s one of three things:
- You never opened a new terminal.
PATHis read when the shell starts. Quit Terminal and reopen it, or runsource ~/.zshrc. - You’re on an Apple Silicon Mac and Homebrew isn’t on your
PATHat all. Homebrew installs to/opt/homebrewon M-series Macs, and older setup guides written for Intel Macs point at/usr/local. Ifbrew --prefixsays/opt/homebrewbut nothing from Homebrew works, this is your problem — our Homebrew install guide has the shell config step. - You installed a keg-only version like
node@22and skipped theexport PATHline.
Never run sudo npm install -g 🚫#
When a global install fails, the first search result always says to put sudo in front of it. Don’t.
The error looks like this:
npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/lib/node_modulessudo does make it go away — by creating root-owned folders inside your npm directory. Every later install as your normal user then fails on those folders, and you’re stuck reaching for sudo forever to dig out of a hole sudo dug.
Installed through Homebrew, you shouldn’t hit this at all: Homebrew’s prefix belongs to your user account, so global installs just work. If you are hitting it, you have a leftover Node from a .pkg installer or an old guide, and the real fix is to remove that one rather than escalate around it.
Frequently asked questions#
How do I update Node.js and npm on a Mac?#
Two separate things. For Node, use Homebrew:
brew update
brew upgrade nodenpm updates on its own schedule, faster than Node does, so bump it directly when you need to:
npm install -g npm@latestDo I need Node.js if I only want npm?#
Yes. npm is written in Javascript and runs on Node — there is no npm without it. That’s also why npm -v and node -v report completely unrelated version numbers.
How do I uninstall Node.js installed with Homebrew?#
brew uninstall nodeIf you previously installed Node from the .pkg file on nodejs.org, Homebrew can’t remove that one — it lives in /usr/local/bin and has to be deleted by hand. Running which -a node will show you every copy on your machine, which is the fastest way to spot a duplicate.
What’s the difference between npm install and npm install -g?#
Without -g, packages land in the node_modules folder of the project you’re standing in, and get written to that project’s package.json. With -g, they install once for your whole user account and become terminal commands. Project dependencies should almost never be global — if you want to know why the --save flag disappeared from that first command, we covered it in do you still need npm install --save?.
Why does npm install create a package-lock.json?#
It records the exact version of every package installed, including your dependencies’ dependencies, so that your teammate and your CI server get byte-for-byte the same tree you did. Commit it. Deleting it to “fix” an install is a habit worth not picking up.
