Platter Join the Waitlist

lsof for ports on macOS

lsof (“list open files”) ships with macOS and is the quickest way to see which process has a port. It needs the right flags to give you a straight answer.

The command

lsof -nP -iTCP:3000 -sTCP:LISTEN
FlagWhat it does
-iTCP:3000Only TCP sockets on port 3000
-sTCP:LISTENOnly sockets in the LISTEN state: servers, not connections
-nDon’t look up hostnames (faster, and shows real addresses)
-PDon’t turn port numbers into service names
-tPrint only PIDs, for use in scripts

Why -P matters

Without it, lsof swaps port numbers for names from /etc/services. On a Mac, lsof -i :4321 showed a server as TCP *:rwhois (LISTEN); the same server with -nP showed TCP *:4321 (LISTEN). If you’re hunting for a port number, ask for numbers.

Why -sTCP:LISTEN matters

-i tcp:3000 matches any socket whose local or remote port is 3000, so a browser tab connected to your server shows up as well as the server. In our test, with one server and one connected client, plain lsof -ti tcp:PORT returned two PIDs and lsof -nP -iTCP:PORT -sTCP:LISTEN -t returned one. If you feed the result into kill, that difference matters.

Reading the result

The NAME column tells you where the server is listening. *:3000 means every address; 127.0.0.1:3000 or [::1]:3000 means this Mac only, over IPv4 or IPv6. The same port can be held twice, once on each, by two different processes: we saw a Node app on [::1]:4321 and a Python server on *:4321 side by side. That’s also how “it’s running but I get the wrong app” happens.

Everything that’s listening

lsof -nP -iTCP -sTCP:LISTEN

Drop the port to list every listening socket on the Mac. Expect some system processes in there: ControlCe on 5000 and 7000 is AirPlay Receiver, for example. To stop one of your own, see how to kill a process on a port on Mac.