Mac localhost guide

How to find the process using a port on Mac

Run lsof against the listening TCP port, inspect the owning PID, ask the process to stop with SIGTERM, and confirm the listener is gone. Use force termination only as a last resort.

  • Published July 10, 2026
  • 8-minute guide
  • Tested on macOS

Quick answer

Find a listener on port 3000

lsof -nP -iTCP:3000 -sTCP:LISTEN

Read the PID from the second column. Inspect it before stopping anything, then send the normal termination signal:

ps -p <PID> -o pid=,ppid=,user=,command=
kill <PID>

Replace <PID> with the number you found. Never paste the angle brackets into the command.

1. Find what is listening on the port

macOS includes lsof, which can list network sockets as well as open files. This form limits the result to TCP listeners on one port:

lsof -nP -iTCP:3000 -sTCP:LISTEN
  • -n skips host-name lookup, which keeps the command quick and the address literal.
  • -P prints port numbers instead of service names.
  • -iTCP:3000 selects TCP sockets on port 3000.
  • -sTCP:LISTEN excludes outbound and established connections.

Change 3000 to the port in your error message. Common development ports include 3000, 5173, 8000, and 8080, but the correct value is always the one your server tried to bind.

2. Read the lsof result before acting

A typical result has columns like these:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    48217 jake   21u  IPv6  ...       0t0  TCP *:3000 (LISTEN)

COMMAND is the executable name, PID is the process identifier, USER is the owner, and NAMEshows the listening address and port. Treat the PID as temporary: processes can exit and macOS can later reuse the same number.

No output usually means there is no matching listener visible to your current user at that moment. It does not prove that every user and privileged process on the Mac is clear.

3. Inspect the owning process

Before terminating a process, confirm that the command and user match the server you intend to stop:

ps -p 48217 -o pid=,ppid=,user=,etime=,command=

This shows the process, its parent PID, owner, elapsed runtime, and full command. The parent can help distinguish a server launched from Terminal, an editor, a package script, or another development tool.

If the result is a system service, a database with active work, a terminal or editor host process, or anything you do not recognize, stop and investigate. Freeing a port is not worth losing unsaved work or corrupting data.

4. Ask the process to stop cleanly

The ordinary kill command sends SIGTERM. This gives a well-behaved server a chance to close sockets and clean up:

kill 48217

Wait a moment, then check the port again. If the process ignores SIGTERM, inspect it once more and use the server’s own shutdown command when one exists. Only as a final escalation should you send SIGKILL:

kill -KILL 48217

SIGKILL cannot be caught or cleaned up by the target process. Do not make it the default response to a port conflict, and do not add sudo merely to force a result.

5. Verify the port is free

Repeat the original query:

lsof -nP -iTCP:3000 -sTCP:LISTEN

If the command returns no rows, the listening TCP socket is gone. Restart your intended server and confirm that the new PID now owns the port.

Why “port already in use” can come back

Errors such as EADDRINUSE mean the requested address and port could not be bound. If the error returns after you stop one process, check for these causes:

  • A watcher, package runner, or process manager automatically restarted it.
  • A second worker or supervisor is listening on the same logical service.
  • You checked TCP while the application error concerns a different protocol.
  • The listener belongs to another user or root and is not visible normally.
  • The app is trying to bind a different interface or port than you assumed.

To list all listening TCP sockets visible to you, remove the single-port filter:

lsof -nP -iTCP -sTCP:LISTEN

What localhost and all-interfaces bindings mean

A listener on 127.0.0.1 or ::1 is bound to the loopback interface: it is intended for connections originating on the same Mac. A listener shown as *, 0.0.0.0, or :: is bound to all interfaces. That is reachability context, not proof that a service is exposed to the internet; firewall, router, and network configuration still matter.

Where Portsmith fits

Portsmith makes the common same-user TCP workflow visual. It maintains a deduplicated menu-bar list, puts the process and port on one row, adds runtime, framework, host, project, and best-effort coding-agent context when available, and places Open, Copy, Focus, and confirmed termination actions beside the listener.

It is not a complete replacement for lsof. Portsmith does not inspect arbitrary files, UDP, remote hosts, root or other-user listeners, every network connection, or the inside of a container. Its advantage is a calmer, safer path through the local dev-server problem it is designed to solve.

Common questions

Can I kill whatever is using a port in one command?

You can compose commands that do that, but identifying and inspecting the PID first is safer. A one-liner can target the wrong process when assumptions about protocol, ownership, or process lifetime are wrong.

Why not start with kill -9?

SIGKILL gives the process no opportunity to close files, flush data, release other resources, or run shutdown handlers. Start with SIGTERM or the server’s own stop command.

Does this find UDP ports too?

No. The commands in this guide deliberately select listening TCP sockets. UDP has different semantics and requires a different lsof query.