Skip to main content

Python Django: How to Resolve "DisallowedHost at / Invalid HTTP_HOST Header" in Python Django

When deploying a Django application, or even running one locally with a non-standard configuration, you may encounter the error DisallowedHost at / Invalid HTTP_HOST header. This is Django's security mechanism preventing your application from responding to requests with unrecognized hostnames.

In this guide, we'll explain why this error occurs, show you exactly how to fix it, and cover best practices to keep your application secure while resolving the issue.

What Does This Error Look Like?

When this error is triggered, Django displays a page like this (in debug mode):

DisallowedHost at /
Invalid HTTP_HOST header: 'your-domain.com'. You may need to add 'your-domain.com' to ALLOWED_HOSTS.

In production (with DEBUG = False), visitors will see a generic 400 Bad Request error instead.

Why Does This Error Occur?

Django includes a security feature called ALLOWED_HOSTS that validates the Host header of every incoming HTTP request. This prevents HTTP Host header attacks, where an attacker sends a request with a forged hostname to exploit your application.

The error occurs when the hostname in the incoming request doesn't match any entry in the ALLOWED_HOSTS list in your settings.py file. Common triggers include:

  • Deploying to a server without updating ALLOWED_HOSTS from the default empty list.
  • Using a reverse proxy (like Nginx or Apache) that forwards requests with a different hostname.
  • Accessing via IP address (e.g., 192.168.1.100) when only domain names are listed.
  • Running locally on a port other than the default, or accessing via 0.0.0.0.
  • Setting DEBUG = False: Django enforces ALLOWED_HOSTS strictly when debug mode is off.
info

When DEBUG = True and ALLOWED_HOSTS is empty, Django automatically allows localhost, 127.0.0.1, and [::1]. Once you set DEBUG = False, you must configure ALLOWED_HOSTS explicitly.

How to Fix It

Step 1: Open Your settings.py File

The ALLOWED_HOSTS setting is located in your project's main settings file, typically at myproject/settings.py.

Step 2: Add Your Hostnames

Add every domain name, subdomain, and IP address that your application should respond to:

# myproject/settings.py

ALLOWED_HOSTS = [
'www.example.com', # Your primary domain
'example.com', # Domain without www
'192.168.1.100', # Server IP address (if accessed directly)
'localhost', # Local development
'127.0.0.1', # Loopback address
]

Step 3: Save and Restart Your Server

After modifying ALLOWED_HOSTS, restart your Django server for the changes to take effect:

# Development server
python manage.py runserver

# Gunicorn
sudo systemctl restart gunicorn

# Or if running directly
gunicorn myproject.wsgi:application --reload

Configuration Options Explained

Specific Domain Names

List each domain and subdomain explicitly. This is the most secure approach:

ALLOWED_HOSTS = [
'example.com',
'www.example.com',
'api.example.com',
]

Wildcard Subdomains

To allow all subdomains of a domain, prefix the domain with a dot:

ALLOWED_HOSTS = [
'.example.com', # Matches example.com, www.example.com, api.example.com, etc.
]

This is equivalent to listing every possible subdomain individually.

IP Addresses

If your server is accessed directly by IP (common during development or on internal networks), include the IP:

ALLOWED_HOSTS = [
'10.0.0.5',
'192.168.1.100',
]

Allow All Hosts (Wildcard *)

Using '*' allows requests from any hostname:

ALLOWED_HOSTS = ['*']
Security Warning

Never use '*' in production. This disables Host header validation entirely, making your application vulnerable to HTTP Host header attacks. Only use this for quick local testing or in environments where another layer (like a reverse proxy) handles host validation.

Environment-Specific Configuration

In real projects, your ALLOWED_HOSTS should differ between development and production. Here are two common patterns:

Using Environment Variables

import os

ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')

Then set the environment variable on your server:

# In your .env file or server configuration
export DJANGO_ALLOWED_HOSTS="example.com,www.example.com,192.168.1.100"

Using Separate Settings Files

# settings/base.py
ALLOWED_HOSTS = []

# settings/development.py
from .base import *
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

# settings/production.py
from .base import *
ALLOWED_HOSTS = ['example.com', 'www.example.com']

Common Scenarios and Fixes

Behind a Reverse Proxy (Nginx, Apache)

When using a reverse proxy like Nginx in front of Gunicorn or uWSGI, the proxy forwards requests to Django. You need to ensure the Host header is passed correctly and the hostname is in ALLOWED_HOSTS.

Nginx configuration:

server {
server_name example.com www.example.com;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Django settings:

ALLOWED_HOSTS = ['example.com', 'www.example.com']

Docker Containers

In Docker environments, you may access Django via the container's IP or a Docker network hostname:

ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'0.0.0.0', # Common in Docker
'web', # Docker service name
'example.com', # Production domain
]

Elastic Beanstalk, Heroku, or Cloud Platforms

Cloud platforms assign dynamic hostnames. You'll typically need to include both the platform's hostname and your custom domain:

# Heroku example
ALLOWED_HOSTS = [
'your-app-name.herokuapp.com',
'example.com',
'www.example.com',
]

Debugging Tips

If you've added the hostname but the error persists, try these steps:

1. Check the exact hostname in the error message:

The error tells you precisely which host header was received. Copy it exactly as shown:

Invalid HTTP_HOST header: 'example.com:8080'

In this case, the port is included. You may need to add the hostname with the port, or configure your proxy to strip it.

2. Print ALLOWED_HOSTS to verify your settings loaded correctly:

# Temporarily add to your view or settings
print(f"ALLOWED_HOSTS = {ALLOWED_HOSTS}")

3. Check for typos and extra whitespace:

# ❌ Common mistake: extra space
ALLOWED_HOSTS = ['example.com ', ' www.example.com']

# ✅ Correct: no extra whitespace
ALLOWED_HOSTS = ['example.com', 'www.example.com']

4. Ensure you're editing the right settings file:

If your project uses multiple settings files (e.g., settings/production.py), make sure you're editing the one that's actually active:

echo $DJANGO_SETTINGS_MODULE

Quick Reference

ScenarioALLOWED_HOSTS Value
Local development['localhost', '127.0.0.1']
Single domain['example.com', 'www.example.com']
All subdomains['.example.com']
IP access['192.168.1.100']
Docker['0.0.0.0', 'localhost', 'web']
Behind reverse proxyDomain names that Nginx/Apache forwards
Testing only (insecure)['*']

Conclusion

The DisallowedHost at / Invalid HTTP_HOST header error is Django's built-in protection against HTTP Host header attacks.

The fix is straightforward: add the correct domain names, subdomains, and IP addresses to the ALLOWED_HOSTS list in your settings.py file, then restart your server.

For production deployments, always list specific hostnames rather than using the wildcard '*', and consider using environment variables to manage different configurations across development, staging, and production environments.