Security Headers Checker
Check a site's HTTP security headers (HSTS, Content-Security-Policy, X-Frame-Options and more), get an A+ to F grade with the exact scoring shown, and copy-paste fixes for nginx, Apache, WordPress and Cloudflare.
Free · Two ordinary page requests (https:// and http://) · Nothing is changed on the site · Private and internal addresses are refused
How the grade is calculated
We fetch https://your-domain/, follow redirects (up to 5, every hop re-checked against our private-address block list) and grade the headers on the final page. Separately we request http://your-domain/ to see whether it redirects to HTTPS. Points add up to 100; leaks subtract.
| Check | Max | How points are given |
|---|---|---|
| HTTP to HTTPS redirect | 10 | Full points if http:// redirects to https://, or if port 80 does not answer at all. 0 if http:// serves a page. |
| Strict-Transport-Security | 20 | 17 for max-age of 180 days or more (10 if shorter, 0 if missing or max-age=0), +3 for includeSubDomains. preload is reported, not scored. |
| Content-Security-Policy | 25 | 25 for an enforced policy that restricts scripts. −8 for 'unsafe-inline' without a nonce/hash, −5 for 'unsafe-eval', −7 for *, http: or https: in script-src (minimum 5). 8 if it has no script-src/default-src. 5 if only Report-Only. 0 if missing. |
| X-Frame-Options or CSP frame-ancestors | 10 | 10 for DENY, SAMEORIGIN or any frame-ancestors. 3 for the obsolete ALLOW-FROM. 0 if missing. |
| X-Content-Type-Options | 10 | 10 for nosniff, otherwise 0. |
| Referrer-Policy | 10 | 10 for no-referrer, same-origin, strict-origin or strict-origin-when-cross-origin. 5 for origin, origin-when-cross-origin or no-referrer-when-downgrade. 0 for unsafe-url or missing. |
| Permissions-Policy | 5 | 5 if present. 2 for the old Feature-Policy only. |
| Cross-Origin-Opener-Policy | 5 | 5 for same-origin or same-origin-allow-popups. |
| Cookies | 5 | 5 if every cookie on the page has Secure, HttpOnly and SameSite (or no cookies are set). 2 if only HttpOnly/SameSite are missing. 0 if any cookie lacks Secure. |
| Total | 100 |
| Information leak | Penalty |
|---|---|
| Server header with a version number (e.g. nginx/1.18.0, Apache/2.4.41) | −5 |
| X-Powered-By with a version number (e.g. PHP/7.4.3) | −5 |
| Software version in X-Generator or any <meta name="generator"> tag (e.g. WordPress 6.4.2, a plugin version); counted once | −5 |
| X-Pingback header (advertises xmlrpc.php) | −3 |
Grade bands: A+ 95+ · A 85+ · B 70+ · C 55+ · D 40+ · F below 40. If the final page is not HTTPS, the grade is F whatever the points.
Daniel Lasek · Last reviewed 2026-11-01
Security headers are short instructions your server sends with every page, telling the visitor's browser what it is allowed to do: only use HTTPS, refuse to run scripts from unknown places, refuse to be shown inside another site's frame. They cost nothing, take minutes to add, and limit the damage when something else goes wrong. This checker fetches your homepage the way a browser does, reads those headers on the final URL after redirects, and grades them with the points shown above, so you can see exactly why you got the letter you got.
What each header does, in plain English
Strict-Transport-Security (HSTS) tells browsers: for the next N seconds, only ever talk to this domain over HTTPS. Without it, someone typing example.com first makes an unencrypted request, which can be intercepted on public Wi-Fi before the redirect to HTTPS happens. Use max-age=31536000; includeSubDomains once every subdomain works over HTTPS.
Content-Security-Policy (CSP) is a list of places scripts, styles, images and frames may come from. It is the header that matters most for hacked sites: the classic WordPress infection injects a <script> that redirects mobile visitors to spam or scam pages. A good CSP stops the browser from running that script even after the database is infected. It is also the header most likely to break things, so it starts as Report-Only (below).
X-Frame-Options or CSP frame-ancestors stops other sites from loading your pages inside an invisible frame and tricking visitors into clicking buttons there (clickjacking). SAMEORIGIN is safe for almost every WordPress site.
X-Content-Type-Options: nosniff stops browsers from guessing file types. Without it, an uploaded file with the wrong extension can be treated as a script.
Referrer-Policy controls how much of the current address is sent to other sites when someone clicks a link. strict-origin-when-cross-origin sends only your domain name to other sites, and nothing at all to plain-http sites.
Permissions-Policy switches off browser features you do not use, such as camera, microphone and location, so a third-party script or embed cannot ask for them.
Cross-Origin-Opener-Policy isolates your window from pages you open in popups. same-origin-allow-popups keeps PayPal and "Sign in with Google" popups working.
The information leaks we also flag
A Server: nginx/1.18.0 or X-Powered-By: PHP/7.4.3 header tells every bot exactly which version you run. PHP 7.4 stopped getting security fixes in November 2022, and bots look for exactly that string. WordPress's <meta name="generator" content="WordPress 6.x.y"> does the same for the CMS. X-Pingback advertises xmlrpc.php, a popular target for password guessing. Hiding versions is not a substitute for updating, but there is no reason to publish them.
How to start a Content-Security-Policy without breaking your site
- Send the policy as
Content-Security-Policy-Report-Only. It blocks nothing. - Open your main pages (home, a post, contact form, checkout, the login page) with the browser console open (F12). Every line that says "Report Only" is something the policy would block.
- Add the legitimate sources you see (your analytics host, your font host, your payment provider) to the right directive.
- Repeat for a week or two, including after plugin updates.
- Rename the header to
Content-Security-Policy. Keep the Report-Only version running alongside if you want to try a stricter policy next.
Most WordPress themes and plugins print inline scripts, so a realistic first WordPress policy keeps 'unsafe-inline' in script-src. That still blocks scripts loaded from an attacker's domain, which is how most injected redirects work. Removing 'unsafe-inline' needs nonces, which WordPress core supports through wp_print_inline_script_tag() but many plugins do not use yet.
Where to add headers on WordPress
There are three places, and you should use one of them, not all three:
- The web server (nginx config or Apache
.htaccess): fastest, covers static files and cached pages. Best if you can edit server config or.htaccess. - A must-use plugin with the
send_headershook: works on any host, including ones without.htaccessaccess, but pages served straight from a page cache will not have the headers until the cache is rebuilt. - Cloudflare Transform Rules: works without touching the server at all, if the site is proxied through Cloudflare (orange cloud). The free plan includes them.
Sending a header from two places can result in two copies. For most headers browsers then use the first or combine them unpredictably, so pick one place.
What this checker does not do
It checks one page: the final URL after following redirects from https://your-domain/. Logged-in pages, checkout and wp-admin can send different headers. It does not test your TLS certificate or cipher settings, and it does not look for malware. A good header grade says nothing about whether the site is already infected; for that, run the free hacked-site scan.
Requests come from LaskyrScanner and are refused for private, loopback and cloud metadata addresses, including when a redirect points at one.
Questions
Will a missing security header get my site hacked?
Not by itself. Headers are a second line of defence that limit what an attacker can do in a visitor's browser, for example running an injected script or framing your login page. Most WordPress hacks start with an outdated plugin, a reused password or a nulled theme. Fix those first, then add headers.
Can a Content-Security-Policy break my WordPress site?
Yes. An enforced CSP blocks every script, style, font, frame or connection it does not allow, which can break page builders, analytics, chat widgets, reCAPTCHA and payment forms. Start with Content-Security-Policy-Report-Only, which blocks nothing and only reports, read the browser console for a week or two, add what is legitimate, then switch to the enforced header.
What is a good HSTS max-age?
One year (max-age=31536000) is the common recommendation and what the HSTS preload list requires. Start lower (for example 300 seconds) only while you confirm every page and subdomain works over HTTPS, because browsers remember the setting for the full max-age.
Should I add preload to my HSTS header?
Only if you understand it. Preload asks browsers to ship your domain as HTTPS-only, including every subdomain. Getting off the list takes months. If any subdomain (an old mail panel, a staging site, a printer) still needs plain http, it will stop working. This checker reports preload but gives no extra points for it.
Is X-Frame-Options still needed if I have frame-ancestors in my CSP?
Modern browsers follow CSP frame-ancestors and ignore X-Frame-Options when both are present. Sending X-Frame-Options SAMEORIGIN as well is harmless and covers very old browsers. Either one earns full points here.
Why does the checker show my WordPress version as a leak?
WordPress prints a generator meta tag with its exact version by default. Automated bots look for that tag to find sites running versions with known holes. Hiding it does not fix an outdated site, so update WordPress first, then remove the tag with the snippet on this page.
I added the headers but the grade did not change. Why?
Usually a cache. Page caches like LiteSpeed Cache, WP Rocket or your host's cache, and CDNs like Cloudflare, can keep serving old responses. Purge every cache and check again. On nginx, an add_header inside a location block also drops all add_header lines from the server block.
Do you store anything about my site?
We save the result (grade, header values and cookie names, never cookie values) so the share link and badge work. Results are deleted after 90 days. We do not store your IP address with the result.
Related
- /tools/wordpress-vulnerability-checker
- /tools/is-my-site-hacked
- /guides/how-hackers-get-into-wordpress-sites
- /scan
Want the rest of the picture? Run the free hacked-site scan.