Guides/What is using port 3000

What is using port 3000 on my Mac, and how do I stop it?

MerdoAI

Maker of Orcylo

  • Published

Quick answer

Run lsof -nP -iTCP:3000 -sTCP:LISTEN in Terminal. It prints the command and PID of whatever is listening on port 3000, usually a dev server you started earlier and forgot. lsof -a -p PID -d cwd shows the folder it was started from, so you know which project it belongs to. Stop it with kill PID, which lets it shut down cleanly, and keep kill -9 for a process that ignores that. If the listener on port 5000 or 7000 is ControlCenter, it is the AirPlay Receiver, which you can turn off in System Settings.

Only one process can listen on a given port and address at a time. When a second server tries, it fails. EADDRINUSE is the name Node.js gives this error: “an attempt to bind a server … failed due to another server on the local system already occupying that address” (Node.js docs). It looks like this:

Error: listen EADDRINUSE: address already in use :::3000

Python on macOS reports the same thing as OSError: [Errno 48] Address already in use. Either way the fix is the same for every language and framework: find the process that holds the port, decide whether you still need it, and stop it. Everything below uses commands that ship with macOS 26, so there is nothing to install.

Find the process using the port

We tested every command here on an M4 Mac mini on 1 October 2026, using a throwaway Node.js server on port 3000. The output shown is from that run, with the user name shortened to dev.

  1. Open Terminal. Press ⌘Space, type Terminal and press Return.

  2. Ask lsof what is listening on the port. Replace 3000 with your port:

    lsof -nP -iTCP:3000 -sTCP:LISTEN

    -iTCP:3000 selects TCP port 3000. -sTCP:LISTEN keeps only the listening socket, meaning the server and not the clients talking to it. -n skips slow host-name lookups and -P prints port numbers instead of service names. Our run printed:

    COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    node    81982 dev        12u  IPv6 0xc1596dfba3cfc841      0t0  TCP *:3000 (LISTEN)

    No output means no process of yours is listening on that port. Add sudo to include processes owned by other users.

  3. Read the line. COMMAND is the program, cut to nine characters (add +c 0 to see full names). PID is the process ID you need for everything else. *:3000 means it accepts connections on every network interface; 127.0.0.1:3000 or [::1]:3000 means only from this Mac.

  4. See the full command. node alone does not say much. This shows the whole command line and how long it has been running:

    ps -o pid,ppid,etime,command -p 81982

    The command line usually names the tool, for example next dev, vite or rails server. ELAPSED tells you whether it is from five minutes ago or last week.

  5. Find the project folder. A process remembers the folder it was started in. That working directory is, for a dev server, almost always the project root:

    lsof -a -p 81982 -d cwd

    lsof -p 81982 | grep cwd gives the same line. Our test server printed the scratch folder we had started it from.

  6. Stop it. If you can find the terminal tab it is running in, press Control-C there. Otherwise run kill 81982, then repeat step 2. When lsof prints nothing, the port is free.

Two shortcuts that can bite

lsof -i :3000 shows more than the server

lsof -i :3000 is the short form many answers suggest, and it works, with three catches. Without -P it prints service names from /etc/services, so in our test port 3000 appeared as *:hbci. Without -n it looks up host names, which can stall. And it lists every connection on the port, not only the listener.

kill $(lsof -ti :3000) can hit your browser

-t prints bare PIDs, which makes a handy one-liner. But without -sTCP:LISTEN it returns every process with a connection on that port. When we connected a client to the test server, lsof -ti :3000 returned two PIDs, the server and the client. On a real Mac that client is often your browser or an editor’s preview. This version only matches the server:

kill $(lsof -t -iTCP:3000 -sTCP:LISTEN)

Activity Monitor cannot answer this question. Its Network tab shows traffic per process, but not port numbers. Its Ports column counts Mach ports, the channels macOS processes use to talk to each other, which is what developers watch when they hunt a port leak (Apple Developer Forums). For network ports, use lsof.

Stop it: kill first, kill -9 last

kill is the command that sends a signal to a process, and by default that signal is TERM, a polite request to exit. A dev server that receives it can close connections, flush logs and stop the processes it started. Give it a few seconds, then check the port again.

kill -9 is the same command with the KILL signal, which the kill manual page describes as “non-catchable, non-ignorable”. The process ends at once and cleans up nothing. That matters for dev servers because many run as a parent and a child: npm run dev starts your framework’s server as a child process. A parent killed with -9 cannot pass anything on, so the child can keep the port, and lsof will show a new PID. Kill that one too, or better, use plain kill from the start.

If USER in the lsof output is root or another account, kill will refuse without sudo. Stop and look first: a root-owned listener is rarely a dev server you forgot.

Common culprits on a Mac

Port Usual owner Default because
3000 Next.js, Rails, many Node.js examples next dev and bin/rails server both default to 3000
5173 Vite Vite’s default dev port; it moves to the next free one if taken
8000 Django, python3 -m http.server Both default to port 8000
5000, 7000 ControlCenter (AirPlay Receiver) macOS uses them for AirPlay
Any published port com.docker.backend Docker Desktop listens for your containers

Sources for the defaults: Next.js CLI, Rails Guides, Vite, Django and Python.

A dev server you forgot

