Skip to content

Security Headers Checker

Security headers are the response headers that tell a browser how to constrain your own page: which scripts may run, whether the site may be framed, how long HTTPS is mandatory. This tool fetches a URL and grades six of them against a fixed, published rubric — no header is inferred or estimated.

How the grade is calculated

The score is out of 100 and the rules never change between sites. Every point is tied to an observed header value, so two people checking the same URL get the same grade.

HeaderMaxFull marks require
Strict-Transport-Security25max-age of at least 15552000 (180 days) on an HTTPS response
Content-Security-Policy25An enforcing policy with no unsafe-inline/unsafe-eval and no wildcard in script-src
Frame protection15CSP frame-ancestors, or X-Frame-Options: DENY/SAMEORIGIN
X-Content-Type-Options10Exactly nosniff
Referrer-Policy10no-referrer, same-origin, strict-origin, or strict-origin-when-cross-origin
Permissions-Policy15Present and non-empty

Grades: A at 90 or above, B at 75, C at 60, D at 45, E at 30, F below that. Partial credit exists where a header is present but weakened — a short HSTS max-age, a CSP that still allows unsafe-inline, a Referrer-Policy that leaks full URLs cross-origin.

A grade is a checklist score, not a security assessment. A site can score A and still be trivially exploitable through its application logic. These headers close specific, well-understood classes of browser-side attack; they say nothing about authentication, authorisation, or injection on the server.
Read the full explanation of security headers checker results ↓

What each header is actually defending against

Strict-Transport-Security

HSTS tells the browser to refuse plaintext HTTP to this host for max-age seconds. It closes the window where a user types example.com, gets an HTTP request on the wire, and an attacker on the same network intercepts the redirect. Set max-age=31536000; includeSubDomains, and add preload plus a submission to hstspreload.org only once you are certain every subdomain — including ones you have forgotten — serves valid HTTPS. Preload is close to irreversible: removal takes months to propagate through browser releases.

HSTS on an HTTP response is ignored entirely by browsers, which is why this tool scores it zero when the final URL is plaintext. Fix the redirect first.

Content-Security-Policy

CSP is the only header on this list that stops injected script from executing. Everything else mitigates; this one prevents. It is also the hardest to deploy, because a policy that is slightly wrong breaks your own site.

The rollout that works: publish the policy in Content-Security-Policy-Report-Only with a report-uri/report-to endpoint, leave it for a fortnight, fix everything the reports surface, then move the identical value to the enforcing header. Note that report-only mode blocks nothing — a site with only the report-only header gets no points here, deliberately.

A policy containing script-src 'unsafe-inline' gives up most of the protection, because injected inline script is precisely what XSS delivers. The modern pattern is a per-response nonce with 'strict-dynamic', which lets your bootstrap script load its own dependencies without enumerating every CDN host.

Frame protection

Clickjacking overlays your page in an invisible iframe on an attacker's site so clicks land on your buttons. CSP frame-ancestors is the standardised control and supports an allowlist of origins; X-Frame-Options is the legacy header with only DENY and SAMEORIGIN (the ALLOW-FROM variant was removed from every browser). Send frame-ancestors, and keep X-Frame-Options: SAMEORIGIN alongside it for very old clients.

X-Content-Type-Options

One value, nosniff, one job: stop browsers second-guessing your Content-Type. Without it, a file a user uploaded as text/plain can be sniffed as HTML or JavaScript and executed in your origin. There is no downside and no compatibility risk — this is the cheapest 10 points on the page.

Referrer-Policy

Controls how much of the current URL is sent in the Referer header on outbound requests. It matters because password-reset links, invite tokens, and session identifiers regularly live in query strings, and unsafe-url sends the lot to every third-party script on the page. strict-origin-when-cross-origin is the sensible default and is what browsers now use when you send nothing — but send it explicitly so the behaviour cannot drift.

Permissions-Policy

Denies powerful browser APIs — camera, microphone, geolocation, payment — to your page *and to every iframe it embeds*. That second part is the point: a compromised third-party widget cannot prompt your users for camera access if the policy forbids it. It replaces the obsolete Feature-Policy header, which used different syntax and is no longer honoured.

A starting configuration

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
nginx — add to the server block, then reload
In nginx, add_header in a nested block silently discards every add_header inherited from the parent. If your headers vanish on one path, look for an add_header inside that location. The always flag is also required, or the headers are omitted on error responses — exactly where they still matter.
curl -sL -o /dev/null -D - https://example.com \
  | grep -Ei 'strict-transport-security|content-security-policy|x-frame-options|x-content-type-options|referrer-policy|permissions-policy'
Verify from the shell — the same request this tool makes

Headers are only meaningful over a working TLS connection, so confirm the certificate and chain with the SSL certificate checker first — HSTS in particular is actively dangerous to enable on a host whose certificate renewal is unreliable, because browsers will refuse to let users click through the error. To see the full response including caching and CDN headers, use the HTTP headers checker.

Frequently asked questions

Why did my site score F when it uses HTTPS everywhere?
HTTPS and security headers are independent. TLS encrypts the transport; these headers constrain what the browser will do with the page once it arrives. A perfectly configured certificate with no CSP, no HSTS, and no nosniff scores zero here — which is exactly the point of checking them separately.
Will adding a Content-Security-Policy break my site?
An enforcing policy very likely will on the first attempt — inline scripts, inline styles, and third-party tags all need explicit allowance. That is why the correct rollout is Content-Security-Policy-Report-Only with a reporting endpoint for a couple of weeks, fixing what the reports show, then promoting the same value to the enforcing header.
Should I enable HSTS preload?
Only when every subdomain, including internal and forgotten ones, serves a valid certificate — includeSubDomains plus preload applies to all of them. Removal from the preload list takes months to reach users through browser releases, so a mistake is a long outage. Run max-age=31536000; includeSubDomains without preload for several months first.
Do I need X-XSS-Protection?
No. The header controlled a legacy XSS auditor that Chrome removed in version 78 and Firefox never implemented; in some configurations it introduced vulnerabilities of its own. It is not scored here. CSP is the replacement, and the only one that works.
X-Frame-Options or CSP frame-ancestors?
Send both. frame-ancestors is the standard, supports origin allowlists, and takes precedence in every current browser; X-Frame-Options: SAMEORIGIN covers clients too old to honour CSP. Full marks are awarded for either, but the pair costs nothing extra.
Why does the report-only header not earn any points?
Because it enforces nothing. Report-only mode logs violations and lets them execute — it is a deployment aid, not a control. A site running only report-only CSP is exactly as exploitable as one with no policy, so scoring it would be misleading.
Can these headers be set at the CDN instead of the origin?
Yes, and for a static site that is often simpler. Be aware that CDN-injected headers can be overridden or duplicated by origin headers, and that duplicated CSP headers are intersected — two policies means the *most* restrictive combination applies, which is a common cause of "my CSP is stricter than what I wrote".
Does a good grade here mean my site is secure?
No. It means six specific browser-side protections are configured. It says nothing about injection, authentication, access control, dependency vulnerabilities, or your server configuration. Treat the grade as a floor that is cheap to reach, not as evidence of a secure application.