localhost:4200 is the default port of the Angular CLI dev server. Running ng serve (or npm start in a new Angular project) compiles the app and serves it with live reload at http://localhost:4200. If the browser shows ERR_CONNECTION_REFUSED, the dev server isn't running yet or the build failed.
What runs on port 4200
Almost always Angular:
| Tool | Command | Notes |
|---|---|---|
| Angular CLI | ng serve / npm start | Default 4200 |
| Nx Angular apps | nx serve my-app | Uses the same Angular dev server |
| Ionic with Angular | ionic serve | Defaults to 8100, not 4200 |
React and Next.js projects use localhost:3000 and Vite projects use localhost:5173. Recent Angular versions use Vite and esbuild under the hood, but ng serve still defaults to 4200.
Fix "localhost:4200 refused to connect"
- Wait for the first build.
ng serveopens the port only after compilation. Watch for theLocal: http://localhost:4200/line, or forApplication bundle generation complete. - Read the build error. A TypeScript or template error stops the build, and nothing listens until you fix it.
- Check the port. If 4200 was busy, the CLI asks whether to use another port. Accepting means the app is on a different port, often 4201 or a random one.
- Docker or a VM?
ng servebinds tolocalhostby default. Inside a container you needng serve --host 0.0.0.0and-p 4200:4200.
Find and free a busy port 4200
Port 4200 is already in use. Use '--port' to specify a different port. usually means another ng serve is still running in a forgotten terminal.
# macOS / Linux
lsof -i :4200
kill -9 $(lsof -ti :4200)
# Windows
netstat -ano | findstr :4200
taskkill /PID <pid> /F
To change the port for one run, use ng serve --port 4201. To change it for the whole team, set it in angular.json:
"serve": {
"options": { "port": 4201 }
}
Open localhost:4200 from another device
ng serve --host 0.0.0.0
Then open http://YOUR-LAN-IP:4200 from your phone on the same Wi-Fi (find the IP with ipconfig getifaddr en0 on macOS, hostname -I on Linux or ipconfig on Windows). The CLI prints a warning that binding to all interfaces is insecure; that's expected for local testing on a trusted network.
If the device gets "Invalid Host header" or a blocked-host response, the dev server is rejecting the hostname in the request. That's the same protection you'll hit with a tunnel, covered below.
Share localhost:4200 publicly
Run a tunnel next to ng serve:
relay connect --name my-angular-app http://localhost:4200
The relay CLI prints a public HTTPS URL that forwards to port 4200. The Angular dev server checks the Host header and only accepts hostnames it knows, so allow the tunnel's hostname:
"serve": {
"options": {
"allowedHosts": ["<hostname relay connect printed>"]
}
}
Older webpack-based Angular builders also accept ng serve --disable-host-check, which turns the check off completely; prefer listing the one hostname. Keeping the same --name means the URL, and therefore the allowed host, stays the same across restarts.
Angular itself never receives webhooks; your API does. If the app talks to a local backend that needs Stripe or GitHub webhooks, forward those to the backend port with relay forward as described in receive webhooks on localhost.
