“80, but unprivileged”
HTTP's real port is 80, and on Unix-like systems ports below 1024 traditionally required root. So developers picked lookalikes anyone can open: 8080, 8000, 8888.
CH. 02 Ports · the doors of a computer
In localhost:3000, localhost picks the computer and 3000 picks the program. A port is a numbered door — every computer has 65,535 of them — and your browser just knocked on one.
Pick a port and send a request
Green lights mean a program is listening behind that door. Try turning your app off, then knock on :3000.
§ 01 The short answer
A port is a number from 0 to 65535 that identifies one program on a computer. The IP address gets data to the right machine; the port gets it to the right program on that machine.
localhost:3000 means “the program listening on port 3000 on this computer.” If nothing is listening there, the connection is refused.
Rules How ports behave
EADDRINUSE — “address already in use.”http:// means port 80 and https:// means 443, which is why real websites never show a port.§ 02 The map
The IANA registry splits the 65,536 ports into three ranges (RFC 6335). Drawn to scale, the famous ports barely show up.
§ 03 Reference
The defaults you'll meet most often while developing. A port is only a convention — any program can listen on any free port — but these are where things usually live.
| Port | What usually runs there | Notes |
|---|---|---|
| Web servers & app frameworks | ||
| 80 | HTTP — the default for http:// | Browsers hide it: http://localhost means port 80. |
| 443 | HTTPS — the default for https:// | Local HTTPS needs a certificate (tools like mkcert help). |
| 1234 | Parcel · LM Studio local API | |
| 1313 | Hugo (hugo server) | |
| 3000 | Next.js, Nuxt, Ruby on Rails, Docusaurus, Grafana, Express & Bun examples | The most famous dev port of all. |
| 3001 | The next try when 3000 is taken | Next.js and others move up one port automatically. |
| 4000 | Phoenix (Elixir), Jekyll, Firebase Emulator UI | |
| 4173 | Vite preview (vite preview) | Serves your production build locally. |
| 4200 | Angular CLI (ng serve) | |
| 4321 | Astro | Default since Astro 3.0. Read it as a countdown. |
| 5000 | Flask · older ASP.NET Core templates | On macOS 12+, AirPlay Receiver already listens here. |
| 5173 | Vite dev server — React, Vue, Svelte, SvelteKit | 5173 spells VITE: V=5, I=1, T=7, E=3. |
| 5500 | VS Code Live Server extension | |
| 6006 | Storybook · TensorBoard | |
| 7860 | Gradio · Stable Diffusion web UI | |
| 8000 | Django, python -m http.server, FastAPI/Uvicorn, Laravel, Gatsby, Deno | “80, but unprivileged.” |
| 8080 | Spring Boot, Tomcat, Jenkins, webpack-dev-server, Vue CLI, many Docker images | The classic alternative HTTP port. |
| 8081 | React Native Metro bundler | |
| 8188 | ComfyUI | |
| 8443 | Alternative HTTPS | |
| 8501 | Streamlit | |
| 8787 | Cloudflare Workers (wrangler dev) | |
| 8888 | Jupyter Notebook · Netlify Dev | |
| 9000 | PHP-FPM, MinIO, SonarQube | A crowded one — conflicts are common. |
| 9229 | Node.js debugger (node --inspect) | |
| 11434 | Ollama (local LLMs) | |
| Databases, queues & data | ||
| 1433 | Microsoft SQL Server | |
| 2181 | Apache ZooKeeper | |
| 3306 | MySQL · MariaDB | |
| 5432 | PostgreSQL | Not a web server — opening it in a browser fails. |
| 5555 | Prisma Studio | |
| 5601 | Kibana | |
| 5672 · 15672 | RabbitMQ · its management UI | |
| 5984 | CouchDB | |
| 6379 | Redis · Valkey | |
| 7474 · 7687 | Neo4j (HTTP · Bolt) | |
| 8086 | InfluxDB | |
| 8123 | ClickHouse HTTP · Home Assistant | |
| 9042 | Apache Cassandra | |
| 9092 | Apache Kafka | |
| 9200 | Elasticsearch · OpenSearch | |
| 11211 | Memcached | |
| 27017 | MongoDB | |
| 54321–54324 | Supabase local stack (API, Postgres, Studio, email) | From supabase start. |
| Infrastructure & tools | ||
| 22 | SSH | Browsers refuse to open it. |
| 25 · 587 | SMTP (sending email) | |
| 53 | DNS | |
| 1025 · 8025 | Mailpit · MailHog (SMTP · web inbox) | Catch outgoing email while developing. |
| 2375 · 2376 | Docker Engine API (plain · TLS) | Never expose 2375 to a network. |
| 3100 | Grafana Loki | |
| 4566 | LocalStack (AWS services, locally) | |
| 5678 | n8n | |
| 6443 | Kubernetes API server | |
| 8200 | HashiCorp Vault | |
| 8500 | HashiCorp Consul | |
| 8545 | Ethereum JSON-RPC (Hardhat, Anvil) | |
| 9090 | Prometheus | |
| 16686 | Jaeger UI | |
| 25565 | Minecraft server | |
| 32400 | Plex Media Server | |
| No common port matches that. Any free port from 1024 to 49151 is fair game for your own app. | ||
§ 04 Field notes
Port numbers look random. Most of them have a story.
HTTP's real port is 80, and on Unix-like systems ports below 1024 traditionally required root. So developers picked lookalikes anyone can open: 8080, 8000, 8888.
Ruby on Rails shipped with port 3000 in 2004. A generation of Node.js tutorials, Create React App and Next.js followed — and 3000 became the default “my app” port.
Vite's default reads V-I-T-E: 5 is V in Roman numerals, 1 looks like I, 7 like T, and 3 like a backwards E.
Since macOS Monterey, AirPlay Receiver listens on 5000 (and 7000) — so Flask can fail with “address already in use.” Turn it off in System Settings → General → AirDrop & Handoff, or use --port 5001.
Every connection has two ports. Yours is temporary — your OS picks it from the dynamic range and frees it when the connection closes.
Port 0 is reserved. Ask your OS to listen on port 0 and it picks a free port for you — a trick test suites use to avoid collisions.
§ 05 Commands
When a server won't start because its port is taken, find out who's behind that door, then stop it — or start your app on another port.
Replace 3000 with your port. For a fuller walkthrough of the errors you might see, read “port already in use” in the troubleshooting guide.
macOS
# Who is listening on port 3000?
lsof -nP -iTCP:3000 -sTCP:LISTEN
# Stop it (use the PID from the output)
kill <PID>
# Every listening port on this Mac
lsof -nP -iTCP -sTCP:LISTENLinux
# Who is listening on port 3000?
sudo ss -ltnp 'sport = :3000'
# Stop it (use the PID from the output)
kill <PID>
# Or in one step
sudo fuser -k 3000/tcpWindows
# Who is listening on port 3000?
Get-NetTCPConnection -LocalPort 3000 -State Listen
# Stop it (OwningProcess from the output)
Stop-Process -Id <PID>
# Classic Command Prompt version
netstat -ano | findstr :3000
taskkill /PID <PID> /F§ 06 Browser rules
Open http://localhost:6000 and Chrome shows ERR_UNSAFE_PORT; Firefox says “This address is restricted.” Nothing is wrong with your server: browsers block web requests to a short list of ports that belong to other protocols, so a malicious page can't trick your browser into talking to, say, a mail server.
The list lives in the Fetch standard. If your app picked one of these by accident, move it to another port.
| Blocked port | Belongs to |
|---|---|
| 21 · 22 · 23 | FTP · SSH · Telnet |
| 25 · 110 · 143 · 587 · 993 | Email (SMTP, POP3, IMAP) |
| 53 | DNS |
| 2049 · 4045 | NFS file sharing |
| 5060 · 5061 | SIP (internet telephony) |
| 6000 | X11 (graphical desktops) |
| 6665–6669 · 6697 | IRC chat |
| 10080 | Amanda backups |
A selection — the standard lists about 80 ports, most of them below 1024.
§ 07 FAQ
Whatever program on your own computer is listening on port 8080. It's the classic “alternative HTTP” port, used by Spring Boot, Tomcat, Jenkins, webpack-dev-server, Vue CLI and many Docker images. If nothing is listening there, your browser shows “localhost refused to connect.”
The program listening on port 3000 on your computer — most often a Next.js, Nuxt, Ruby on Rails or Node.js development server. It only works while that server is running, and only on your machine.
Vite's development server. React, Vue, Svelte and SvelteKit projects created with Vite open there by default. The number spells VITE: 5 is V in Roman numerals, then 1, 7 and 3 stand in for I, T and E.
Usually Django's runserver, Python's built-in http.server, FastAPI with Uvicorn, or Laravel's artisan serve. Like 8080, it's a lookalike of HTTP's port 80 that doesn't need admin rights.
Not on the same address at the same time. The first program to listen claims the port; the second fails with an error like EADDRINUSE (“address already in use”). Stop the first one, or start the second on a different port.
65,536 per protocol: TCP and UDP each have ports 0 through 65535, and port 0 is reserved. Ports 0–1023 are system ports, 1024–49151 are registered ports, and 49152–65535 are dynamic ports your operating system hands out for outgoing connections.
Since macOS Monterey, AirPlay Receiver listens on port 5000 (and 7000). Turn it off in System Settings → General → AirDrop & Handoff, or run your app on another port, for example flask run --port 5001.
They reach the same server, but your browser treats them as different sites: cookies, logins and localStorage saved on one won't appear on the other. And if localhost resolves to IPv6 (::1) while your server only listens on 127.0.0.1, only one of them will work.