HTTP security headers are response policies that tell the browser how to treat your site. They are not a substitute for secure application code. Used correctly, they close common classes of attack cheaply: SSL stripping (HSTS), cross-site scripting and data injection (CSP), MIME confusion (X-Content-Type-Options), clickjacking (framing controls), referrer leakage (Referrer-Policy), and unwanted browser features (Permissions-Policy).
Want a live grade right now? Paste any public HTTPS URL into the free HTTP Security Header Checker. It fetches the URL and scores the security-relevant headers the client actually receives — including ones a CDN or reverse proxy added or stripped. The rest of this article explains what each header means, what good values look like, and the order to fix them on sites you own or are authorized to harden.
What HTTP security headers are
When a browser requests a page, the server answers with status, body, and a set of response headers. Most headers describe caching, encoding, or content type. A smaller set is security policy: they constrain what the browser is allowed to do with that response and with future requests to the same host.
Three practical points before the list:
- They are defence in depth. A strong CSP does not make unsafe sinks safe. It raises the cost of exploiting them. Fix the code; keep the headers.
- What the client receives is what counts. A CDN, load balancer, or platform edge can add or remove headers after your app emits them. Config on the origin alone is not enough — verify with a live fetch.
- Apply them on HTML that browsers render. Many of these headers are meaningless or only partially relevant on pure JSON APIs. Prioritize document responses and authenticated UI.
Authoritative baselines live in the OWASP HTTP Headers Cheat Sheet and the MDN docs linked below. This article follows those sources and focuses on the six headers that matter most for day-to-day web hardening.
The priority six
1. Strict-Transport-Security (HSTS)
HSTS tells the browser that this host must be reached only over HTTPS for a period of time (max-age, in seconds). After the first successful HTTPS response that includes the header, later http:// navigations to that host are upgraded to HTTPS before the request leaves the browser. Users also cannot click through certificate errors for an HSTS host.
Recommended starting point (OWASP; matches common preload guidance):
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Omit preload until every subdomain is ready and you intend to submit — the token alone does nothing, and hstspreload.org no longer recommends preloading as a default.
max-age=63072000— two years. Browsers refresh the deadline every time they see the header.includeSubDomains— apply the policy to every subdomain of this host. Only enable this when all subdomains speak HTTPS.preload— signals intent to submit the domain to browser preload lists (see hstspreload.org). Preload requiresincludeSubDomainsandmax-ageof at least one year. Submission is a separate operational step; the token alone does nothing until the domain is accepted and browsers ship an updated list.
Caveats (read before you ship):
- Send HSTS only over HTTPS. Browsers ignore it on plain HTTP so a network attacker cannot inject a hostile policy.
- A long
max-agewith a broken certificate locks users out until the policy expires or you serve a fixed cert again. Roll out with a shortmax-agefirst, then raise it. - Without
includeSubDomains, anhttp://subdomain remains open to SSL stripping even when the apex is locked down.
If you serve HTTPS already and have not set any security header yet, start here. One line closes the SSL-stripping downgrade class for returning visitors.
2. Content-Security-Policy (CSP)
CSP is the strongest in-browser control against XSS and unwanted resource loads. It lists where scripts, styles, images, fonts, frames, and connections may come from. Modern CSP also supersedes older framing headers via frame-ancestors.
A tight policy is hard. That is why so many sites ship none, or ship one that allows 'unsafe-inline' everywhere and gains almost nothing. Prefer:
- Ship
Content-Security-Policy-Report-Onlyfirst and watch reports. - Remove inline scripts/styles or move them behind nonces or hashes.
- Flip to enforcing
Content-Security-Policywhen the report noise is acceptable. - Avoid
'unsafe-inline'and'unsafe-eval'inscript-srcunless you have a documented, temporary exception.
Minimal illustrative policy for a simple static site (adjust origins to your real CDNs):
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
For the full directive set and migration patterns, use the OWASP CSP Cheat Sheet. When you are reading a raw CSP string from a response or a report, the in-browser Cyber Swiss Army Knife is a convenient place to pretty-print or decode fragments without uploading them.
3. X-Content-Type-Options
X-Content-Type-Options: nosniff
This single value tells the browser to honour the declared Content-Type and not MIME-sniff the body into a different, executable type. OWASP recommends it site-wide. Pair it with correct Content-Type headers (including charset=UTF-8 on HTML).
4. Framing: X-Frame-Options vs CSP frame-ancestors
Clickjacking embeds your UI in a hostile page and tricks the user into clicking. Two headers address it:
| Mechanism | Example | Notes |
|---|---|---|
CSP frame-ancestors | frame-ancestors 'none' | Modern, preferred. Can allow specific parent origins. |
X-Frame-Options | DENY or SAMEORIGIN | Legacy. ALLOW-FROM is obsolete and ignored by modern browsers. |
OWASP recommendation: prefer CSP frame-ancestors. Keep X-Frame-Options: DENY (or SAMEORIGIN if you must frame yourself) as belt-and-braces for older clients. Framing headers only help on responses that render interactive UI; they do nothing useful on a bare JSON API redirect body.
5. Referrer-Policy
Controls how much of the current URL is sent as Referer on later navigations and subresource loads. OWASP's suggested default:
Referrer-Policy: strict-origin-when-cross-origin
That keeps full referrer on same-origin requests, sends only the origin on HTTPS→HTTPS cross-origin requests, and sends nothing on HTTPS→HTTP. Tighten further (no-referrer or same-origin) for highly sensitive apps if product allows.
6. Permissions-Policy
Formerly Feature-Policy. Disables powerful browser features your page does not need, so an XSS cannot casually turn on the camera or geolocation:
Permissions-Policy: geolocation=(), camera=(), microphone=()
Add or remove features to match what the product actually uses. Empty allowlists mean "nobody, including this origin."
Live check vs curl vs DevTools
Three common ways people "check headers," and what each misses:
| Method | What you see | Blind spots |
|---|---|---|
| Browser DevTools → Network | Headers for the document you just loaded | Only your session, your path, your cookies; easy to miss intermediate responses |
curl -sI https://example.com | Headers from one request you craft | May skip JS-driven navigations; may hit a different POP or cache key than users |
| Live header checker | Server response from a fresh fetch graded for security headers | Still one URL at a time — re-check auth'd app routes and www vs apex separately |
CDN and reverse-proxy surprises are the usual reason DevTools and origin config disagree. Always grade the hostname users type. If apex redirects to www, grade the final host too.
Quick local sanity check (authorized targets only):
# Final response headers after redirects (-L follows; -I is HEAD)
curl -sI -L "https://example.com" | tr -d '\r' | grep -iE \
'^(HTTP/|strict-transport-security|content-security-policy|x-content-type-options|x-frame-options|referrer-policy|permissions-policy):'
Treat curl as a spot check. Use the live grader when you want a consistent score you can re-run after each config change.
Common misconfigurations
- CSP stuck in Report-Only. Useful for rollout; useless as a permanent state. Schedule the flip to enforce.
- HSTS without
includeSubDomains. Apex is locked;http://shop.orhttp://api.remains strippable. - Relying on
X-XSS-Protection. Modern guidance is to omit it or setX-XSS-Protection: 0. It is deprecated, inconsistently implemented, and can introduce bugs. Use CSP instead (OWASP). X-Frame-Options: ALLOW-FROM. Obsolete. Use CSPframe-ancestors.'unsafe-inline'everywhere in CSP. Looks green in some checklists; blocks almost no XSS.- Headers only on
/. Set them on the HTML responses that matter (and error pages). A perfect homepage with bare login HTML still fails users. - Information leak headers left on. Not in the "priority six," but remove or genericize
Server/X-Powered-Bywhen you can — they help fingerprinting more than operators.
Fix order for defenders
On a site you own or are contractually authorized to harden:
- Confirm HTTPS end-to-end (valid cert, HTTP→HTTPS redirect, no mixed active content).
- Ship HSTS with a short
max-age(for example one day), monitor, then raise toward two years; addincludeSubDomainsonly when every subdomain is ready; consider preload last. - Add
X-Content-Type-Options: nosniff, a framing policy (frame-ancestors/X-Frame-Options),Referrer-Policy, and a locked-downPermissions-Policy. These are low-risk on most apps. - Design CSP in report-only, remove inline barriers, then enforce. Budget real engineering time; this is the hard one.
- Re-grade with a live fetch after each change — HTTP Security Header Checker — and keep a note of CDN config so the next deploy does not silently drop headers.
Adjacent hardening that often sits in the same engagement:
- Domain email authentication (SPF / DKIM / DMARC) via the Email Security Checker
- Registration hygiene and expiry watching via WHOIS Lookup
If your product exposes MCP servers or AI agent tool bridges, browser headers alone do not protect tool calls. Runtime policy on the agent path is a separate control — SentinelAgent Guard is built for that layer.
FAQ
What does "check security headers" mean in practice?
It means fetching a URL the way a browser would and reading which security-relevant response headers came back, then comparing them to a baseline (HSTS present with a sane max-age, CSP not absent or wildly permissive, nosniff, framing controls, referrer and permissions policies). A live grader automates that comparison.
Which security header should I add first?
Strict-Transport-Security, if the site already serves HTTPS correctly. It is one line of config and directly targets SSL-stripping downgrades for returning visitors. Then add the easy wins (nosniff, framing, referrer, permissions), then invest in CSP.
Is X-Frame-Options still needed if I have CSP frame-ancestors?
For modern browsers, frame-ancestors is enough. Keeping X-Frame-Options: DENY or SAMEORIGIN is still reasonable for older clients. Do not use ALLOW-FROM.
Why does my server config show headers that the live check does not?
A CDN, API gateway, or hosting platform in front of the origin can strip or override them. The live check shows what clients receive. Fix the layer that terminates TLS for users, not only the app container.
Should I enable HSTS preload immediately?
No. Stabilize HTTPS on every subdomain first, run HSTS with includeSubDomains and a long max-age successfully in production, then submit via the preload process. Preload is powerful and slow to undo.
Does a good header grade mean the site is secure?
No. Headers raise the bar for specific browser-side attacks. They do not fix SQL injection, broken access control, secret leakage, or unsafe agent tool bridges. Use them as one layer in a broader review.