Skip to content

Security headers checker:
are yours actually protecting?

Enter a URL — we fetch it and value-analyze every security-relevant response header: HSTS, CSP, frame protection, nosniff, Referrer-Policy, Permissions-Policy, cross-origin isolation, info-leak headers and every Set-Cookie flag. You get one letter grade, a transparent 100-point score, and copy-paste fixes for nginx, Apache and Cloudflare.

Every header, one scorecard Values analyzed, not just presence Copy-paste fixes per server
Why "header: present" proves nothing

Four headers that protect nobody

Single-header checkers stop at "found ✓". Every one of these passes that test and fails its actual job — which is why we grade values, not presence.

The tutorial max-age

HSTS max-age=300, copied from a blog post's "test value" in 2023. Protection expires five minutes after each visit — any user who comes back tomorrow starts unprotected again.

expires in 5 min

Report-Only, forever

A CSP deployed as Report-Only "for a week of testing" — in 2024. It enforces nothing, blocks nothing, and grades as "CSP: found" in naive tools. We score it as what it is: deploying, not deployed.

enforcing: nothing

The deploy that ate them

A reverse-proxy migration, and the add_header block didn't move with it. Every point you'd earned vanished mid-deploy — and headers don't error when they disappear. They just stop arriving.

regression: silent

The chatty server

Server: nginx/1.14.0 and X-Powered-By: PHP/5.6 tell every scanner exactly which CVE list to open. Free information for attackers, removable with one config line each.

CVE list: attached
Value decoder

Six header values that lie

Each of these reads as "configured" to a presence check. Each does something very different from what its author intended.

Strict-Transport-Security: max-age=0

The self-destruct value: zero doesn't mean "forever", it means delete the policy. This is how you turn HSTS off — publishing it "to be safe" removes protection from every returning browser.

→ max-age=31536000 — a year
default-src *

CSP theater. A policy that allows every source blocks nothing, but satisfies every "has CSP?" checkbox. Wildcards and 'unsafe-inline' in script-src cost you 13 of CSP's 25 points here.

→ start from default-src 'self'
X-Frame-Options: ALLOW-FROM …

Deprecated years ago and ignored by every modern browser — you have no frame protection while the header says you do. The modern spelling is CSP's frame-ancestors.

→ frame-ancestors 'self' https://partner.example.com
X-Frame-Options: DENY, SAMEORIGIN

Two conflicting values — usually the app and the proxy each setting their own. Browsers treat the merged header as invalid and ignore it: two protections add up to zero.

→ set it in exactly one place
SameSite=None without Secure

Chrome rejects the cookie outright — None is only valid alongside Secure. The cross-site integration this was written for breaks silently, per browser, per version.

→ SameSite=None; Secure — or rethink
X-XSS-Protection: 1; mode=block

The zombie: every modern browser removed this auditor, and on the old ones that had it, the header could be abused to create leaks. Modern advice is to send nothing — we flag it for removal, not addition.

→ delete it (or send "0")
The killer detail

One scorecard for the whole response

The reference tools check HSTS on one page, X-Frame-Options on another, the Server header on a third, cookies on a fourth. But browsers evaluate your response as a whole — and so do attackers.

  • Every value analyzed, not just found: a 1-day HSTS scores half, a Report-Only CSP scores as "deploying", a wildcard CSP scores as theater — and a nonce policy carrying 'unsafe-inline' as its old-browser fallback is read the way browsers read it, not flagged.
  • The algorithm is public — the exact weight table is published, and every result page shows where each point went.
  • Cookie flags read off the real Set-Cookie lines — Secure, HttpOnly, SameSite, and the __Host- prefix that locks all three in.
  • Fixes ordered by points gained, each with the nginx, Apache and Cloudflare config ready to paste.

How the grade is computed

100 points · public weights
Strict-Transport-Security · 20Full credit needs max-age ≥ 6 months. Shorter values earn half — protection that expires between visits is half a protection. max-age=0 earns nothing: it's the delete order.
Content-Security-Policy · 25The big one. Enforcing and clean = 25. Enforcing with effective unsafe-inline/unsafe-eval/wildcards = 12. Report-Only = 8. Missing = 0.
Frame protection · 15frame-ancestors or a valid X-Frame-Options. ALLOW-FROM counts as nothing — browsers ignore it. So do conflicting merged values.
nosniff · Referrer · Permissions · 3010 each. Weak Referrer-Policy values (the legacy default leaks full URLs cross-origin) earn 5; unsafe-url earns 0.
Cookie flags · 10Proportional to Secure + HttpOnly + SameSite across every cookie the response sets. No cookies = full credit.
COOP bonus · +5Cross-origin isolation is extra credit, framed as what it is: COOP is a cheap win, COEP only matters if you need SharedArrayBuffer — skipping it is never penalized.
Version leaks · −3 eachServer with a version, X-Powered-By, X-AspNet-Version. Hygiene, not a lock — weighted accordingly.
Bands: A+ ≥ 95 · A ≥ 85 · B ≥ 70 · C ≥ 45 · D ≥ 25 · F below. One hard rule: without an enforcing CSP the grade caps at B — and A+ additionally requires a clean CSP and a 6-month HSTS.
For terminal people

