The Complete Guide to HTTP Security Headers

Learn which HTTP security headers your site needs, what each one does, and how to implement them to protect against XSS, clickjacking, and data injection.

8 min read Security

HTTP security headers are one of the fastest wins in web security. A handful of response headers can block entire categories of attacks — cross-site scripting (XSS), clickjacking, MIME sniffing, and more. Yet most websites have none of them configured.

HTTP security headers are directives sent by a web server to a browser that control how the page is loaded and interpreted. They protect against XSS, clickjacking, protocol downgrade attacks, and data injection without requiring any changes to your website's code. The most important headers are Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy.

Essential security headers at a glance:

Header Primary Protection Difficulty
Content-Security-Policy (CSP) XSS, data injection Medium
Strict-Transport-Security (HSTS) SSL stripping, downgrade attacks Low
X-Frame-Options Clickjacking Low
X-Content-Type-Options MIME sniffing attacks Low
Referrer-Policy Privacy, data leakage Low
Permissions-Policy Unauthorized browser features Low

This guide covers every important security header, what it does, and how to set it up.

Why Security Headers Matter

When your server sends a response, it can include headers that instruct the browser on how to handle your content. These headers cost nothing in performance but add meaningful protection:

  • They don't require changes to your application code
  • They're effective immediately after deployment
  • They signal trustworthiness to security auditors and customers

You can check your current headers at Website Linter — our security scan checks all of the headers below.

1. Content-Security-Policy (CSP)

Protects against: XSS, data injection, clickjacking

CSP is the most powerful and most complex security header. It tells browsers which sources are allowed to load scripts, styles, images, and other resources.

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com

Key CSP directives:

Directive What It Controls
default-src Fallback for all resource types
script-src JavaScript sources
style-src CSS sources
img-src Image sources
connect-src XHR, fetch, WebSocket
frame-ancestors Which origins can embed your page

Start with Report-Only mode. Set Content-Security-Policy-Report-Only first to collect violations without breaking anything, then tighten your policy.

2. Strict-Transport-Security (HSTS)

Protects against: Protocol downgrade attacks, SSL stripping

HSTS tells browsers to always use HTTPS for your domain — even if a user types http:// or clicks an HTTP link.

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Parameters explained:

  • max-age=31536000 — Cache this policy for 1 year (required for HSTS preload)
  • includeSubDomains — Apply to all subdomains
  • preload — Submit your domain to the HSTS Preload List for hardcoded browser protection

⚠️ Do not enable this until you're fully committed to HTTPS. Once set with a long max-age, reverting to HTTP will break your site for users who have the cached header.

3. X-Frame-Options

Protects against: Clickjacking

Prevents your site from being embedded in iframes on other domains.

X-Frame-Options: DENY

Or to allow framing only from the same origin:

X-Frame-Options: SAMEORIGIN

Note: This header is superseded by Content-Security-Policy: frame-ancestors, but X-Frame-Options has better support in older browsers. Implement both.

4. X-Content-Type-Options

Protects against: MIME sniffing attacks

Prevents browsers from guessing the content type of a response if the server gets it wrong.

X-Content-Type-Options: nosniff

This is a single-value header — just add nosniff and move on. There's no reason not to have it.

5. Referrer-Policy

Protects: User privacy, prevents leaking sensitive URLs

Controls how much referrer information is included with requests when navigating away from your site.

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

Common values:

Value Behavior
no-referrer Never send referrer
origin Send only the domain
strict-origin-when-cross-origin Full URL for same-origin, domain-only for cross-origin HTTPS
unsafe-url Always send full URL (not recommended)

strict-origin-when-cross-origin is the recommended default — it balances privacy with analytics functionality.

6. Permissions-Policy

Protects against: Unauthorized use of browser features

Restricts which browser APIs and features can be used by your page or embedded third-party content.

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

This header replaces the older Feature-Policy. Restrict everything you don't explicitly need.

7. Cross-Origin-Opener-Policy (COOP) and Cross-Origin-Embedder-Policy (COEP)

These headers are required to enable powerful browser features like SharedArrayBuffer and high-resolution timers:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

If you're not using those APIs, COOP: same-origin-allow-popups is a safer choice that avoids breaking OAuth popup flows.

Implementation by Platform

Nginx

add_header Content-Security-Policy "default-src 'self';" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Apache

Header always set Content-Security-Policy "default-src 'self';"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

Cloudflare Workers / CDN

If you're using Cloudflare, you can inject headers via Transform Rules without touching your server config.

Checking Your Score

Once you've added headers, verify them at Website Linter. Our security scanner checks all of the above headers and gives you a grade from A to F with specific remediation steps. Most sites can get from F to B in under 30 minutes.

A strong security header score signals professionalism to customers, passes security audits faster, and meaningfully reduces your attack surface.