Website security checker: HTTPS, security headers, cookies and mixed content
Check the basics every site should have: HTTPS with HSTS, a Content-Security-Policy, clickjacking protection, secure cookies, no http:// files on https pages, and a security.txt, with the headers to copy.
What is checked
| Check | Read from | Rule |
|---|---|---|
HTTPS | Final URL | The page is served over https://, and the http:// address redirects straight to it. |
Strict-Transport-Security | Response header | Present, with max-age of at least six months (a year for preload lists). |
Content-Security-Policy | Header or meta tag | Enforced, not report-only, and script-src without 'unsafe-inline' (unless a nonce or hash is used), 'unsafe-eval' or wildcards. |
Clickjacking | Response headers | CSP frame-ancestors, or X-Frame-Options DENY or SAMEORIGIN. |
X-Content-Type-Options | Response header | nosniff, so browsers never run a file as a different type. |
Referrer-Policy | Response header | Set, and not unsafe-url. |
Cookies | Set-Cookie | Secure on HTTPS sites, HttpOnly on session and login cookies, and never SameSite=None without Secure. |
Mixed content | HTML | No scripts, styles, frames, images, media or form actions on http:// addresses. |
Script integrity | HTML | Scripts from other domains carry an integrity hash where the file has a fixed version. |
Version headers | Response headers | Server and X-Powered-By do not reveal software versions. |
security.txt | /.well-known/security.txt | Present, with Contact and an Expires date in the future (RFC 9116). |
What this check is, and what it is not
It is a passive hygiene check. It makes the same requests any visitor’s browser makes, reads the headers and HTML, and compares them with current recommendations. It never sends attack payloads, guesses passwords or scans ports.
So it cannot find vulnerabilities in your code, outdated plugins or weak passwords. A good score means the standard browser protections are switched on, not that the site cannot be broken into. For that, use a penetration test or a vulnerability scanner you are allowed to run.
Why these headers matter
- HSTS stops the first plain-HTTP request, which an attacker on public Wi-Fi can intercept.
- A Content-Security-Policy limits the damage of cross-site scripting: an injected script that is not on the list does not run.
- frame-ancestors stops clickjacking, where another site shows yours in a hidden frame and tricks visitors into clicking.
- Secure and HttpOnly cookies keep login sessions off unencrypted connections and out of reach of injected scripts.
Where to set the headers
- nginx: add_header with the always flag, in the server block.
- Apache: Header always set, in the virtual host or .htaccess.
- Netlify and Cloudflare Pages: a _headers file in the published folder.
- Vercel: the headers array in vercel.json.
- Cloudflare in front of any server: Transform Rules, response header modification.
- Your framework: middleware such as helmet for Express, or headers() in next.config.js.
Roll out a Content-Security-Policy safely
Send the policy as Content-Security-Policy-Report-Only first. Browsers then report what it would block without blocking it. Browse the site, fix or allow what the console reports, and only then rename the header to Content-Security-Policy. The fix in the report starts you with a policy built from the scripts your page already loads.