Django runserver default port: 8000
Django runserver uses TCP port 8000 by default. Django does not look for another port. runserver prints “Error: That port is already in use.” and exits with status 1, so nothing serves your project until you start it again on a free port, for example python manage.py runserver 8001.
Key facts
| Port | Protocol | Role | Category |
|---|---|---|---|
| 8000 | TCP | manage.py runserver development server | Backend |
What happens when the port is busy
Django does not look for another port. runserver prints “Error: That port is already in use.” and exits with status 1, so nothing serves your project until you start it again on a free port, for example python manage.py runserver 8001.
Change the port
python manage.py runserver 8001A bare number changes only the port. The address stays at the default, 127.0.0.1.
python manage.py runserver 0.0.0.0:80010 is a shortcut for 0.0.0.0, so runserver 0:8001 is equivalent. Use it only when other devices need to reach the server.
python manage.py runserver 127.0.0.1:${PORT:-8000}runserver reads no port environment variable, so your shell expands ${PORT:-8000} before Django sees it. That works in a terminal or a script that exports PORT.
Bind address
Binds to 127.0.0.1 by default, which other machines on your network cannot reach. Giving 0.0.0.0, or its shortcut 0, as the address makes the server reachable from the network. The -6 flag changes the default address to ::1, and a bracketed IPv6 address such as [::1]:8001 turns IPv6 on.
What else uses this port
TCP port 8000 is also the default for Laravel artisan serve.
The dataset is the 12 tools on the ports index.
Find and free this port
These commands find the process that holds TCP port 8000 and stop it. They come from the Port in use command generator. PID_NUMBER stands for the process ID you read from the first command: replace it before you run the others.
lsof -nP -iTCP:8000 -sTCP:LISTEN
ps -p PID_NUMBER -o pid,ppid,user,command
kill -TERM PID_NUMBERss -ltnp 'sport = :8000'
ps -p PID_NUMBER -o pid,ppid,user,command
kill -TERM PID_NUMBERGet-NetTCPConnection -LocalPort 8000 -State Listen -ErrorAction SilentlyContinue | Select-Object LocalAddress, LocalPort, State, OwningProcess
Get-CimInstance -ClassName Win32_Process -Filter "ProcessId = PID_NUMBER" | Select-Object ProcessId, ParentProcessId, Name, CommandLine
Stop-Process -Id PID_NUMBERRead the output of the second command before you stop anything, because the owner may be a container or another person’s process. Then run the first command again to confirm the port is free.
Next free ports
Counting up from 8000, the next three ports that no tool in this dataset uses as a default are 8001, 8002, and 8003. They are suggestions only: another program on your machine may hold any of them, so run the find command above before you choose one.
In Rig
Rig reads a file named exactly Procfile in the project root and runs each entry through /bin/sh -c. When a port is set, Rig exports PORT and appends --port N to the entry. runserver takes its port as a positional argument and rejects that flag (error: unrecognized arguments), so a Django Procfile entry fails to start while a port is set. With no port set, Rig appends nothing. When 8000 is held, who_owns_port returns the owner’s PID, command, and working directory plus the first free port in the 50 above it.
Collisions in practice
Django does not look for another port when 8000 is taken, and the same number is the default for php artisan serve and Laravel Octane. A Python project and a PHP project on one Mac therefore collide on the first day. The failure itself is clean: runserver prints that the port is in use and exits. The trap comes after it. A browser tab already open on localhost:8000 still loads, but it now talks to the other project’s server. After a failed start, check what answers on 8000 before you debug your own settings.
Frequently asked questions
Does Django’s runserver pick another port when 8000 is in use?
No. In Django’s source, an address-in-use error is mapped to the message “That port is already in use.”, written to stderr with an Error: prefix, and the process exits with status 1. Start it again with a different addrport, such as python manage.py runserver 8001.
How do I reach runserver from my phone or another computer?
Give runserver an address that is not the default. The default, 127.0.0.1, is not reachable from other machines. Use python manage.py runserver 0.0.0.0:8000 (or 0:8000). In a new project ALLOWED_HOSTS is empty, and Django rejects a request that uses your machine’s IP address with a DisallowedHost error until you add that address to ALLOWED_HOSTS in settings.py. Anyone on the same network can then request the site, so use it on a network you trust.
How do I run runserver on IPv6?
Pass -6 to change the default address from 127.0.0.1 to ::1, or give an IPv6 address in brackets, for example python manage.py runserver "[::1]:8001". Quote the argument in zsh, where square brackets are glob characters.
Sources
- Django: django-admin and manage.py, runserver (addrport, default 127.0.0.1:8000, --ipv6)
- Django tutorial part 1: changing the port and the 0 shortcut for 0.0.0.0
- django/django source (main): runserver maps address-in-use to “That port is already in use.” and exits with status 1
- Laravel 10.x installation: php artisan serve starts a server at http://localhost:8000
- Laravel Octane: default port 8000
Busy ports in Rig
When a start fails because a port is taken, Rig shows which process owns it when it can, and lets you reclaim the port or choose another. You do not need Rig to use this page.