HTTP Request Headers Explained: What Each One Leaks About You

A working reference to the HTTP request headers your browser sends on every request. What each one means, what it reveals, and how to read the chain when a corporate proxy, VPN, or CDN sits in the path.

·8 min read·by ToolsWalla·
networkinghttpsecurityprivacytutorial

Every HTTP request your browser sends carries a small block of metadata called request headers. Most users never see them, but they describe who is asking, where the request came from, and which intermediaries touched it on the way. When something is wrong (the server logs a different IP than the one in your account profile, a corporate filter is silently blocking part of a page, a CDN is caching the wrong thing), the answer is almost always in the headers.

This post is a working reference for the common ones. Open the HTTP Headers Inspector in another tab if you want to see your own values while you read.

The identity headers

User-Agent is the oldest and noisiest identity header. Originally one short string, it now reads like a stack trace. A typical Chrome on Windows looks like:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36

Every fragment is a historical lie kept alive for compatibility. Real Chrome is not Mozilla, not Safari, and not WebKit any more. Each token exists because some server at some point checked for it.

Sec-Ch-Ua, Sec-Ch-Ua-Platform, Sec-Ch-Ua-Mobile are the modern Chromium replacement. They split the same information into typed key-value fields. Sec-Ch-Ua: "Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147" is the structured equivalent of the User-Agent string above. Firefox and Safari do not send these. The "Sec-Ch-" prefix is fixed by the spec and means "secure client hint", a hint the server cannot spoof out of an iframe.

Accept-Language is the most under-appreciated leak in this list. en-US,en;q=0.9,hi;q=0.8 tells every site you visit that you read US English first, generic English second, and Hindi third. That is enough to narrow down a region or first language with high accuracy, even when the IP says something else. There is no easy way to suppress it without breaking sites that depend on locale negotiation.

The where-from headers

Referer records the page you came from. The misspelling is original to RFC 1945 and was never corrected. Modern browsers default to a referrer-policy of strict-origin-when-cross-origin, which means cross-origin requests carry only the origin (https://example.com) and not the full URL. Within the same origin the full URL is still sent.

Origin is set on cross-origin requests and form submissions. It carries only the scheme, host, and port. Servers that implement CORS read it to decide whether to accept the request.

Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User are a newer set of metadata headers that describe the request from the browser side: was this a top-level navigation or a sub-resource fetch, was it triggered by a user click or by a script, is it same-origin or cross-site. Servers can use them to reject suspicious sub-resource requests without parsing the rest. Sec-Fetch-Site: cross-site plus Sec-Fetch-Mode: no-cors plus Sec-Fetch-Dest: image is what an image-leech embed looks like.

The content negotiation headers

Accept lists which response types the browser can handle and at what priority. text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 translates to: HTML if you have it, image/webp if you have it, anything else as a last resort.

Accept-Encoding lists compression formats. Modern browsers send gzip, br, zstd. The server picks the best one it supports. Mismatches here are a common cause of "the page works in Chrome but is garbled in this older client" issues.

Content-Type and Content-Length describe the request body. They are present on POSTs and PUTs, absent on GETs.

The caching headers

Cache-Control carries directives in either direction. On a request, no-cache tells intermediaries not to serve a cached response without revalidating. no-store is stronger and means do not write to any cache.

If-None-Match and If-Modified-Since are conditional request headers. The browser sends them when it has a cached copy and wants the server to confirm whether anything changed. The server replies with 304 Not Modified if nothing did. This is the foundation of HTTP caching.

Pragma: no-cache is a legacy header that means the same thing as Cache-Control: no-cache. Browsers send it for compatibility with old proxies.

The proxy and CDN headers

This is where most real diagnostic value lives. Every intermediary between your browser and the server can add headers, and reading them is how you reconstruct the path.

X-Forwarded-For is the most common chain header. Each proxy appends the IP of its caller. X-Forwarded-For: 49.37.114.185, 116.50.59.202 means the original client was 49.37.114.185, the request hit a proxy, and the proxy at 116.50.59.202 forwarded it on. Reading left to right gives you the path. The rightmost entry is the proxy you are talking to directly. Servers should trust only the entries written by hops they control.

X-Real-Ip is the same idea simplified to one value: the IP the most recent trusted proxy saw the request come from. nginx commonly sets this.

Cf-Connecting-Ip and Cf-Ipcountry are Cloudflare-specific. When a site is fronted by Cloudflare these are the canonical fields for client IP and ISO country code. Cf-Ray is the unique trace id for that edge node, useful when filing a Cloudflare support ticket.

X-Vercel-Ip-Country, X-Vercel-Ip-City, X-Vercel-Ip-Country-Region, X-Vercel-Ip-Timezone, X-Vercel-Ip-Latitude, X-Vercel-Ip-Longitude are the same idea on Vercel. They are added to every request that hits a Vercel edge function and are how this site knows where you are.

X-Forwarded-Proto says whether the original client request was http or https. Useful in container deployments where the application server speaks plain http internally and the load balancer terminates TLS.

Cdn-Loop is added by CDNs to detect routing loops between providers. A request that has Cdn-Loop: cloudflare already on it should not be forwarded to Cloudflare again. Harmless to see, but informative when debugging multi-CDN setups.

Via names the intermediary itself. Corporate web filters use this header to advertise their vendor and version. If you see one of these you know which appliance is sitting between you and the internet:

  • websense or forcepoint mean Forcepoint Web Security
  • bluecoat or proxysg mean Symantec Blue Coat (Broadcom)
  • zscaler means Zscaler ZIA
  • mcafee means McAfee Web Gateway
  • squid means open-source Squid

A header like Via: 1.1 hosted.websense 61c is unambiguous: that request just passed through a Forcepoint deployment.

Cookies

Cookie is its own category, large enough to deserve a separate post. The short version: cookies are key-value pairs scoped to a domain that the browser attaches to every matching request. They are how sites recognize you across requests. They are also the largest single source of header bloat. A request with ten third-party cookies can easily push the request header block past 4 KB. Servers commonly reject requests with cookie headers above 8 KB with HTTP 431 Request Header Fields Too Large.

The HTTP Headers Inspector redacts cookie values by default to keep them out of accidental screenshots. It still reports the size so you can spot oversized cookie headers.

What can you do with all of this

A few real cases where reading request headers solves the problem in seconds:

  • "The server logs an IP from another country, but I am at home." Look at X-Forwarded-For and Cf-Connecting-Ip. If your home ISP has rotated your IP or you are on a corporate VPN, the headers will show you the real path.
  • "The site loads in Chrome but not from our office." Look for a Via header. If it names Forcepoint, Zscaler, or BlueCoat, your office filter is involved. Compare which destination URL gets blocked between Chrome and a curl from outside the office.
  • "The page is being served stale." Look at Cache-Control and Age. An Age header above your supposed TTL means a CDN edge is holding an old copy.
  • "Login keeps logging me out." Look at the cookie size. If it is approaching 4 KB, some cookies are growing on every request and you are bumping up against limits.

The headers are always there. Most of the time they tell you exactly what is going on. The hard part is just looking at them.

Related tools on ToolsWalla