First identify the service
A port number cannot tell you which framework owns it. Start with the terminal that launched the app, then inspect the listener:
# Windows PowerShell
Get-NetTCPConnection -LocalPort 8000 -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
Get-Process -Id <PID>
# macOS or Linux
lsof -nP -iTCP:8000 -sTCP:LISTEN
Probe the root without assuming that a browser page exists:
curl -i http://127.0.0.1:8000/
Start the intended server
| Tool | Command | What to expect |
|---|---|---|
| Django | python manage.py runserver | Development server on 127.0.0.1:8000 by default. |
| Django, LAN test | python manage.py runserver 0.0.0.0:8000 | Listens on all interfaces; use the computer’s LAN IP from another device. |
| Python files | python -m http.server 8000 --bind 127.0.0.1 | Serves the current directory. It is not a Django or API server. |
| FastAPI with Uvicorn | uvicorn main:app --host 127.0.0.1 --port 8000 | Serves the ASGI app named app from main.py. |
Django’s runserver is for development only. Django’s own documentation says it is not designed for production. Binding to 0.0.0.0 also makes it reachable beyond your browser, so use a trusted network and firewall.
Why /admin or /docs returns 404
localhost:8000/admin and /docs are not features of the port. Routes come from the application currently listening there.
- Django admin: the project must include
django.contrib.adminand mappath("admin/", admin.site.urls). The trailing slash matters with common Django settings. - FastAPI docs: Swagger UI normally appears at
/docsunless the app disables or changesdocs_url. - Python http.server: it serves files and directories. It has no application admin or API documentation route.
A framework-generated 404 is useful evidence: the network connection succeeded, but the requested application route does not exist.
Diagnose the actual failure
| Result | Interpretation | Action |
|---|---|---|
| Connection refused | No process is listening at the resolved address and port. | Start the server; confirm the exact bind address and port. |
Address already in use | Another process owns 8000. | Identify it, stop it if appropriate, or start on another port such as 8001. |
| 404 response | The server is reachable; the path is wrong or not registered. | Inspect the app’s route configuration. |
| 400 Bad Request in Django | The hostname may not be permitted by ALLOWED_HOSTS. | Add the precise development hostname; do not use a wildcard without understanding the risk. |
| Works on this computer only | The server probably listens on loopback, or the firewall blocks LAN traffic. | Bind deliberately to a LAN-reachable interface and permit only the needed network. |
A reproducible test sequence
- Run the documented start command and keep its terminal open.
- Confirm the printed URL and check the listener.
- Request
/withcurl -i. - Only after the root responds, test framework-specific paths such as
/admin/or/docs. - If another device is involved, test the machine’s LAN IP and verify both binding and firewall rules.
Official references
- Django: runserverDefault address and port, address selection, and development-only warning.
- Django: ALLOWED_HOSTSHost-header validation and development behavior.
- Python: http.serverCommand-line file server options and security considerations.
- FastAPI: First stepsApplication startup and interactive documentation routes.