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.

Updated

Key facts

Default ports for Django runserver
PortProtocolRoleCategory
8000TCPmanage.py runserver development serverBackend

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

Port as the addrport argument
python manage.py runserver 8001

A bare number changes only the port. The address stays at the default, 127.0.0.1.

Address and port
python manage.py runserver 0.0.0.0:8001

0 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.

Read the port from the shell
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.

macOS (zsh)
lsof -nP -iTCP:8000 -sTCP:LISTEN
ps -p PID_NUMBER -o pid,ppid,user,command
kill -TERM PID_NUMBER
Linux (bash)
ss -ltnp 'sport = :8000'
ps -p PID_NUMBER -o pid,ppid,user,command
kill -TERM PID_NUMBER
Windows (PowerShell)
Get-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_NUMBER

Read 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

  1. Django: django-admin and manage.py, runserver (addrport, default 127.0.0.1:8000, --ipv6)Official documentation, checked 13 October 2026
  2. Django tutorial part 1: changing the port and the 0 shortcut for 0.0.0.0Official documentation, checked 13 October 2026
  3. django/django source (main): runserver maps address-in-use to “That port is already in use.” and exits with status 1Official documentation, checked 13 October 2026
  4. Laravel 10.x installation: php artisan serve starts a server at http://localhost:8000Official documentation, checked 13 October 2026
  5. Laravel Octane: default port 8000Official documentation, checked 13 October 2026

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.

Related

https://userig.app/ports/django