Port 5000 Already in Use on macOS? It's AirPlay Receiver
Port 5000 already in use on macOS? AirPlay Receiver (ControlCenter) binds 5000 and 7000. Confirm with lsof, disable AirPlay Receiver, or change your Flask, Docker, or Node port.
On this page
- Why port 5000 is always in use on macOS
- What is using port 5000? Confirm with lsof
- Fix 1: Disable AirPlay Receiver (free ports 5000 and 7000)
- macOS Ventura, Sonoma, Sequoia, and later
- macOS Monterey
- Fix 2: Keep AirPlay Receiver, change your Flask / Docker / Node port
- Flask
- Node / Express
- Next.js
- Docker Compose
- Rails / other Ruby apps
- Generic Python HTTP server
- The quieter failure mode: blank pages and odd HTTP responses
- What about “just use another default forever”?
- Quick checklist: port 5000 already in use on macOS
- Takeaway
You start a local server and macOS answers with something like this:
Error: listen EADDRINUSE: address already in use :::5000
Or, with Docker:
Error starting userland proxy: listen tcp4 0.0.0.0:5000: bind: address already in use
You did not launch another app. kill does nothing useful. Restarting the terminal does nothing. Port 5000 is simply taken — and “what is using port 5000 on my Mac?” is the right next question.
On macOS Monterey (12) and later (Ventura, Sonoma, Sequoia…), the usual culprit is not a leftover Node process. It is AirPlay Receiver, running under Control Center (ControlCenter / ControlCe in lsof), which binds TCP 5000 (and often 7000) by default. Apple documents both ports as used by AirPlay.
This post covers how to confirm it, disable AirPlay Receiver to free the port, or keep AirPlay and change your app port instead.
Why port 5000 is always in use on macOS
Port 5000 is a popular default:
- Flask’s development server
- Many Docker Compose samples and demo APIs
- Node, Express, and assorted static servers and internal dashboards
AirPlay Receiver, introduced as a first-class Mac feature in Monterey, turns your Mac into an AirPlay target (phone → Mac screen/speakers). That service needs network listeners. Apple’s port list maps TCP 5000 and TCP 7000 to AirPlay.
So two ecosystems quietly chose the same number:
| Side | Uses port 5000 for |
|---|---|
| macOS | AirPlay Receiver (ControlCenter) |
| Dev tools | Local HTTP / API servers |
If you upgraded past Big Sur, AirPlay Receiver was often already on. You only notice when a framework tries to bind the same port and throws EADDRINUSE / “address already in use.”
What is using port 5000? Confirm with lsof
Before changing system settings, verify who owns the port:
lsof -nP -iTCP:5000 -sTCP:LISTEN
If AirPlay is involved, you will see something like:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ControlCe 423 you 33u IPv4 0x… 0t0 TCP *:5000 (LISTEN)
ControlCe 423 you 34u IPv6 0x… 0t0 TCP *:5000 (LISTEN)
ControlCe is Terminal truncating ControlCenter. That process is part of macOS; it is not your Flask app and not a rogue Docker container.
Also check 7000 if that port shows up in compose files or other tools:
lsof -nP -iTCP:7000 -sTCP:LISTEN
Same ControlCenter process usually means the same root cause.
Fix 1: Disable AirPlay Receiver (free ports 5000 and 7000)
If you do not use your Mac as an AirPlay target, turn the feature off. Ports release immediately; no reboot required.
macOS Ventura, Sonoma, Sequoia, and later
- Open System Settings
- Go to General → AirDrop & Handoff (on some builds this is labeled AirDrop & Continuity)
- Turn AirPlay Receiver off
Faster path: open System Settings and search for AirPlay. Older blog posts still say System Preferences → Sharing — that path was Monterey-era; on current macOS the toggle lives under AirDrop & Handoff.
macOS Monterey
- Open System Preferences
- Open Sharing
- Uncheck AirPlay Receiver
Then re-check the port:
lsof -nP -iTCP:5000 -sTCP:LISTEN
No output means nothing is listening. Start your server again.
Trade-off: other Apple devices can no longer AirPlay to this Mac. Outbound AirPlay from the Mac (to a TV or speaker) is a different feature and is not what this toggle is for.
Fix 2: Keep AirPlay Receiver, change your Flask / Docker / Node port
If you actually use AirPlay Receiver, do not disable it for a local server. Point the app at another port. Anything free above 1024 works; 5001, 5050, 8000, and 8080 are common choices. Avoid 7000 while AirPlay Receiver is on.
Flask
flask run --port 5001
Or in code:
if __name__ == "__main__":
app.run(port=5001)
Persist it in the environment:
export FLASK_RUN_PORT=5001
Node / Express
PORT=5001 node server.js
# or
npx serve -l 5001
Next.js
PORT=5001 next dev
# or
next dev -p 5001
Docker Compose
services:
api:
ports:
- "5001:5000" # host:container
That maps host 5001 to container 5000, so the image can keep its internal default without fighting ControlCenter on the Mac.
Rails / other Ruby apps
rails server -p 5001
# or
bundle exec puma -p 5001
Generic Python HTTP server
python3 -m http.server 5001
The quieter failure mode: blank pages and odd HTTP responses
Sometimes the bind does not fail. You already have something on 5000, open http://localhost:5000, and get a blank page, a refusal, or a response that is clearly not your app.
That can happen when the browser hits AirPlay’s listener instead of your process — or when two things fight for the same port over time. If lsof shows ControlCenter on 5000, stop debugging your framework first. Fix the port ownership, then retest.
What about “just use another default forever”?
For personal machines, either fix is fine. For shared repos and onboarding docs, changing the default port is usually kinder:
- New teammates on macOS hit the conflict less often.
- Nobody has to disable a system feature they might want.
- Docker port maps stay explicit and boring.
A one-line note in the README helps:
## Local dev
Default API port is **5001** (not 5000). macOS AirPlay Receiver
often occupies 5000/7000 via Control Center.
If your team standardizes on 5000 for historical reasons, document the AirPlay toggle next to the setup steps so the next person does not spend an hour on EADDRINUSE.
Quick checklist: port 5000 already in use on macOS
- See
EADDRINUSE/ “address already in use” on 5000 (or 7000). - Run
lsof -nP -iTCP:5000 -sTCP:LISTENto see what is using port 5000. - If the command is
ControlCe/ ControlCenter → AirPlay Receiver. - Either:
- System Settings → General → AirDrop & Handoff → AirPlay Receiver off (Monterey: Sharing), or
- Run Flask, Docker, Node, etc. on 5001 (or another free port) and update Compose/README.
- Confirm with
lsofagain, then start the server.
Takeaway
Port 5000 is not “broken” on modern macOS. Apple claimed it for AirPlay Receiver through Control Center, and a large slice of the local-dev world (Flask defaults, Docker samples, Node apps) still assumes 5000 is free. Once you know that, the mystery is gone: diagnose with lsof, free the port by disabling AirPlay Receiver, or stop competing and bind somewhere else.
If you only remember one command from this post, make it this:
lsof -nP -iTCP:5000 -sTCP:LISTEN
When ControlCenter shows up, you are not debugging your stack — you are negotiating with the OS.
More field notes when the next problem is specific enough to be useful.