What you can check yourself

The headers are one curl away. The value analysis, the grade and the watching-forever part are what's worth automating.

See every response headercurl -sI https://example.com
Just the security setcurl -sI https://example.com | grep -iE '^(strict-transport|content-security|x-frame|x-content-type|referrer|permissions)'
Cookie flags, uneditedcurl -sI https://example.com | grep -i '^set-cookie'
What your server admits tocurl -sI https://example.com | grep -iE '^(server|x-powered-by|x-aspnet)'
Value-analyze all of it, grade it, and watch it across deploys# ↑ that's this tool
FAQ

Common security headers questions

Paste your URL above. We fetch it and read every security-relevant response header: HSTS, CSP, X-Frame-Options / frame-ancestors, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP/COEP/CORP, info-leak headers, and the flags on every Set-Cookie. The values are analyzed, not just their presence. You get a letter grade, a prioritized fix list and per-server config snippets. Free, no signup.

No — and any tool that implies it is overclaiming. Security headers are browser-side seatbelts: they contain damage (an injected script that can't run, a login page that can't be framed, a session cookie that can't leak over plain http). They don't fix the injectable code, the weak password reset, or the unpatched dependency behind them. An A+ means your responses give browsers every protection they know how to apply. That's necessary, cheap, and not sufficient.

A strict one deployed cold — quite possibly, which is exactly why CSP ships with a rehearsal mode. Deploy your policy as Content-Security-Policy-Report-Only first: browsers report every would-be violation without blocking anything. Read a week of reports, fix the inline scripts they point at (nonces are the usual road), then rename the header to enforcing. The trap is the second step never happening. Report-Only scores 8 of 25 here and caps the grade at B: it is a phase, not a destination.

Partially, and the split matters. Cross-Origin-Opener-Policy: same-origin is a cheap win: it severs window references from cross-origin pages and defuses a family of XS-Leaks. We award it bonus points. COEP is different. It gates crossOriginIsolated features like SharedArrayBuffer, and it breaks every cross-origin resource you load without explicit opt-in. Skip it if you don't need those features: we mark COEP "absent, fine" rather than penalizing it.

Less than the fuss suggests, more than zero. A determined attacker can fingerprint your stack from behavior alone, so server_tokens off is hygiene, not a lock. But automated scanners work from advertised versions, and Server: nginx/1.14.0 is an invitation to try every CVE published since 2018. It costs one config line to remove, so the cost-benefit is excellent even if the benefit is modest — which is why we weigh it at −3 points, not −30.

Only deliberately. Preload hardcodes your domain into the browsers themselves — even the first-ever visit is HTTPS-only, which closes HSTS's one real gap. But it's close to permanent: removal from the Chromium list takes months to propagate, and the requirements (max-age ≥ 1 year, includeSubDomains, every subdomain on HTTPS forever) bind hosts you haven't created yet. That intranet box on http? It stops working. Preload is the right end state for most domains — reached on purpose, not via copy-paste.

A few former best practices are now dead weight, and we flag them. X-XSS-Protection: the auditor is gone from every modern browser and was abusable on the old ones, so send nothing or 0. Expect-CT: obsolete, because browsers have required certificate transparency for new certificates since 2018. Public-Key-Pins: deprecated in 2018, after it locked real sites out of their own domains. P3P: a ghost. A modern response is defined by six headers present and these absent.

Both, ideally. Headers are set per response. The page that matters is the one that sets your session cookie: the login or app page, not the marketing homepage. This tool accepts full URLs with paths, so you can grade https://app.example.com/login directly. A common finding: the homepage scores an A behind a CDN that injects headers, while the app subdomain (served by the origin) sends none of them.

Free tools are just the start.
Uptimia keeps your sites healthy.

Uptime, SSL, domain expiry, page speed, transactions — monitored from 171+ locations worldwide. Free for 30 days.

30 days free no credit card cancel anytime free plan after trial
100,000+ websites monitored · GDPR-compliant