HTTP security headers explained: what each one prevents
Security headers are instructions a server sends with each page telling the browser what the page may do: only use HTTPS, run scripts from these places only, don't let other sites frame it, don't guess file types, share less in the referrer. A small static site needs about six of them, and the most valuable is a strict Content-Security-Policy.
Read the headers your site sends
- From a terminal, run
curl -sI https://yourdomain.com. The-Iasks for headers only; each line isname: value. - In a browser, open DevTools, go to the Network panel, reload, click the first request (the page itself) and look under Response Headers.
- Check more than the home page. Headers can differ between pages, files and error pages on some hosts.
- Compare against the table below, noting what's missing and what's set to a weak value.
What each header does
| Header | Prevents | Typical value |
|---|---|---|
| Content-Security-Policy | Injected or unexpected scripts, styles, frames and form targets running on your page | default-src 'self'; script-src 'self'; frame-ancestors 'none'; form-action 'self' tightened to what the page uses |
| Strict-Transport-Security | Visitors being downgraded to unencrypted HTTP on later visits | max-age=31536000 at first, adding includeSubDomains once every subdomain has HTTPS |
| X-Content-Type-Options | Browsers guessing a file's type and running an upload as script | nosniff |
| Referrer-Policy | Full URLs, including query strings, leaking to other sites | strict-origin-when-cross-origin or stricter |
| Permissions-Policy | Embedded or injected code using the camera, microphone, location or payment features | Turn off what you don't use, e.g. camera=(), microphone=(), geolocation=() |
| X-Frame-Options | Your page being loaded in a hidden frame for clickjacking | DENY, kept for older browsers alongside CSP frame-ancestors |
The OWASP HTTP headers cheat sheet is the fuller reference and gives the reasoning for each value; this page keeps HTTP security headers explained at the level a small site needs. For the policy itself, the Content-Security-Policy explainer goes directive by directive.
HSTS, carefully
Strict-Transport-Security tells the browser to use HTTPS for your host for max-age seconds, even if someone types http://. MDN's HSTS reference notes the risks: with includeSubDomains, any subdomain without a working certificate becomes unreachable, and visitors can't click past certificate errors. The preload flag asks browsers to build your domain into their HTTPS-only list, which is slow to undo. Start with a modest max-age, confirm every subdomain works, and only then lengthen it or preload.
Headers to leave out
- X-XSS-Protection. The old browser filter it controlled has been removed and could introduce problems; OWASP advises not sending it, or sending
0. A strict CSP does the job properly. - Server and X-Powered-By. Not security headers but leaks: they announce your software and version. Remove them if your host lets you.
- Header values copied from a large site. A CSP built for a site with dozens of third-party scripts is far weaker than one built for yours.
What a static site actually needs
A brochure site with no scripts, no logins and a contact form gets most of its protection from two things: HTTPS everywhere, and a CSP that allows no scripts and lets forms post only to your own origin. Add nosniff, a referrer policy, frame-ancestors 'none' and a short Permissions-Policy and you've covered the common attacks against a page like that. Sites with accounts, payments or user-generated content need all of this plus server-side defences that no header provides; the security checklist for AI websites lists them.
Security headers on Anticode sites
Published sites are served over HTTPS on both name.anticode.dev and custom domains. Design-engine pages carry a Content-Security-Policy that includes script-src 'none' and frame-src 'none', so no script can run on them and nothing can be embedded in them. Sentinel checks the policy, form targets, referrer policy and HTTPS on every build, and each site has a security report at /.well-known/anticode-security, worked out from the published pages on each request. You can't edit the headers yourself; run curl -sI against your own site to see the full set it sends. If a header you need isn't there, the Next.js export gives you full control of headers on your own host.
Common mistakes
- A CSP in report-only mode left on for good, which reports problems but blocks nothing.
'unsafe-inline'inscript-srcto make one widget work, which undoes most of the policy.- Setting headers on the HTML but not on error pages or files served from another bucket.
- Judging by a letter grade alone. Header scanners are useful, but a high grade with a loose CSP is still a loose CSP.
Questions people ask
Can I set security headers with meta tags?
Some. A CSP and a referrer policy can be set with meta tags, but HSTS, X-Content-Type-Options, frame-ancestors and Permissions-Policy only work as real HTTP headers.
Is X-Frame-Options still needed?
CSP frame-ancestors replaces it in current browsers. Sending both does no harm and covers older browsers.
Do security headers affect SEO?
Not directly. HTTPS is a lightweight ranking signal; the other headers protect visitors rather than rankings.