localhost:3000 is a web server running on your own computer and listening on port 3000. Next.js, the Express hello world example and Rails all default to that port. If the page refuses to connect, nothing is listening there. If the server will not start, another process already holds the port, and you can find and stop it.
| What you see | Meaning | First thing to try |
|---|---|---|
| Browser: localhost refused to connect | Nothing is listening on port 3000 | Start the dev server and read the URL it prints |
| Terminal: EADDRINUSE :::3000 | Another process already uses port 3000 | Find that process and stop it, or use another port |
| Page loads, but an old app appears | A different project's server is still running | Stop it, then restart the right one |
Updated
localhost always means this machine, and the number after the colon picks which program on it you are talking to. Most trouble with port 3000 comes from one of two opposite problems: no server is running there, or two servers want it at once. Type a port below to get the commands for your system.
Port: 3000
List the process listening on the port, then stop it by its PID (the second column).
lsof -i :3000 -sTCP:LISTEN
kill <PID>
# still running? force it
kill -9 <PID>Show connections with their process IDs, filter by the port, then end that PID.
netstat -ano | findstr :3000
taskkill /PID <PID> /FLeave the other process alone and start your app somewhere free.
next dev -p 3001
PORT=3001 node app.js
npm run dev -- --port 3001| Tool | Command | Default URL |
|---|---|---|
| Next.js | next dev / next start | http://localhost:3000 |
| Express hello world example | node app.js | http://localhost:3000 |
| Ruby on Rails | bin/rails server | http://localhost:3000 |
| Vite | vite | http://localhost:5173 |
| Vite preview | vite preview | http://localhost:4173 |
| Astro | astro dev | http://localhost:4321 |
A small Express server that falls back to 3000, and prints a readable message when the port is taken.
const express = require("express");
const app = express();
const port = Number(process.env.PORT) || 3000;
app.get("/", (req, res) => res.send("Hello"));
const server = app.listen(port, () => {
console.log(`Listening on http://localhost:${port}`);
});
server.on("error", (err) => {
if (err.code === "EADDRINUSE") {
console.error(`Port ${port} is busy. Try PORT=${port + 1} node app.js`);
process.exit(1);
}
throw err;
});
A computer can run many servers at once, so each one listens on a numbered port. Only one program can listen on a given port and address at a time, which is why starting a second server on 3000 fails with EADDRINUSE.
Port 3000 has no official meaning. It became a habit because popular tools picked it as their default, so it is also the port most likely to be taken by a server you forgot about.
First confirm a server is running: its terminal should show a ready message and a URL. If it exited with an error, fix that error first, since the browser cannot connect to a server that is not there.
Next compare ports. If the terminal says 5173 or 4321 and you typed 3000, the browser is knocking on an empty door. Finally, try 127.0.0.1:3000 in place of localhost:3000, which rules out name resolution to the IPv6 address when the server only listens on IPv4.
localhost is the name for your own computer, usually 127.0.0.1 or ::1, and 3000 is a port number. Together they address a server running locally, most often a development server for a web app. Nobody else on the internet can open your localhost URL.
No program is accepting connections on that port. The dev server may not be running, may have crashed with an error, or may be listening on a different port such as 5173. Check the terminal where you started it.
Find the process holding the port with lsof on Mac or Linux, or netstat -ano on Windows, then stop it with kill or taskkill. Or start your app on another port, for example next dev -p 3001.
Pass -p, as in next dev -p 4000, or set the PORT environment variable when you run the command. The Next.js docs note that PORT cannot be set inside a .env file, because the server starts before that file is read.
Not through that address, because localhost on their machine means their own computer. To share it on your network, the server must listen on all interfaces and others use your machine's local IP address and port.
Related: Vite vs Next.js, Install Node.js and npm on Mac, HTTP status codes, Deploy a React app, npm commands cheat sheet.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.