Host general request
Specifies which host and port the client wants to reach — the only mandatory HTTP/1.1 request header.
What it does
Host tells the server which hostname and port the client wants to reach. It's the only header that is mandatory in HTTP/1.1 requests — a request without Host must be rejected with 400 Bad Request.
The reason it exists: a single server's IP address can host thousands of websites (virtual hosting). When a request arrives, the IP address alone doesn't tell the server which site is being requested. Host provides that disambiguation — the server inspects it and routes the request to the correct site.
Syntax
Host: <hostname>
Host: <hostname>:<port>
Port is only included if it's non-standard (i.e., not 80 for HTTP or 443 for HTTPS):
Host: example.com
Host: api.example.com
Host: example.com:8080
Host: localhost:3000
Why it's mandatory
Before HTTP/1.1 (1997), HTTP/1.0 had no Host header. Every server had its own IP address — one IP, one site. This was fine when the internet was small. As the web grew, IP address exhaustion became a real concern, and the model of "one IP per website" became impractical.
HTTP/1.1 introduced Host as a mandatory header precisely to enable name-based virtual hosting: one IP address, one web server, thousands of domains. Nginx, Apache, and every modern web server use Host to route requests to the right virtual host configuration.
Virtual hosting in practice
A server at IP 203.0.113.1 might host:
example.com
blog.example.com
api.example.com
another-site.com
All four requests arrive at the same IP. The Host header tells the server which site to serve:
GET /about HTTP/1.1
Host: blog.example.com
vs.
GET /about HTTP/1.1
Host: another-site.com
Without Host, both requests are identical at the network layer and the server can't distinguish them.
HTTP/2 and HTTP/3
In HTTP/2 and HTTP/3, Host is replaced by the :authority pseudo-header (part of the binary framing layer). However, Host is still accepted for compatibility. HTTP/2 frames carry :authority: example.com in the HEADERS frame rather than a Host: header line — it's the same concept, different wire format.
Host and security
Host header injection. Some applications use the Host header to generate URLs (password reset links, absolute redirect URLs). If the server trusts a user-supplied Host without validation, an attacker can send a forged Host: evil.com and the app generates links to evil.com in legitimate-looking emails — a host header injection attack.
Mitigation: always validate Host against an allowlist of known good values. Most frameworks do this, but custom routing logic can have gaps.
Routing in load balancers and reverse proxies. Load balancers use Host to route traffic. If a request arrives with an unexpected Host, it may be routed to the wrong backend or rejected. When debugging routing issues, always check what Host value is being forwarded.
Common mistakes and gotchas
Forgetting Host on raw HTTP/1.1 requests. When hand-crafting HTTP requests (with netcat, raw socket code, or testing tools), forgetting Host causes immediate 400 Bad Request. It's the most common mistake when building low-level HTTP clients from scratch.
Mismatched Host in development. Running a service on localhost:3000 but proxying through nginx with a different host? The proxied Host header may not match what your app expects. Use proxy_set_header Host $host; in nginx to forward the original host.
Ports in Host for HTTPS. Host: example.com:443 is technically correct but unusual — port 443 is the default for HTTPS and is normally omitted. Some servers handle this gracefully; others may not match the virtual host correctly. Stick to Host: example.com for standard HTTPS.
Real-world examples
Standard browser request:
GET /docs HTTP/1.1
Host: developer.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Non-standard port (local development):
GET /api/users HTTP/1.1
Host: localhost:8080
Content-Type: application/json
400 response for missing Host:
GET /index.html HTTP/1.1
HTTP/1.1 400 Bad Request
Content-Type: text/html
400 Bad Request: Missing Host header
FAQ
Can there be multiple Host headers?
No — Host must appear exactly once. A request with multiple Host headers (or a Host with a comma-separated list) is malformed. Servers must reject it with 400 Bad Request. This is also a security concern — some proxies may handle multiple Host headers inconsistently, enabling host header smuggling attacks.
Does Host matter for HTTPS?
Yes, but TLS adds SNI (Server Name Indication) at the handshake level, which serves a similar purpose — telling the server which certificate to present before the HTTP layer begins. For HTTPS virtual hosting, both SNI (at the TLS layer) and Host (at the HTTP layer) need to be correct.
What happens if Host doesn't match any virtual host?
The server either serves a default site (usually the first configured virtual host) or returns 400/404. nginx and Apache both have a "default server" concept for requests with unrecognised Host values. This is also how you can catch misconfigured clients or scanning tools sending arbitrary Host values.
Fun fact
The Host header's mandatory status is unique in HTTP — it's the only request header the spec requires servers to reject if absent. This reflects just how fundamental virtual hosting became to the web. Before Host, roughly 1996–1997, every website needed its own IP address. The IPv4 address space would have been exhausted years earlier if virtual hosting hadn't been invented. A single mandatory HTTP header is a big part of why we didn't run out of IP addresses in the early 2000s.