How to find a port on Mac Terminal
You hit npm run dev, see "port 3000 already in use", and now you need to know who's holding it — from the Mac Terminal. Here are the three reliable terminal commands for mapping a port back to a process on macOS, and which one to reach for in which situation.
How do I find a port on Mac Terminal?
Open Terminal (Cmd+Space → "Terminal" → Return) and run a single command:
lsof -nP -iTCP:3000 -sTCP:LISTEN
Replace 3000 with the port you want. The PID column is the process ID. The COMMAND column is the program name. lsof is preinstalled on every macOS version — no Homebrew, no npm install, no setup.
The short answer
In the Mac Terminal, run:
lsof -nP -iTCP:3000 -sTCP:LISTEN
Replace 3000 with the port you care about. The output looks like this:
COMMAND PID USER FD TYPE DEVICE NAME
node 54231 khalouf 23u IPv6 0x... TCP *:3000 (LISTEN)
The PID column (54231 here) is your answer. That's the process holding port 3000.
The longer answer (and why)
1. lsof — the right default
lsof ("list open files") ships with macOS. Despite the name, it lists open everything — files, sockets, pipes, network connections. Sockets are files in Unix, so listening ports show up here.
The flags worth knowing:
-n— don't resolve IPs to hostnames (faster, no DNS).-P— don't translate port numbers to service names (you want3000, nothbci).-iTCP:3000— match TCP traffic on port 3000. Use-iUDP:53for UDP, or-i :3000for both.-sTCP:LISTEN— only show listening sockets (skip established connections).
If you're scripting, -t gives you just the PID:
lsof -ti :3000 # bare PID, suitable for piping
That's the form you'll see in the famous one-liner kill -9 $(lsof -ti :3000).
2. netstat — when lsof is unavailable
netstat on macOS is BSD-flavored and doesn't have the -p flag that Linux users expect. You can list listening sockets with:
netstat -anv -p tcp | grep LISTEN
You won't see process names here, but you'll see every listening port at once — useful when you don't yet know which port is in question.
To go from a port back to a PID, fall back to lsof. There's no good native way to do it with netstat alone on macOS.
3. ss — note: not on macOS
If you're coming from Linux, you might be reaching for ss -ltnp. Don't. ss isn't installed on macOS by default and isn't worth installing — lsof already does the job. (You can brew install iproute2mac if muscle memory demands it, but it's a wrapper.)
4. The Activity Monitor route
Activity Monitor (Cmd+Space → "Activity Monitor") lets you see all running processes with a Network tab. It's good for confirming what a PID corresponds to, but it doesn't let you query by port. You still need lsof first to find the PID, then Activity Monitor to inspect it.
Common gotchas
Empty output
If lsof -i :3000 returns nothing, three things to check:
- Is the server actually running? Check with
ps aux | grep node(or whatever runtime you're using). - Is it listening on TCP, not UDP? Try
lsof -i :3000without theTCPqualifier. - Was it started under another user? If
sudo, you may needsudo lsof -i :3000to see it.
Multiple PIDs
If lsof returns several rows for one port, you're usually looking at a parent + child (e.g. a Node cluster, or a webpack-dev-server that forked workers). The first PID is typically the one you want; the rest die with it on signal.
IPv6 vs IPv4
macOS prefers IPv6. A server bound to :: shows up under TYPE IPv6. lsof -iTCP:3000 matches both, so this is rarely a problem — but if you're seeing the port in a browser and not in lsof, double-check you're not filtering one family out.
Once you have the PID
What you do next depends on intent:
- Just want to free the port? Send SIGTERM first:
kill <PID>. If it ignores you, escalate:kill -9 <PID>. (Why not always-9? See our post on EADDRINUSE.) - Want to know what it is?
ps -o pid,ppid,command -p <PID>shows the full command line and parent. - Want to share it publicly? See free ngrok alternatives for tunneling localhost ports.
One-liners worth saving
# Who has port 3000?
lsof -nP -iTCP:3000 -sTCP:LISTEN
# Bare PID (for scripting)
lsof -ti :3000
# All listening TCP ports on the machine, sorted
lsof -nP -iTCP -sTCP:LISTEN | tail -n +2 | sort
# Kill whoever has port 3000 (gracefully, then forcefully)
PID=$(lsof -ti :3000) && kill $PID; sleep 2; kill -9 $PID 2>/dev/null