How to kill the process on a port on Mac
Two commands. lsof tells you which process is listening on the port, kill stops it. Below: the exact commands for any port, a one-liner, a shell function, and what to do when the process will not die or comes straight back.
Updated . Applies to macOS.
1. Find the process on the port
Replace 3000 with your port. The flags matter: -sTCP:LISTEN shows only the process that owns the port, not clients connected to it, and -nP skips DNS and service-name lookups so the command returns instantly instead of hanging for a few seconds.
lsof -nP -iTCP:3000 -sTCP:LISTENTypical output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 46999 mikko 23u IPv6 0x9c1a3f2e0b4d1c11 0t0 TCP *:3000 (LISTEN)The number you need is in the PID column. COMMAND is truncated to nine characters, which is why a Next.js server shows up as node or next-serv and macOS Control Center as ControlCe.
If nothing is printed, nothing is listening on that port on this Mac. Check the port number, and whether the server is inside a Docker container or on another machine.
2. Stop it
kill without options sends SIGTERM, which asks the process to shut down cleanly. Most dev servers exit within a second.
kill 46999Run the lsof command again. If the process is still there, force it. SIGKILL cannot be caught or ignored, which is also why it should be the second attempt, not the first: the process gets no chance to remove temp files or close connections.
kill -9 46999One line for the impatient
lsof -t prints only the PIDs, so the two steps fold into one. Add -9 to kill only if the polite version did not work.
kill $(lsof -ti tcp:3000 -sTCP:LISTEN)If the port is free, kill complains that it got no arguments. That is harmless.
A shell function for next time
Put this in ~/.zshrc (or ~/.bashrc), open a new terminal, and killport 3000 does the whole thing.
killport() {
local pids
pids=$(lsof -ti "tcp:$1" -sTCP:LISTEN)
if [ -z "$pids" ]; then
echo "nothing is listening on port $1"
return 1
fi
echo "$pids" | xargs kill && echo "stopped $pids on port $1"
}See everything that is listening
Leave out the port to list every TCP listener on the Mac. This is the quickest way to find out which ports your forgotten dev servers, previews and agents are holding.
lsof -nP -iTCP -sTCP:LISTENmacOS ships the BSD netstat, which has no Linux-style -p flag to show the process, so lsof is the tool for this on a Mac.
When it will not die, or comes straight back
"Operation not permitted"
The process belongs to another user or to root. sudo kill <PID> works for your own servers started with sudo. For macOS system services, do not kill them: they are restarted by launchd immediately. Turn the feature off instead. The usual case is ports 5000 and 7000, held by AirPlay Receiver; see port 5000 and 7000 on Mac.
The port is busy again a second later
Something is supervising the process and restarting it: nodemon, pm2, a --watch flag, or the npm run dev parent that spawned the server you just killed. Kill the parent instead. Find it with the parent PID:
ps -o ppid=,command= -p 46999Or stop everything that matches the command line, for example every Next.js dev server on the Mac:
pkill -f "next dev"The owner is Docker
If lsof shows com.docke as the command, a container publishes the port. Killing Docker's proxy does nothing useful; stop the container:
docker ps
docker stop <container>Without the terminal
Activity Monitor can end a process if you already know the PID (type it into the search field), but it cannot tell you which process holds a port. That is the gap Port Monitor fills: it shows the port, the command, the PID and the project folder in one list, and the × button does the SIGTERM-then-SIGKILL sequence above.