What the address means
In http://localhost:3000/login:
httpis the application protocol.localhostresolves to the current device’s loopback interface, commonly127.0.0.1or::1.3000selects one TCP port on that device./loginis an application path sent after the connection succeeds.
“Localhost” changes with the client. On your phone, localhost means the phone—not the laptop running your development server.
Why port 3000 appears in development
Port 3000 is a convention used by several tools and tutorials. Next.js documents it as the default for next dev. A Node or Express application can listen on 3000 when its code or environment selects that value. Other tools use different defaults: Vite documents 5173, Django uses 8000 for runserver, and Flask uses 5000 for its development command.
The terminal output is more reliable than the convention. If a tool prints 3001, 5173, or another URL, use the printed address.
Start and verify a service
For an existing project, use the command in its README or package scripts. A common Next.js project uses:
npm run dev
# then open the exact Local URL printed by Next.js
A minimal Node HTTP server can make the relationship explicit:
// server.mjs
import http from 'node:http'
http.createServer((request, response) => {
response.writeHead(200, { 'content-type': 'text/plain' })
response.end(`You requested ${request.url}\n`)
}).listen(3000, '127.0.0.1')
node server.mjs
curl -i http://127.0.0.1:3000/
Why /login, /admin, or /docs may fail
Port 3000 only gets the request to one server. That server must still recognize the path and method.
| Result | What it means |
|---|---|
/ works, /login returns 404 | The server is reachable; the route is missing, differently named, or under another base path. |
/login returns 405 | The route exists but does not accept the HTTP method used by the request. |
/admin redirects | The application may be enforcing authentication or a canonical path. |
| Every path is refused | No server is accepting connections at the requested address and port. |
A browser address bar makes a GET request. An API route that accepts only POST will not behave like a web page.
Check what is actually running
# Windows PowerShell
Get-NetTCPConnection -LocalPort 3000 -State Listen |
Select-Object LocalAddress, OwningProcess
# macOS or Linux
lsof -nP -iTCP:3000 -sTCP:LISTEN
# Inspect the HTTP response
curl -i http://127.0.0.1:3000/
No listener means there is nothing to fix in the browser. An HTTP response means the connection works and the status, headers, application log, and browser console should guide the next step.
For a full decision tree covering ERR_CONNECTION_REFUSED, EADDRINUSE, Docker, WSL, and blank screens, use localhost:3000 not working.
When to use another port
Two services cannot normally listen on the same address and port at the same time. Configure one service on a different port when projects run together. The port number itself does not change whether a service is a frontend, API, database, or admin interface.
| Port | Documented or common association | Guide |
|---|---|---|
| 5000 | Flask development server | Flask on 5000 |
| 5173 | Vite development server | Vite on 5173 |
| 8000 | Django development server | Django on 8000 |
| 8080 | Spring Boot and other HTTP services | Services on 8080 |
| 8888 | Jupyter Server | Jupyter on 8888 |
| 9200 | Elasticsearch HTTP API | Elasticsearch on 9200 |
Official references
- Next.js CLIDefault development port and port/hostname options.
- Node.js net serverHow a server binds to a port and reports address conflicts.
- MDN: Local network accessLoopback, local, and public address spaces.