This is the usual answer. A server left running in another terminal tab, in an editor’s built-in terminal, or by an AI coding agent that ran npm run dev and moved on keeps its port until you stop it. Two frameworks soften this. Vite “will automatically try the next available port” unless you set strictPort (Vite), which avoids the error but can leave you with servers on 5173, 5174 and 5175. Next.js 16.2 writes the running dev server’s PID, port and URL to .next/dev/lock, and a second next dev in the same folder prints that PID with a ready-made kill command (Next.js).

Docker containers

When a container publishes a port with -p, it is Docker Desktop’s backend process that listens on your Mac and forwards connections into the Linux VM (Docker docs). So lsof shows com.docker.backend (cut to com.docke unless you add +c 0), not your app. That process serves every published port at once, so killing it is the wrong tool. Find the container instead:

docker ps --format "table {{.Names}}\t{{.Ports}}"

Look for :3000-> in the PORTS column, then run docker stop with that container’s name.

AirPlay Receiver on ports 5000 and 7000

On our Mac, lsof showed ControlCenter listening on both 5000 and 7000, and Apple lists both ports for AirPlay (Apple). This is why flask run, which uses port 5000, so often fails on a Mac; Flask’s own docs point to the AirPlay Receiver setting (Flask). On macOS 26, choose Apple menu > System Settings > General > AirDrop & Continuity and turn off AirPlay Receiver (Apple, macOS 26), or start Flask with flask run --port 5001.

Keep it from happening again

  • Give each project its own port. Set it in the dev script, for example next dev -p 3001, so two projects never race for 3000.
  • Fail loudly. In Vite, strictPort: true makes a busy port an error instead of a silent move to the next one.
  • Stop servers when you switch projects. Control-C in the terminal that started them is still the cleanest way.
  • Watch them in one place. Orcylo’s Projects view lists your running dev servers grouped by project folder, with their ports, memory and how long each has been idle. It nudges you to stop the ones that have been idle for a long time, and always asks before stopping anything (see Projects in Orcylo).

If the culprit turns out to be a heavy app rather than a port, how to check CPU and memory usage on a Mac walks through Activity Monitor. The glossary entry on PIDs and its neighbours explain the other terms lsof and Activity Monitor use, and the guide to Mac task managers compares tools that can quit apps for you.

Questions people ask

How do I kill the process on port 3000 on a Mac?

Find its PID with lsof -nP -iTCP:3000 -sTCP:LISTEN, then run kill followed by that PID. As a one-liner, kill $(lsof -t -iTCP:3000 -sTCP:LISTEN) stops only the listening server. Avoid kill $(lsof -ti :3000): it also matches clients connected to the port, such as your browser.

What does "address already in use" mean?

Another process is already listening on the address and port your server tried to use, and only one can listen there at a time. In Node.js the error code is EADDRINUSE; in Python on macOS it is OSError: [Errno 48] Address already in use. Find and stop the other process, or start your server on a different port.

Why is ControlCenter using port 5000 on my Mac?

That is the AirPlay Receiver, which lets other Apple devices stream to your Mac. On macOS 26 it listens on ports 5000 and 7000. If you need port 5000 for Flask or another server, turn off AirPlay Receiver in System Settings > General > AirDrop & Continuity, or run your server on another port.

Can I see which app is using a port in Activity Monitor?

No. Activity Monitor shows network traffic per process but not port numbers, and its Ports column counts Mach ports, the channels macOS processes use to talk to each other, not network ports. Use lsof in Terminal instead.

Is kill -9 safe to use?

It always stops the process, but the process gets no chance to close files, finish writes or stop the child processes it started. Use plain kill first and give it a few seconds. Keep kill -9 for a process that ignores that, and check the port again afterwards.

Sources

  1. 1.Node.js documentation: Errors, EADDRINUSE · nodejs.org
  2. 2.Next.js documentation: next CLI (default port 3000) · nextjs.org
  3. 3.Next.js 16.2: dev server lock file · nextjs.org
  4. 4.Vite documentation: server.port and server.strictPort · vite.dev
  5. 5.Rails Guides: The Rails Command Line (bin/rails server port) · guides.rubyonrails.org
  6. 6.Django documentation: runserver · docs.djangoproject.com
  7. 7.Python documentation: http.server · docs.python.org
  8. 8.Flask documentation: Development Server, Address already in use · flask.palletsprojects.com
  9. 9.Docker documentation: Networking on Docker Desktop · docs.docker.com
  10. 10.Docker documentation: docker container ls · docs.docker.com
  11. 11.Apple: TCP and UDP ports used by Apple software products · support.apple.com
  12. 12.Apple: Change AirDrop & Continuity settings on Mac (macOS Tahoe 26) · support.apple.com
  13. 13.Apple Developer Forums: Mach port leakage (Activity Monitor Ports column) · developer.apple.com

About the author

MerdoAI

Maker of Orcylo

Orcylo is a native menu bar system monitor for macOS 15 Sequoia and later. It groups about 700 processes under the 25 or so apps that own them, keeps 30 days of history and shows your Claude Code and Codex limits. The guides cover the same ground: what is slowing a Mac down, what Activity Monitor's figures mean, and how much of an AI coding limit is left.

How these guides are written and checked: our editorial policy. To report a mistake, contact support@orcylo.app.

More guides