LookMyIPLookMyIP
Blog/HTTP Headers Explained: What They Reveal About You
Privacy7 min read

HTTP Headers Explained: What They Reveal About You

By LookMyIP Editorial

Learn what HTTP headers are, what information they contain, which headers reveal personal data, and how to check and control your HTTP header footprint.

What Are HTTP Headers?

HTTP headers are metadata sent along with every HTTP request and response. When your browser requests a webpage, it sends headers containing information about itself, what content it can accept, and any stored cookies. The server responds with headers describing the content, caching policies, and security directives.

Headers are invisible during normal browsing — you don't see them in the page content. But they carry a surprising amount of information about you and your setup. Use LookMyIP's HTTP Headers tool at lookmyip.com/headers to see exactly what headers your browser sends.

Request Headers Your Browser Sends

Every time your browser makes a request, it sends headers like these:

User-Agent: Identifies your browser, version, and operating system. Example: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36". This single header reveals your OS, browser, version, and device type.

Accept-Language: Lists your preferred languages (e.g., "en-US,en;q=0.9,es;q=0.8"), revealing your nationality and language preferences.

Accept-Encoding: Tells the server what compression formats your browser supports (gzip, br, deflate).

Referer: Shows the URL of the page you came from, allowing the destination site to track where you were before. Note: the header name is intentionally misspelled — the typo was baked into the HTTP specification in 1996.

Cookie: Sends stored cookies for the domain, which may include session IDs, tracking identifiers, and preferences.

DNT (Do Not Track): A header requesting not to be tracked. Unfortunately, this is largely ignored by most websites and is being deprecated.

Sec-CH-UA (Client Hints): Modern browsers send detailed "client hint" headers that provide structured information about browser version, platform, and device characteristics.

Important Response Headers

Content-Type: Tells the browser what type of content it's receiving (text/html, application/json, image/png, etc.) and the character encoding.

Set-Cookie: Tells the browser to store a cookie. This is how sites maintain sessions and track users across visits.

Cache-Control: Dictates how long the browser should cache the response. Proper caching reduces server load and speeds up page loads.

Content-Security-Policy (CSP): A critical security header that restricts where the page can load resources from, preventing cross-site scripting (XSS) attacks.

Strict-Transport-Security (HSTS): Tells the browser to only connect to this site over HTTPS for a specified period, preventing downgrade attacks.

X-Frame-Options: Prevents the page from being embedded in iframes, protecting against clickjacking attacks.

X-Content-Type-Options: nosniff: Prevents the browser from MIME-type sniffing, ensuring it respects the declared Content-Type.

HTTP Headers and Privacy

Your HTTP headers contribute to your browser fingerprint — a combination of characteristics that can uniquely identify you even without cookies:

  • User-Agent string identifies your exact browser version and OS
  • Accept-Language reveals your language and likely nationality
  • Referer reveals your browsing path across sites
  • Client Hints provide detailed device information
  • Accept header variations differ between browsers

When combined with other fingerprinting techniques (canvas fingerprinting, WebGL, screen resolution, installed fonts), HTTP headers help tracking services identify and follow you across websites — even in private browsing mode.

How to reduce your header footprint:

  • Use Firefox with Enhanced Tracking Protection, which limits the User-Agent string
  • Install browser extensions like uBlock Origin that can strip or modify headers
  • Use a VPN to hide your IP from the header analysis
  • Consider the Tor Browser for maximum header uniformity
  • Check what your browser reveals using LookMyIP's HTTP Headers tool

Security Headers That Actually Matter

Security header checklists tend to list a dozen headers as equally important. They are not. Four do most of the work, and two commonly recommended ones are now obsolete.

Content-Security-Policy is by far the most valuable and the hardest to deploy. It tells the browser which sources of script, style and other resources are permitted, which turns most cross-site scripting from a compromise into a blocked console error.

The modern approach uses nonces rather than source allowlists, because allowlists containing a CDN are trivially bypassed:

Content-Security-Policy:
  default-src 'self';
  script-src 'nonce-{random}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
  frame-ancestors 'none'

Each <script> tag carries the matching nonce attribute, regenerated per request. strict-dynamic lets a trusted script load further scripts, which is what makes bundlers and analytics work.

Deploy it in report-only mode first — Content-Security-Policy-Report-Only with a report-uri — and read the violations for a week before enforcing. Enforcing a policy written from theory will break your site.

Strict-Transport-Security forces HTTPS for a period, preventing downgrade attacks and stripping.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Be careful with includeSubDomains: it applies to every subdomain including internal ones that may not have certificates. And preload submits your domain to a list hardcoded into browsers, which is effectively irreversible for months.

X-Content-Type-Options: nosniff stops the browser guessing content types, which prevents an uploaded file from being executed as script. One line, no downside, deploy it everywhere.

Referrer-Policy: strict-origin-when-cross-origin stops full URLs, which frequently contain tokens and identifiers, leaking to third parties.

