HTTP Security Headers Explained
September 26, 2026 · DevOps
Some of the web's best defenses cost nothing and require no code changes in your app: HTTP security headers are instructions your server sends with every response, telling the browser how to behave securely. Most "top 10 headers" lists describe what each header does — this guide leads with what each header stops, because the threat is what makes the header make sense.
What security headers are
Every HTTP response carries headers — metadata like Content-Type. Security headers are a subset that constrain the browser: "only run scripts from these sources", "never use plain HTTP for this domain", "don't let other sites frame this page". The browser enforces them automatically. They're defense-in-depth: they don't fix vulnerabilities in your code, but they sharply limit what an exploited vulnerability can do.
Content-Security-Policy: your XSS seatbelt
Threat: cross-site scripting (XSS) — an attacker injects a malicious <script> into your page (via a comment field, a profile bio, a reflected parameter), and every visitor's browser runs it, stealing sessions.
Defense: CSP whitelists resource sources. A starter policy:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
This says: load everything from our own origin, no plugins/objects, and don't let other sites frame us. An injected script from evil.com simply doesn't execute — the browser refuses. CSP is the most powerful header here and the most feared, because a too-strict policy breaks your own site. Rollout rule: deploy in report-only mode first (Content-Security-Policy-Report-Only), collect violation reports, tune, then enforce. Never start with 'unsafe-inline' — it re-allows exactly the injected inline scripts CSP exists to stop.
Strict-Transport-Security: HTTPS, always
Threat: SSL stripping — an attacker on the network downgrades your visitor's connection from HTTPS to HTTP and reads everything.
Defense:
Strict-Transport-Security: max-age=31536000; includeSubDomains
After one HTTPS visit, the browser remembers: this domain is HTTPS-only for a year, subdomains included — it upgrades even typed-in http:// URLs before sending anything. Note the bootstrap caveat: the first-ever visit must already be HTTPS for the header to be seen (HSTS preload lists solve this for major sites). Only send HSTS over HTTPS, and make sure subdomains are actually HTTPS-ready before adding includeSubDomains.
X-Frame-Options and frame-ancestors: stopping clickjacking
Threat: clickjacking — your page loaded invisibly inside an attacker's iframe; the victim clicks what looks like a harmless button but actually clicks your "delete account" button underneath.
Defense (modern): frame-ancestors 'self' inside your CSP — the current standard, supporting full origin lists. Defense (legacy): X-Frame-Options: DENY or SAMEORIGIN — still needed for older browsers. Send both; they don't conflict. Ignore ALLOW-FROM — it was never universally supported and is deprecated.
X-Content-Type-Options: stopping MIME-sniffing tricks
Threat: an attacker uploads a "profile picture" that's actually HTML+JavaScript; the browser sniffs the content, decides it's HTML despite the image content-type, and executes the script in your origin.
Defense:
X-Content-Type-Options: nosniff
One line: the browser must honor the declared Content-Type and never guess. Cheap, zero breakage risk for sane sites, no reason not to send it.
Check your site: enter any URL in our free HTTP Header Checker to see exactly which security headers your server sends — and which are missing.
Referrer-Policy and Permissions-Policy: limiting leaks and access
Threat (referrer): your page links to an external site, and the full URL — including session tokens or private paths in query strings — leaks via the Referer header. Defense: Referrer-Policy: strict-origin-when-cross-origin (the modern default-ish sane choice): same-origin requests keep the full URL, cross-origin leaks only the origin.
Threat (permissions): third-party iframes and scripts accessing camera, microphone, geolocation. Defense: Permissions-Policy: camera=(), microphone=(), geolocation=() disables sensitive features page-wide unless you explicitly allow them. If your site doesn't use the camera, say so — then a compromised script can't either.
Common misconfigurations to avoid
'unsafe-inline'in CSP — defeats the XSS protection for scripts/styles. Refactor to nonces or hashes instead.ALLOW-FROMin X-Frame-Options — deprecated, inconsistently supported; useframe-ancestors.- HSTS with short max-age or without includeSubDomains — weak protection theater; commit to a year once HTTPS is solid everywhere.
- Wildcard
*in CSP source lists — allows any origin, which is barely a policy at all. - Setting headers only on 200 responses — error pages need them too; configure at the server/CDN level, not per-route in app code.
Frequently asked questions
- What are HTTP security headers?
- HTTP response headers that instruct the browser how to handle your site securely: which scripts may run (CSP), whether HTTP is ever allowed (HSTS), whether the page may be framed (X-Frame-Options), and more. They're a free, server-side defense layer — no JavaScript required.
- Which security headers are most important?
- Content-Security-Policy (XSS defense), Strict-Transport-Security (HTTPS enforcement), X-Frame-Options / frame-ancestors (clickjacking defense), X-Content-Type-Options: nosniff (MIME-sniffing defense), and Referrer-Policy (leak control). Those five cover the highest-impact threats.
- What does Content-Security-Policy do?
- It whitelists where the browser may load resources from — scripts, styles, images, frames. If an attacker injects a malicious script (XSS), CSP blocks it because the attacker's source isn't on the list. It's the single most powerful browser-side XSS mitigation available.
- What is HSTS?
- HTTP Strict Transport Security: a header telling the browser "only ever contact this domain over HTTPS, for the next N seconds" — including converting typed-in http:// URLs before any request goes out. It defeats SSL-stripping attacks that downgrade connections to plaintext.
- How do I add security headers to my website?
- At your web server or CDN layer: Apache (.htaccess `Header set`), Nginx (`add_header`), or your CDN's rules (Cloudflare Transform Rules, etc.). Application frameworks can also emit them. Start with report-only mode for CSP, verify nothing breaks, then enforce.
- Will security headers break my site?
- They can, if misconfigured — an overly strict CSP blocks your own scripts and embeds. That's why CSP has a report-only mode: deploy `Content-Security-Policy-Report-Only` first, watch the violation reports, tune the policy, then switch to enforcing. The other headers rarely break anything.
- How do I test my security headers?
- Scan with securityheaders.com for a graded report, check manually in browser DevTools (Network tab → response headers), or use our HTTP Header Checker to see exactly what your server sends for any URL.
Related articles
Cron Expressions Explained: Syntax, Examples & Pitfalls
Reading cron syntax field by field, the examples you'll actually use, and the timezone/day-of-month traps that bite everyone once.
SecurityWhat Is a JWT? Structure, Claims & Security Explained
JSON Web Tokens explained: header, payload, and signature, what claims like exp and sub mean, and the security rules that actually matter.
Web DevelopmentBase64 Encoding Explained: How It Works & When to Use It
What base64 really does, why it inflates data by 33%, base64 vs base64url, and when to reach for it — and when not to.