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

Canonical page: https://orcylo.app/find-process-using-port-mac

By [MerdoAI](https://x.com/merdoAI) (Maker of Orcylo). Published October 1, 2026. Editorial policy: https://orcylo.app/guides#how-we-write

**Short 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](https://nodejs.org/api/errors.html)). It looks like this:

```text
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

<!-- [ORIGINAL DATA] -->
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:

   ```sh
   lsof -nP -iTCP:3000 -sTCP:LISTEN
   ```

   `-iTCP:3000` selects TCP port 3000. `-sTCP:LISTEN` keeps only the [listening](https://orcylo.app/glossary#listening-port) 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:

   ```text
   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:

   ```sh
   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:

   ```sh
   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:

```sh
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](https://developer.apple.com/forums/thread/110688)). 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](https://nextjs.org/docs/app/api-reference/cli/next), [Rails Guides](https://guides.rubyonrails.org/command_line.html), [Vite](https://vite.dev/config/server-options), [Django](https://docs.djangoproject.com/en/stable/ref/django-admin/) and [Python](https://docs.python.org/3/library/http.server.html).

### 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](https://vite.dev/config/server-options)), 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](https://nextjs.org/blog/next-16-2-ai)).

### 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](https://docs.docker.com/desktop/features/networking/)). 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:

```sh
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](https://support.apple.com/en-us/103229)). 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](https://flask.palletsprojects.com/en/stable/server/)). On macOS 26, choose Apple menu > System Settings > General > AirDrop & Continuity and turn off AirPlay Receiver ([Apple, macOS 26](https://support.apple.com/guide/mac-help/mchl6a407f99/26.0/mac/26.0)), 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](https://orcylo.app/#projects)).

If the culprit turns out to be a heavy app rather than a port, [how to check CPU and memory usage on a Mac](https://orcylo.app/check-cpu-memory-usage-mac) walks through Activity Monitor. The [glossary entry on PIDs](https://orcylo.app/glossary#pid) and its neighbours explain the other terms lsof and Activity Monitor use, and [the guide to Mac task managers](https://orcylo.app/task-manager-for-mac) 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

- [Node.js documentation: Errors, EADDRINUSE](https://nodejs.org/api/errors.html)
- [Next.js documentation: next CLI (default port 3000)](https://nextjs.org/docs/app/api-reference/cli/next)
- [Next.js 16.2: dev server lock file](https://nextjs.org/blog/next-16-2-ai)
- [Vite documentation: server.port and server.strictPort](https://vite.dev/config/server-options)
- [Rails Guides: The Rails Command Line (bin/rails server port)](https://guides.rubyonrails.org/command_line.html)
- [Django documentation: runserver](https://docs.djangoproject.com/en/stable/ref/django-admin/)
- [Python documentation: http.server](https://docs.python.org/3/library/http.server.html)
- [Flask documentation: Development Server, Address already in use](https://flask.palletsprojects.com/en/stable/server/)
- [Docker documentation: Networking on Docker Desktop](https://docs.docker.com/desktop/features/networking/)
- [Docker documentation: docker container ls](https://docs.docker.com/reference/cli/docker/container/ls/)
- [Apple: TCP and UDP ports used by Apple software products](https://support.apple.com/en-us/103229)
- [Apple: Change AirDrop & Continuity settings on Mac (macOS Tahoe 26)](https://support.apple.com/guide/mac-help/mchl6a407f99/26.0/mac/26.0)
- [Apple Developer Forums: Mach port leakage (Activity Monitor Ports column)](https://developer.apple.com/forums/thread/110688)

More guides: [Which app is using my CPU or memory](https://orcylo.app/check-cpu-memory-usage-mac), [Why is my Mac so slow](https://orcylo.app/why-is-my-mac-so-slow), [Activity Monitor glossary](https://orcylo.app/glossary), [Activity Monitor alternatives](https://orcylo.app/best-activity-monitor-alternatives), [Task Manager for Mac](https://orcylo.app/task-manager-for-mac).

---

Orcylo: Claude Code and Codex limits in the Mac menu bar, plus an Activity Monitor alternative. €5 for the first 20 licences, then €7.50 for the next 30, then €9.99, for one Mac. One payment, every update for life. No account, no subscription. https://orcylo.app/