Two to skip: X-XSS-Protection is deprecated and its filter caused vulnerabilities of its own — set it to 0 or omit it. X-Frame-Options is superseded by CSP's frame-ancestors, though it remains harmless to keep for very old clients.

Caching Headers and Why Pages Go Stale

Caching is where headers most often cause visible bugs, usually of the form "I deployed a fix and users still see the old version".

Three headers control it, and only one of them is really needed.

Cache-Control is the modern, authoritative header. The directives that matter:

Cache-Control: public, max-age=31536000, immutable

for versioned static assets — a file named app.a3f9c2.js will never change, so cache it for a year and tell the browser not to even revalidate.

Cache-Control: no-cache

for HTML. Despite the name, this does not mean "do not cache". It means "cache, but revalidate before every use". The directive that genuinely prevents storage is no-store, which is what you want for pages containing personal data.

Cache-Control: private, max-age=0, must-revalidate

for authenticated pages, where private prevents shared caches and CDNs from storing a response meant for one user.

ETag and Last-Modified enable conditional requests. The browser sends If-None-Match with the stored ETag, and the server replies 304 Not Modified with no body if nothing changed — saving bandwidth while still confirming freshness.

Expires is the HTTP/1.0 predecessor of max-age and is ignored when Cache-Control is present. There is no reason to set it in new deployments.

The pattern that avoids nearly all cache problems is cache-busting by filename: give static assets a content hash in the name and cache them permanently, while serving the HTML that references them with no-cache. A deployment changes the HTML, which is always revalidated, and the HTML points at new asset filenames, which are fetched fresh. Nothing is ever stale and nothing is ever needlessly re-downloaded.

Inspect what a site actually sends with the HTTP header checker or:

curl -sI https://example.com | grep -i 'cache-control\|etag\|expires'

Headers, Proxies and the Real Client IP

Once a request passes through a CDN or load balancer, the connection your application sees originates from the proxy, not the user. Recovering the real client address is a common requirement and a common source of security bugs.

X-Forwarded-For is the long-standing convention. Each proxy appends the address it received the connection from, producing a chain:

X-Forwarded-For: 203.0.113.5, 198.51.100.10, 172.16.0.3

The leftmost entry is nominally the original client. It is also entirely attacker-controlled. Anyone can send a request with a forged X-Forwarded-For header, and if your application trusts the leftmost value for rate limiting, geolocation or access control, it can be trivially bypassed.

The correct approach is to count from the right. If you know there are exactly two trusted proxies in front of you, the real client is the third entry from the right; everything to the left of your trusted set is unverified user input. Most frameworks expose this as a "trusted proxy count" or "trusted proxy list" setting, and configuring it is not optional.

Forwarded (RFC 7239) is the standardised replacement, carrying protocol and host as well:

Forwarded: for=203.0.113.5; proto=https; host=example.com

It has the same trust properties and the same requirement to validate the chain.

Vendor-specific headers are safer where available, because the CDN sets them and strips any client-supplied version: Cloudflare's CF-Connecting-IP, AWS ALB's X-Forwarded-For behaviour with a fixed proxy count, and Fastly's Fastly-Client-IP.

Related headers matter for correctness rather than security. X-Forwarded-Proto tells your application whether the original request was HTTPS, which is what stops an application behind a TLS-terminating proxy from generating http:// redirect URLs and creating a redirect loop. X-Forwarded-Host preserves the original Host header, without which generated absolute URLs point at the internal hostname.

Frequently Asked Questions

Are custom headers starting with X- still recommended?

No. RFC 6648 deprecated the X- convention in 2012 because headers that became standard were stuck with a prefix implying they were experimental. Use a descriptive name without the prefix for new custom headers. Existing ones like X-Forwarded-For remain in use for compatibility.

Do response headers affect SEO?

Some do, meaningfully. X-Robots-Tag controls indexing at the header level and is the only way to apply directives to non-HTML files like PDFs. Link: rel="canonical" sets a canonical URL for resources that cannot carry a <link> element. Caching headers affect crawl efficiency. Security headers do not directly affect ranking, though HTTPS itself is a minor signal.

Why do I see different headers in the browser than with curl?

Content negotiation. The browser sends Accept-Encoding, Accept-Language and a full User-Agent, and servers and CDNs vary their response accordingly. Add -H 'Accept-Encoding: gzip' and a browser user agent to curl to see comparable output. A CDN cache hit versus miss also changes headers.

Can I hide the Server header?

Yes, and it is worth doing. Removing version information from Server and X-Powered-By does not stop a determined attacker, who can fingerprint by behaviour, but it removes you from automated scans that search for specific vulnerable versions. In nginx, server_tokens off; in Express, app.disable('x-powered-by').

How large can headers be?

There is no protocol limit, but servers impose one — typically 8KB total, sometimes 4KB per header. Exceeding it returns 431 Request Header Fields Too Large. Very large cookies are the usual cause, which is one argument for keeping session data server-side.

Try It Yourself

Use LookMyIP's free tools to look up IP addresses, check DNS records, verify SSL certificates, and more.