Guide

HTTP Security Headers: The Complete Guide (2026)

HTTP security headers are response headers that tell the browser how to behave more safely — they neutralise clickjacking, protocol downgrade, MIME-sniffing and much of XSS, usually in a single line of configuration each.

By Paul Rudenko, Security ResearcherUpdated Jun 26, 20269 min read

HTTP security headers are response headers a web server sends with every page that tell the browser how to behave more safely — which scripts it may run, whether the page can be framed, whether to insist on HTTPS. They are among the cheapest, highest-leverage defences on the web: most are a single line of configuration, and together they neutralise whole classes of attack such as clickjacking, protocol downgrade, MIME-sniffing and a large share of cross-site scripting (XSS) impact.

This guide explains each header that matters in 2026, gives a copy-paste baseline you can deploy today, and covers the mistakes that quietly break them. It is grounded in the relevant IETF RFCs and the OWASP Secure Headers Project, the two reference sources for this topic.

What are HTTP security headers?

Every time a browser requests a page, the server replies with a status line, a body (the HTML) and a set of response headers — key/value metadata about the response. Most headers are mundane (Content-Type, Cache-Control).

A subset of them instruct the browser to enforce specific security behaviours. Because the browser enforces them, a correct header protects every visitor automatically, with no change to your application code.

Critically, these headers are read passively. Anyone — including an attacker, a search engine, or a checker like this one — can see exactly which headers your site returns by making a single ordinary request. There is no “scan” to detect; the configuration is public the moment your site is online. That is also why getting them right is worth the few minutes it takes.

Why do security headers matter?

Headers are a defence-in-depth layer. They do not replace fixing the underlying bug, but they dramatically reduce what an attacker can do when something else goes wrong. Three concrete examples:

Protocol downgrade. Without HSTS, a visitor who types example.com makes a first request over plaintext HTTP. An attacker on the same network can intercept that request before the redirect to HTTPS ever happens (the classic SSL-strip attack). HSTS tells the browser to never use HTTP for your domain again.

Clickjacking. Without a framing policy, an attacker can load your site inside an invisible iframe over their own page and trick a logged-in user into clicking buttons they cannot see. X-Frame-Options and CSP frame-ancestors forbid that.

Cross-site scripting. If an attacker injects a <script> into your page, a Content-Security-Policy that only allows scripts from your own origin can stop that injected script from executing at all — turning a critical XSS into a non-event.

The headers that matter, one by one

At a glance, here is what each header defends against and a sane default value. Each is explained in detail below.

HeaderProtects againstSane default
Strict-Transport-SecurityProtocol downgrade / SSL-stripmax-age=63072000; includeSubDomains; preload
Content-Security-PolicyCross-site scripting (XSS)default-src 'self'
X-Content-Type-OptionsMIME-sniffingnosniff
X-Frame-OptionsClickjackingDENY
Referrer-PolicyURL / token leakagestrict-origin-when-cross-origin
Permissions-PolicyUnwanted feature accessgeolocation=(), camera=(), microphone=()
Cross-Origin-Opener-PolicyCross-window (Spectre-class) attackssame-origin

Strict-Transport-Security (HSTS)

Defined in RFC 6797, HSTS forces the browser to use HTTPS for your domain for a fixed period, eliminating the plaintext-first-request window. Set a long max-age (two years is standard) once you are confident every subdomain serves HTTPS.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
The preload directive opts your domain into a list hard-coded into Chrome, Firefox, Safari and Edge, so even the very first visit is HTTPS. Only add it once includeSubDomains is safe for you — preload removal takes months to propagate.

Content-Security-Policy (CSP)

The single most effective header against XSS, and the hardest to deploy. CSP is an allow-list of where scripts, styles, images and other resources may load from (the MDN reference documents every directive). Start strict and widen deliberately:

Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

Avoid 'unsafe-inline' for scripts where you can — it disables much of CSP's protection. For apps that need inline scripts, use a per-request nonce or hash instead. Deploy with Content-Security-Policy-Report-Only first to catch breakage without blocking anything.

X-Content-Type-Options

One value, no downside. It stops the browser from second-guessing (“sniffing”) the declared content type, which prevents an uploaded file from being reinterpreted as executable script.

X-Content-Type-Options: nosniff

X-Frame-Options & frame-ancestors

Controls whether your pages may be embedded in a frame. The modern mechanism is the CSP frame-ancestors directive; the older X-Frame-Options header is still worth sending for legacy browsers. Use both, kept consistent.

X-Frame-Options: DENY

Referrer-Policy

Limits how much of the originating URL is sent to other sites when a user clicks a link or loads a third-party resource — stopping full URLs (which may contain tokens or IDs) from leaking.

Referrer-Policy: strict-origin-when-cross-origin

Permissions-Policy

Disables powerful browser features your site does not use — camera, microphone, geolocation — so that injected or third-party code cannot quietly access them.

Permissions-Policy: geolocation=(), camera=(), microphone=()

