Updated 9 hours ago
A URL can point at a resource, but it can't ask for JSON instead of XML. It can't prove you're logged in. It can't remember that you were here yesterday. It can't even say which website you want when multiple sites share an IP address.
Request headers solve this. They transform a dumb pointer into a sophisticated conversation between client and server.
How Headers Give Requests a Voice
When you request https://api.example.com/users/123, the URL specifies what you want. But it says nothing about:
- Whether you want JSON or XML
- Whether you're authenticated
- What language you prefer
- Whether you have a cached version
- What browser you're using
Headers fill these gaps. They're the difference between pointing at something and actually communicating about it.
The Headers Every Request Needs
Host: Which Door Are You Knocking On?
This header is mandatory in HTTP/1.1, and here's why: a single IP address can host hundreds of websites. When your request arrives at that IP, the server needs to know which site you want. The Host header is your answer.
Even though the hostname appears in your URL, it's sent again as a header because the raw HTTP message needs it explicitly.
User-Agent: Who's Asking?
This identifies your browser or application. Servers use it for analytics, compatibility decisions, bot detection, and mobile optimization.
The User-Agent string has become a museum of browser history. Modern browsers still claim to be "Mozilla" because in 1996, Netscape (Mozilla) got served richer content, and every browser since has had to maintain the lie to avoid being served dumbed-down pages. We're still living with that deception.
Modern web development generally avoids User-Agent sniffing in favor of feature detection, but the header persists everywhere.
Accept: What Can You Handle?
This header enables content negotiation—a single URL returning different formats based on what you prefer. The q values indicate preference: HTML is most preferred (implicit q=1.0), XML less so (q=0.9), anything else least (q=0.8).
An API endpoint might return JSON to your JavaScript app and XML to a legacy system, same URL, different conversation.
Accept-Language: What Do You Speak?
This tells the server: "I prefer US English, but any English works, and Spanish is acceptable." Websites use this to automatically display content in your language without asking.
Accept-Encoding: How Compressed Can You Go?
Modern browsers support multiple compression algorithms. By advertising what you can decompress, you let the server shrink responses dramatically—a 100KB HTML file might compress to 20KB with gzip.
Proving Who You Are
Authorization: Your Credentials
This header carries proof of identity. Common schemes:
- Basic: Username and password in Base64 (only safe over HTTPS)
- Bearer: Tokens from OAuth 2.0 or JWT
- Digest: Cryptographic hash of credentials
- API Key: Custom schemes for programmatic access
Invalid credentials get you a 401 Unauthorized response.
Cookie: Your Memory
HTTP is stateless—each request is independent, with no memory of previous ones. Cookies fix this. When a server sets a cookie, your browser stores it and automatically includes it in future requests to that domain.
This is how websites remember you're logged in, remember your preferences, and track your behavior across pages.
Caching: Don't Send What I Already Have
If-Modified-Since
This says: "I have a version from this date. Only send a new one if it's changed."
If unchanged, the server returns 304 Not Modified with no body. Your browser uses its cached copy. Bandwidth saved.
If-None-Match
ETags (entity tags) are more precise than timestamps. The server assigns each version a unique identifier. If your cached ETag matches the current one, the content hasn't changed—304, use your cache.
Security: Where Did You Come From?
Origin
This header is central to CORS (Cross-Origin Resource Sharing) security. When JavaScript on one domain tries to fetch data from another, the browser includes the Origin header. The server checks it and decides whether to allow access.
Critically, JavaScript cannot fake this header. The browser sets it automatically for cross-origin requests, preventing malicious sites from impersonating trusted ones.
Referer
Note the misspelling—it's been standardized this way since the original HTTP spec typo.
This header tells the server which page linked to the current request. Useful for analytics (where's traffic coming from?), security (did this request originate from an expected page?), and navigation context.
Privacy concerns have led to the Referrer-Policy header, which controls how much of this information gets shared.
Connection Management
Connection and Keep-Alive
Opening a TCP connection is expensive—multiple round trips just to establish the channel. HTTP/1.1 defaults to keeping connections open so multiple requests can flow through a single connection.
Connection: close tells the server you're done and it can drop the connection after responding.
Partial Requests: Just Give Me Part of It
Range
This requests only a portion of a resource. Essential for:
- Resumable downloads: Pick up where a failed download left off
- Video streaming: Request small chunks progressively
- Large file handling: Read just the header of a huge file
The server responds with 206 Partial Content and the requested bytes.
When Proxies Get Involved
X-Forwarded-For
When your request passes through proxies or load balancers, the server sees the proxy's IP, not yours. This header preserves the chain—the leftmost IP is the original client. Critical for security logging, rate limiting, and geolocation.
X-Forwarded-Proto
Load balancers often handle HTTPS externally and forward requests to backend servers over plain HTTP. This header tells the backend that the original connection was secure, so it generates HTTPS URLs and enforces security policies correctly.
Custom Headers: Extending the Conversation
Applications add custom headers for:
- Request tracing: Unique IDs that follow a request through distributed systems
- API versioning: Requesting specific API versions
- Feature flags: Enabling experimental features
- Client metadata: App-specific information
The "X-" prefix is deprecated for new headers, but legacy systems are full of them.
Frequently Asked Questions About Request Headers
Was this page helpful?