Every HTTP response carries a set of headers alongside the page content — metadata about caching, redirects, security policy, and server behavior that does not render on screen but determines how the page actually behaves. These headers are rarely inspected directly. When something is subtly wrong — a redirect loop, a caching bug, a missing security header — the headers are usually where the cause is found. Five of them are significant enough that this site's own HTTP header checker scores every domain against exactly these five; they are covered first, below.
The 5 Headers Worth Checking on Every Site
These are the headers behind the “Security headers” score on this site's own checker. Missing even one is common, but each addresses a real, well-understood attack rather than a theoretical one.
- strict-transport-security (HSTS) — forces HTTPS-only connections to this domain, and to every subdomain when
includeSubDomainsis set, for the specifiedmax-agein seconds, even when a user entershttp://. A missing HSTS header on an HTTPS site is a common and inexpensive gap to close. - x-frame-options — for example,
SAMEORIGIN: restricts embedding of this page in an iframe to pages on the same origin, the standard clickjacking defense (largely superseded today by CSP'sframe-ancestors, which a well-configured CSP also sets). - x-content-type-options: nosniff — prevents the browser from inferring a file's type differently than declared, closing off a class of content-sniffing attacks.
- referrer-policy — for example,
strict-origin-when-cross-origin: controls how much of this page's URL is sent as theRefererheader when a link is clicked — the full URL to same-origin destinations, only the origin to other sites, and nothing at all when navigating from HTTPS to HTTP. - content-security-policy (CSP) — a detailed allowlist specifying which origins scripts, styles, images, fonts, and frames may load from, a primary defense against cross-site scripting. A well-configured CSP names specific analytics, advertising, and chat vendors while blocking everything else by default (
object-src 'none',frame-ancestors 'none').
Status Codes: The First Thing to Check
- 200 — OK. The request succeeded and the response contains the requested content.
- 301 / 308 — permanent redirect. Search engines and browsers remember and reuse the new location going forward.
- 302 / 307 — temporary redirect. Treated as non-permanent; the original URL should still be checked on subsequent requests.
- 404 — not found. The server is reachable and functioning; the specific resource does not exist at this URL.
- 500 / 502 / 503 — server-side error. 500 indicates an application error; 502/503 usually indicate a proxy, load balancer, or upstream service problem rather than the application itself.
Redirect Chains
A single redirect (old URL to new URL) is normal and inexpensive. A chain of several redirects in sequence (A to B to C to D) is a common and often overlooked performance problem: each hop adds a full round trip before the browser begins loading the actual page, and search engines generally recommend keeping chains as short as possible — ideally a single hop. Inspecting the full redirect chain is one of the fastest ways to identify this.
Common Headers, Decoded
Beyond the five above, the following is a fuller reference of headers found on nearly any site, regardless of server or CDN, grouped by function.
Content and Transport
- content-type — the body's MIME type and character encoding, for example
text/html; charset=utf-8. Tells the browser how to parse and render the content that follows. - content-encoding — the compression algorithm used on the body, for example
brfor Brotli. The client decompresses the body using the same algorithm before reading it. - transfer-encoding: chunked — the response is streamed in pieces rather than sent as one fixed-length block, common when the server does not know the final size in advance.
- connection: keep-alive — an HTTP/1.1-era hint that the underlying TCP connection remains open for reuse instead of closing after this response. Largely irrelevant on HTTP/2 and HTTP/3, which multiplex many requests over one connection.
- date — when the server generated this specific response, according to its own clock.
- vary: accept-encoding — tells caches that the response can differ based on that request header, so a cache may need to store a separate copy per compression format a client accepts.
- alt-svc — advertises that the server also supports a newer protocol; for example,
h3=":443"; ma=86400indicates that HTTP/3 is available on port 443, and that this can be cached for 86,400 seconds (one day). - link — resource hints and related documents bundled into one header:
rel=preloadtells the browser to begin fetching a font or image early,rel=preconnectopens a connection to another origin in advance, and entries such asrel=sitemappoint to another document describing the site. - server — identifies the software or platform that handled the request, for example
nginxor a CDN's own name. A CDN or reverse proxy in front of the origin often shows its own name here rather than what the origin server is running. - via — lists every proxy or gateway the request passed through en route to the client; for example,
1.1 Caddyindicates a Caddy server handled it directly. Multiple comma-separated entries indicate multiple hops, most often a CDN in front of the origin.
Caching
- cache-control: public, max-age=10, s-maxage=10 —
publicindicates that any cache, browser or CDN, may store this response;max-age=10allows a browser to reuse its cached copy for 10 seconds;s-maxage=10gives shared caches such as a CDN their own 10-second limit, which overridesmax-agespecifically for them. - etag — a fingerprint of this exact response body. A client that already has this ETag cached can send it on the next request (
If-None-Match) and receive a 304 Not Modified response instead of downloading the same content again. - last-modified — when this resource last actually changed, according to the server. Works the same way as
etagbut as a timestamp instead of a content fingerprint: a client can send that date back (If-Modified-Since) and get a 304 Not Modified if nothing has changed since. Coarser than an ETag — it can't tell two versions apart if they changed within the same second — but cheaper for a server to generate, since it doesn't need to hash the response body.
Security and Privacy
Three additional security headers worth knowing, beyond the five covered at the top of this page:
- cross-origin-opener-policy — controls whether this page shares a browsing context, including
window.openeraccess, with cross-origin popups it opens.unsafe-noneis the permissive default, providing no isolation. - cross-origin-resource-policy — controls which other sites may directly load this resource, such as embedding an image from it.
cross-originpermits any site to do so. - permissions-policy — explicitly disables browser features for the page.
geolocation=(), camera=(), microphone=()means the empty allowlists block every origin, including the page itself, from requesting those features. - x-xss-protection — toggled the browser's built-in reflected-XSS filter in old versions of Chrome, Safari, and Internet Explorer (
1; mode=blockenabled it and blocked the page outright on detection). Deprecated and ignored by every current major browser, which removed that filter entirely in favor of content-security-policy — seeing this header today usually just means a security-headers checklist or an old server config template hasn't been updated, not that anything is misconfigured.
Cookies and Error Reporting
- nel (Network Error Logging) — instructs the browser to report connection-level failures, such as DNS errors or timeouts, for this origin to the endpoint named in
report-to. Asuccess_fractionof 0 means only failures are reported, never successful requests. - report-to — the reporting endpoint that
nel, and other browser reporting APIs, send those reports to.
CDN and Hosting Vendor Headers
Most sites of any size sit behind a CDN or managed hosting platform, and each stamps its own headers onto every response — mainly to answer one question: did this request hit cache, or go all the way back to the origin server. These are useful for debugging performance and caching issues specific to whichever vendor is in front of the site; the server header above is usually the first clue as to which one that is.
- cf-ray (Cloudflare) — a unique ID for this specific request, made of a hex request identifier and a short airport-style code for the Cloudflare data center that handled it (for example,
...-HYDfor Hyderabad). Cloudflare support asks for this ID when investigating a specific request. - cf-cache-status (Cloudflare) — whether Cloudflare's edge cache served this response:
HITcame from cache,MISSwas fetched from the origin and is now cached,DYNAMICmeans the content wasn't eligible for caching at all, andEXPIRED/STALEmean a cached copy existed but was past its freshness window. - cf-connecting-ip (Cloudflare) — the original visitor's IP address, preserved by Cloudflare for the origin server to read. Without it, the origin would only see Cloudflare's own edge IP as the source of every request.
- x-served-by (Fastly) — identifies the specific cache node (a name like
cache-lhr-etc) that served this response, useful for tracing which of a CDN's many points of presence a request landed on. - x-cache-hits (Fastly) — how many times this exact cached object has been served since it was last fetched from the origin; a rising number over repeated requests confirms caching is actually working, not just configured.
- x-cache (Fastly, Amazon CloudFront, and several others) — a simple
HIT/MISScache verdict, the same idea as Cloudflare'scf-cache-statusbut from a different vendor. Which vendor set it is usually clear from the accompanyingserverorviaheader, since the format itself isn't unique to any one of them. - x-amz-cf-id (Amazon CloudFront) — a unique per-request identifier, CloudFront's equivalent of Cloudflare's
cf-ray, needed when opening a support case with AWS about a specific request. - x-amz-cf-pop (Amazon CloudFront) — the CloudFront edge location (point of presence) that handled this request, for example
BOM50-P1for a Mumbai edge node. - x-vercel-id (Vercel) — a per-request trace ID encoding the region that handled the request, used when debugging a specific request with Vercel or reading its logs.
- x-vercel-cache (Vercel) — this deployment's own cache verdict:
HIT,MISS,STALE, orPRERENDERfor a page generated at build time — conceptually the same signal as Next.js's own x-nextjs-cache below, since Vercel is one of the platforms Next.js commonly deploys to.
Framework-Specific: Next.js
Sites built on Next.js add several of their own headers on top of standard HTTP ones, describing how that specific page was rendered and cached.
- x-nextjs-cache — indicates whether this response came from Next.js's own cache:
HITserved a cached copy,MISSindicates the page was rendered fresh, andSTALEindicates a cached copy was served while a fresh one regenerates in the background. - x-nextjs-prerender —
1indicates this page was statically generated at build time, or generated on demand and then cached, rather than rendered per request. - x-nextjs-stale-time — the number of seconds a cached copy of this page is served before Next.js regenerates it in the background, according to its revalidation settings.
Non-Standard and Application-Specific Headers
A short, unfamiliar x- header that doesn't match anything above isn't necessarily a mistake — nothing stops a server, framework, or internal application from setting its own custom headers, and the x- prefix has historically been the informal convention for exactly that (a header like x-rm is a short, custom name a specific application chose, not something defined by any HTTP standard or well-known vendor). There's no registry to look these up in the way there is for standard headers; the only reliable way to know what one means is to check the documentation, source code, or support channel of whichever service actually set it. If it doesn't affect caching, redirects, or the five security headers covered above, it's usually safe to ignore.
Response Time
Time-to-first-byte — how long the server took to begin responding — is a useful signal that is distinct from total page load time. It reflects server and backend performance specifically, before the browser has begun downloading, parsing, or rendering anything.
When to Check Headers
- Debugging a redirect loop or an unexpectedly long redirect chain.
- Confirming that basic security headers are present after a server or CDN configuration change.
- Investigating a stale-content report by checking whether Cache-Control is configured as expected.
- Verifying that a migration or DNS cutover did not leave the previous server still answering for the domain.
If headers show an unexpected server or an outdated redirect target after a migration, this is often a stale DNS record pointing at the wrong destination rather than a server misconfiguration, and should be ruled out first.
Frequently Asked Questions
Which headers actually matter for security?
Five in particular: strict-transport-security, x-frame-options, x-content-type-options, referrer-policy, and content-security-policy. These are the ones this tool's own security score is based on, and each addresses a specific, well-understood attack rather than a theoretical one.
Is a missing security header always a real problem?
Not necessarily urgent, but rarely worth ignoring — these headers are inexpensive to add and each closes off a specific attack class (clickjacking, MIME sniffing, cross-site scripting). A missing header on an internal tool matters less than the same gap on a public-facing site handling user data.
Why does a redirect chain matter if the page loads fine in the end?
Every hop in the chain adds a full round trip before the browser can even begin loading the actual page — it works, but slower than it should. A chain of three or four redirects is a common, overlooked performance cost; the fix is almost always to point the original link directly at the final destination.
What's the difference between a 502 and a 503?
Both point upstream rather than at the application itself. 502 (Bad Gateway) means a proxy or load balancer got an invalid response from the backend it's forwarding to. 503 (Service Unavailable) means the backend is deliberately not accepting requests right now — often mid-deploy or overloaded. Neither is typically an application-code error the way a 500 is.
The server header shows something unexpected — is that a problem?
Usually not. A CDN or reverse proxy sitting in front of the origin frequently reports its own name here (e.g. Cloudflare, nginx) rather than what the actual origin server is running — that's expected behavior for any site behind a CDN, not a misconfiguration.
Inspect any URL's headers with the HTTP header checker.