Cross-Origin-Opener-Policy (COOP)

Isolates your page into its own browsing-context group, defending against cross-window attacks such as those in the Spectre family. Safe for most sites that do not depend on cross-origin popups.

Cross-Origin-Opener-Policy: same-origin

For a typical site that serves its own content, this is a sound starting set. Add it incrementally — CSP last and in report-only mode — and re-test after each change.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
Cross-Origin-Opener-Policy: same-origin
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

Want to see which of these your site already sends?

Run the free Security Headers Checker →

What are the most common mistakes?

Setting the header on only one path. Security headers must be sent on every response — including redirects, error pages and assets. A common failure is configuring them on the app but not on the front-end proxy or CDN that actually terminates the connection.

HSTS without full HTTPS. If any subdomain still needs HTTP, do not send includeSubDomains — you will lock visitors out of it. Confirm every host is HTTPS first.

CSP with 'unsafe-inline' everywhere. A policy that allows all inline scripts technically “has a CSP” but provides little XSS protection. Treat removing inline script as the real goal.

Duplicate or conflicting headers. If both your application and your proxy set the same header, browsers may see two values and behave unpredictably. Set each header in exactly one place.

How do I monitor and report CSP violations?

A policy you cannot observe is a policy you cannot tighten. Content-Security-Policy supports a reporting channel that tells you what it would have blocked, which is how you deploy a strict policy without breaking the site. Run it in report-only mode first: the browser enforces nothing but sends a JSON report for every violation, so you can find the legitimate scripts and styles you need to allow before you switch on enforcement.

Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint

The modern delivery mechanism is the Reporting API, configured with a Reporting-Endpoints header that names where reports should be sent; the older report-uri directive is still widely honoured and worth keeping alongside it for coverage.

Whichever you use, route the reports somewhere you will actually read — a collector you own or a third-party service — and review them before promoting a report-only policy to an enforcing one. Treat the first week of reports as a to-do list, not a finished result.

Expect noise. Browser extensions, injected corporate proxies and antivirus tooling generate CSP violation reports that have nothing to do with your site. Filter by the document-uri and blocked-uri fields and look for patterns from your own origins before you widen the policy.

Which headers can I stop sending?

Several headers that still appear in older hardening checklists are now deprecated or actively counter-productive. Sending them wastes bytes and, in one case, can introduce a vulnerability.

X-XSS-Protection controlled a legacy browser XSS filter that no major browser ships any more. The filter itself could be abused to create information-leak side channels, so current guidance is to send X-XSS-Protection: 0 (explicitly off) or simply omit it and rely on a real Content-Security-Policy instead.

Expect-CT enforced Certificate Transparency during a transition period that has ended; CT is now mandatory in browsers by default, and the header is deprecated. Drop it.

Feature-Policy was renamed and redesigned as Permissions-Policy. If you still send the old header, migrate to Permissions-Policy — the syntax differs, so do not just rename it. Sending both is harmless but redundant.

Public-Key-Pins (HPKP) is the cautionary tale: it let sites pin specific certificate keys, but a mistake could lock every visitor out of the site for the pin's lifetime. Browsers removed support for it. Never deploy it.

How to check your site

You can read your own headers with a single request — for example curl -I https://example.com — but interpreting which are missing, weak or misconfigured against current best practice is the slow part. The free SecScan Security Headers Checker does exactly that: it reads the headers your homepage already returns, grades each against the OWASP recommendations, and gives you the precise value to add. It is passive — equivalent to a single curl request — and needs no signup.

Once headers are in place, the same configuration feeds into your overall website security score, alongside your TLS configuration and exposed-file checks.

Frequently asked questions

What are the most important HTTP security headers?

The highest-impact headers are Strict-Transport-Security (HSTS), which forces HTTPS; Content-Security-Policy (CSP), the strongest defence against cross-site scripting; X-Content-Type-Options: nosniff; a framing policy via X-Frame-Options or CSP frame-ancestors; Referrer-Policy; and Permissions-Policy. Together they cover protocol downgrade, XSS, clickjacking, MIME-sniffing and feature abuse.

Are security headers enough on their own?

No. Security headers are a defence-in-depth layer — they reduce the impact of other vulnerabilities but do not replace fixing them. A site still needs secure code, current TLS, patched software and no exposed files. Headers are the cheapest layer to add, not the only one.

Will adding a Content-Security-Policy break my site?

It can if deployed carelessly, because CSP restricts where scripts and styles may load from. Deploy it first with the Content-Security-Policy-Report-Only header, which reports violations without blocking anything, fix the reported issues, then switch to the enforcing header.

How do I check which security headers my website sends?

You can run curl -I against your URL to see the raw headers, or use a free checker that grades them against best practice. The SecScan Security Headers Checker reads your homepage headers passively and returns a pass/fail for each with the exact value to add.

Related guides

See your whole external attack surface

One page is a start. The full external scan covers TLS, headers, DNS, exposed files, open services and known-exploited CVEs across your whole domain.

See the full scan →