HTTP Headers Test - View Browser Request Headers

doc

Inspect HTTP headers your browser sends and server responses. Analyze CSP, HSTS, Referrer-Policy, and privacy signals for security and debugging.

HTTPS protects the connection. It does not decide how the browser behaves once a response arrives. That decision is made by response headers, and the difference between a hardened site and a vulnerable one is often six lines of configuration that nobody looks at.

This page covers the headers that matter in practice, what a correct value looks like, and how each one is usually misconfigured.

Content-Security-Policy

What it does. CSP declares which sources the page may load scripts, styles, images and connections from. It is the only control that meaningfully limits the impact of an injected script, because it operates after the injection has already succeeded.

A reasonable starting value.

default-src 'self'; script-src 'self' 'nonce-{random}'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

How it goes wrong.

  • 'unsafe-inline' is added to make an existing site work, which removes most of the XSS protection the header was meant to provide.
  • 'unsafe-eval' is added for a framework that compiles templates at runtime, reopening code execution.
  • The policy stays in Content-Security-Policy-Report-Only indefinitely. Report-only never blocks anything; it only logs violations. Teams add it, watch the reports for a week, and never flip the switch.
  • default-src is omitted, so each directive falls back to nothing and undocumented resource types load freely.

The practical rollout. Deploy in report-only, collect violations for a week, fix the legitimate ones, then switch to enforcing. Keep a separate report endpoint so that breakage shows up as data rather than as a support ticket.

Strict-Transport-Security

What it does. Tells the browser that this host must only be contacted over HTTPS for the duration given, defeating protocol downgrade and cookie theft on the first plaintext request.

A reasonable value. max-age=31536000; includeSubDomains; preload

How it goes wrong.

  • max-age is set to something short like 3600, which gives an attacker a window every hour.
  • The header is sent only on the HTTPS response but the site still answers HTTP — which is fine — yet the site also serves an HTTP redirect without the header, so the first request stays unprotected.
  • preload is added before every subdomain is HTTPS-ready, and a single HTTP-only subdomain becomes permanently unreachable for users who already have the policy cached.

Note the asymmetry: HSTS is easy to add and hard to remove. A browser that has cached a one-year policy will refuse plaintext for a year regardless of what the server says next.

X-Frame-Options and frame-ancestors

What it does. Prevents the page from being framed, which is the precondition for clickjacking.

A reasonable value. DENY, or SAMEORIGIN when the site frames itself.

How it goes wrong. The ALLOW-FROM directive is still widely copied from old documentation, and no current browser supports it — the header is silently ignored and the page remains frameable. The modern equivalent is the CSP frame-ancestors directive, which also supports specific origins. Setting both is fine; when they conflict, browsers that understand CSP prefer frame-ancestors.

X-Content-Type-Options

What it does. nosniff stops the browser from guessing a content type. Without it, a file uploaded as text/plain can be interpreted as HTML or JavaScript if the content looks like it, which is how many upload features become stored XSS.

The correct value is one word. nosniff. There is no other supported value.

Referrer-Policy

What it does. Controls how much of the current URL is sent to other origins in the Referer header. Full URLs leak paths, query strings, tokens and occasionally session identifiers to third parties and to any site a user clicks through to.

A reasonable value. strict-origin-when-cross-origin — full URL on same-origin requests, origin only cross-origin, nothing on downgrade. It is also the modern browser default, but relying on a default means older clients behave differently, so setting it explicitly is still worth doing.

Permissions-Policy

What it does. Restricts which features and sensors the page, and any embedded frame, may use — geolocation, camera, microphone, payment, USB, and so on.

A reasonable value. geolocation=(), camera=(), microphone=(), payment=() — the empty parentheses mean "deny for all origins including self". Grant specific origins only where a feature is genuinely used.

Cross-origin isolation, when you need it

Three additional headers — Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy and Cross-Origin-Resource-Policy — control whether the page runs in an isolated context. They are only required for features such as SharedArrayBuffer and high-resolution timers. Adding them without understanding the consequences breaks third-party embeds, so treat them as opt-in rather than as part of a default checklist.

Two headers people still get wrong

X-XSS-Protection. The legacy reflected-XSS filter is gone from modern browsers. The correct value today is 0, which disables it. Setting 1; mode=block is worse than sending nothing, because it can introduce new vulnerabilities in old clients while providing no protection in current ones.

Server and X-Powered-By. Not security headers, but they advertise the stack. Removing them is cheap and reduces the value of automated scanning.

How to check a site

From a terminal:

curl -sI https://example.com | grep -iE "content-security-policy|strict-transport|x-frame|x-content-type|referrer-policy|permissions-policy"

Then confirm three things rather than just presence:

  1. The header is on the response that matters — the HTML document, not only the API or the static assets.
  2. The value is enforcing, not reporting — check for Report-Only in the header name.
  3. It survives the CDN — many platforms strip or override headers at the edge. If you set it in application code but the edge rewrites the response, the browser sees the edge's version.

Where to set them

  • At the origin application — best for headers that depend on request context, such as per-request CSP nonces.
  • At the reverse proxy or CDN — best for static values like HSTS and nosniff, and it covers responses the application never sees.
  • In both places, carefully — duplicate values are legal but confusing; a mismatch between edge and origin is a common source of "it works in staging" reports.

FAQ

Do these headers replace input validation?

No. CSP limits the damage of a successful injection; it does not prevent the injection. Encoding and validation remain the primary control.

Is a missing HSTS header a vulnerability?

It is a weakness rather than a directly exploitable flaw — it matters when an attacker can force a plaintext request, for example on a hostile network.

Why does my CSP break the page?

Usually because inline scripts or eval are blocked. The fix is nonces or hashes, not adding 'unsafe-inline'.

Are security headers a ranking factor?

Not directly. They affect user safety and can affect how browsers treat the site, but no major search engine scores them as a ranking signal.