`uvicorn --host 0.0.0.0` Is the Flag You Need When Your FastAPI App Works Locally and Is Still Invisible From Everything Else
A practical guide to Uvicorn host binding for developers whose app works in the browser on the same machine but cannot be reached from Docker, phones, reverse proxies, or other hosts.
Why this flag matters: one of the most common fake backend bugs is a perfectly healthy app listening only where nobody else can reach it.
This problem shows up everywhere: Docker, local LAN testing, remote servers, VM-based development, reverse proxies, and mobile testing. The developer says, "The app works on my machine." That part is true. The missing detail is that it only works from the same machine because the process is bound to loopback.
The usual mistake
A developer launches the app like this:
uvicorn app.main:app --reloadThen visits it locally and sees everything working.
By default, that process commonly listens on 127.0.0.1, which means:
- the same host can reach it
- another machine on the network cannot
- a container or proxy may not be able to
- the service appears "up" while still being unreachable from the place that matters
The fix
Bind to all interfaces:
uvicorn app.main:app --host 0.0.0.0 --port 8000Now the process listens on all network interfaces available to that machine.
This does not magically override firewalls, security groups, or Docker networking, but it removes one extremely common blocker.
Situations where this matters most
This flag is especially relevant when:
- your API is running inside Docker
- you want to test from your phone on the same Wi-Fi
- nginx or Caddy should proxy to the app
- another container needs to call the service
- the app lives on a remote VM
In all of those cases, binding only to 127.0.0.1 is often the reason outside clients see nothing.
How to verify what is actually listening
On Linux, you can confirm the bind address with:
ss -ltnp | grep 8000If you see 127.0.0.1:8000, that explains the invisibility problem. If you see 0.0.0.0:8000, the app is listening broadly enough and you can move on to the next network layer.
That next layer might be:
- Docker port publishing
- host firewall rules
- cloud firewall or security group settings
- reverse-proxy configuration
But the important thing is that you stop blaming CORS or FastAPI routing before checking whether the server is reachable at all.
A common Docker example
If you run FastAPI in Docker, the host flag and published port usually go together:
docker run -p 8000:8000 my-fastapi-imageInside the container, your app still needs:
uvicorn app.main:app --host 0.0.0.0 --port 8000Publishing the port without changing the bind address often creates a container that looks mapped correctly and still cannot serve traffic from outside itself.
Final recommendation
If your FastAPI app works only on the same machine and nowhere else, check the bind address before you start chasing fancier explanations. uvicorn --host 0.0.0.0 is often the missing line between "the app runs" and "the app is actually reachable."