Web Security

What Are HTTP Security Headers and Why Are They Important?

HTTP security headers are response headers that tell the browser how to handle your site safely — blocking XSS, clickjacking, protocol downgrades, and MIME confusion even when your app code has bugs. Here is the full header-by-header reference, with examples, a decision table, and the pitfalls a summary skips.

By Inventive HQ Team

The Invisible Shield: HTTP Security Headers

HTTP security headers are response headers a web server sends alongside a page to tell the browser how to handle that content safely — and because the browser enforces them, they keep protecting your users even when your application code has a bug. A handful of headers block the most common web attacks: Content-Security-Policy stops cross-site scripting (XSS), Strict-Transport-Security forces HTTPS to defeat downgrade and man-in-the-middle attacks, X-Frame-Options and CSP frame-ancestors stop clickjacking, X-Content-Type-Options stops MIME-sniffing, and Referrer-Policy and Permissions-Policy limit what leaks out and which browser features a page can reach.

That is the summary an AI overview will give you. What it can't give you is the part that actually matters when you sit down to configure a server: which headers to turn on first, which ones will break your site if you deploy them wrong, exactly what value to send, and how the newer cross-origin isolation headers (COOP/COEP/CORP) fit in. This guide is the full header-by-header reference — with a decision table, real config for Nginx, Apache, and Next.js, and the pitfalls that turn a security upgrade into an outage. It's the pillar for our security-header cluster; each header below links to a deep dive.

HTTP security headers as a browser-enforced defense layer Incoming attacks — XSS, clickjacking, protocol downgrade, and MIME sniffing — strike a shield made of security headers before reaching the application behind it. Headers are enforced by the browser, in front of your app XSS Clickjacking Downgrade MIME sniff Security headers Your app (may have bugs)

Despite their importance, security headers remain one of the most overlooked parts of web security — large-scale scans routinely find that the majority of sites are missing basics like HSTS and a real CSP. The good news is that they are cheap to add and, added in the right order, low-risk. Below is the complete map before we go header by header.

Every security header at a glance

Use this as the decision table. The four headers marked "safe to add first" almost never break a working site; CSP is the most powerful but needs a staged rollout.

HeaderWhat it stopsExample valueNotes
Strict-Transport-Security (HSTS)Protocol downgrade / SSL-strip MITMmax-age=31536000; includeSubDomains; preloadSafe to add first. Consider the HSTS preload list.
X-Content-Type-OptionsMIME-type sniffing → files run as scriptsnosniffSafe to add first. Only one valid value.
X-Frame-OptionsClickjacking (framing)DENY or SAMEORIGINSafe to add first. Pair with frame-ancestors; see X-Frame-Options vs frame-ancestors.
Referrer-PolicyReferrer URL leakage to third partiesstrict-origin-when-cross-originSafe to add first. Balances privacy with analytics.
Content-Security-Policy (CSP)XSS, injection, unwanted resource loadsdefault-src 'self'; script-src 'self'Most powerful, highest breakage risk. Roll out with report-only mode and handle third-party resources.
Permissions-PolicyAbuse of camera, mic, geolocation, etc.geolocation=(), camera=(), microphone=()Deny features you don't use. See Permissions-Policy explained.
Cross-Origin-Opener-Policy (COOP)Cross-window attacks (XS-Leaks)same-originPart of cross-origin isolation.
Cross-Origin-Embedder-Policy (COEP)Loading un-vetted cross-origin resourcesrequire-corpWith COOP, enables crossOriginIsolated.
Cross-Origin-Resource-Policy (CORP)Side-channel (Spectre) resource theftsame-originDeclares who may embed a resource.

Despite their critical importance, security headers remain one of the most overlooked aspects of web security. Studies consistently show that most websites fail to implement basic security headers, leaving users vulnerable to attacks that proper headers would prevent. Understanding and implementing these headers is essential for any website owner or developer concerned with security.

How HTTP Headers Work

Every time a browser requests a web page, the server responds with the requested content plus HTTP headers—metadata about the response:

Standard Response Headers

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Server: nginx

These headers tell the browser what type of content it's receiving and how to process it.

Security Response Headers

Security headers add protective instructions:

Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

These headers tell the browser:

  • Always use HTTPS for this site
  • Only load scripts from the same origin
  • Don't allow this page to be framed
  • Don't try to guess content types

Browsers that understand these headers enforce the policies, providing protection even if attackers find application vulnerabilities.

Critical Security Headers for 2025

1. Content-Security-Policy (CSP)

Purpose: Prevents XSS attacks by controlling which resources can load

How it works: Defines approved sources for scripts, styles, images, and other resources. Browsers refuse to load content from unapproved sources.

Example:

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

This policy:

  • Allows resources only from the same origin by default
  • Permits scripts from same origin and cdn.example.com
  • Allows inline styles (though this weakens protection)

2025 Best Practice: Use nonce-based CSP for dynamic content or hash-based CSP for static sites rather than 'unsafe-inline' which significantly weakens protection.

2. Strict-Transport-Security (HSTS)

Purpose: Forces browsers to always use HTTPS, preventing downgrade attacks

How it works: Once browsers receive this header, they refuse to connect over HTTP for the specified duration, even if users type "http://" in the address bar.

Example:

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

This tells browsers:

  • Enforce HTTPS for 31,536,000 seconds (1 year)
  • Apply to all subdomains
  • Include this site in the HSTS preload list

Critical: Submit your domain to the HSTS preload list for maximum protection. Preloading ensures browsers enforce HTTPS before the very first connection, eliminating the vulnerability window.

3. X-Frame-Options / frame-ancestors (CSP)

Purpose: Prevents clickjacking attacks by controlling whether pages can be embedded in frames

How it works: Tells browsers whether to allow the page to be displayed in <iframe>, <frame>, <embed>, or <object> elements.

X-Frame-Options example:

X-Frame-Options: DENY

Options:

  • DENY: Never allow framing
  • SAMEORIGIN: Allow framing only by same origin
  • ALLOW-FROM https://example.com: Allow specific origin (deprecated)

CSP frame-ancestors example:

Content-Security-Policy: frame-ancestors 'none'

Best Practice: Use both X-Frame-Options and CSP frame-ancestors for maximum compatibility. Modern browsers prefer frame-ancestors, but older browsers need X-Frame-Options. For a side-by-side breakdown of the two, read X-Frame-Options vs CSP frame-ancestors.

Advertisement

4. X-Content-Type-Options

Purpose: Prevents MIME-type sniffing attacks

How it works: Stops browsers from trying to "guess" content types, forcing them to respect the Content-Type header.

Example:

X-Content-Type-Options: nosniff

Why it matters: Without this header, browsers might interpret uploaded files as executable scripts even if the server sends them as images, creating XSS vulnerabilities.

5. Referrer-Policy

Purpose: Controls how much referrer information browsers send when navigating from your site

How it works: Determines what information the Referer header includes when users click links or load resources.

Example:

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

Options range from:

  • no-referrer: Never send referer information
  • strict-origin-when-cross-origin: Send full URL for same-origin, only origin for cross-origin HTTPS, nothing for HTTP
  • unsafe-url: Send full URL always (not recommended)

2025 Best Practice: Use strict-origin-when-cross-origin or no-referrer-when-downgrade to balance privacy with legitimate analytics needs.

6. Permissions-Policy (formerly Feature-Policy)

Purpose: Controls which browser features and APIs the site can use

How it works: Allows or denies access to features like geolocation, camera, microphone, etc.

Example:

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

This denies access to geolocation, microphone, and camera for all origins, preventing malicious scripts from accessing these features. For the full syntax and how it differs from the old Feature-Policy header, see what Permissions-Policy is and how it enhances security.

7. Cross-Origin Isolation: COOP, COEP, and CORP

Purpose: Defend against side-channel attacks (such as Spectre) and cross-window information leaks, and — as a bonus — unlock powerful browser APIs.

These three newer headers work together to control how your page interacts with content from other origins. They matter most for sites handling sensitive data or those that need high-precision timers and SharedArrayBuffer.

Cross-Origin-Opener-Policy (COOP) severs the connection between your page and any window that opened it (or that it opens via window.open), so another origin can't reach into your page's window object:

Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Embedder-Policy (COEP) requires every cross-origin resource your page loads to explicitly opt in (via CORP or CORS) before the browser will fetch it:

Cross-Origin-Embedder-Policy: require-corp

Cross-Origin-Resource-Policy (CORP) goes on your resources (images, scripts, fonts) to declare who is allowed to embed them, blocking side-channel theft:

Cross-Origin-Resource-Policy: same-origin

Why it matters: Sending Cross-Origin-Opener-Policy: same-origin together with Cross-Origin-Embedder-Policy: require-corp puts the page into a cross-origin isolated state (self.crossOriginIsolated === true). This is what re-enables SharedArrayBuffer and high-resolution timers that browsers disabled after Spectre. The trade-off: require-corp can break third-party embeds (ads, widgets, images) that don't send the right CORP or CORS headers, so test carefully before enforcing it.

Deprecated Headers to Avoid

Several older headers are now deprecated and can actually create vulnerabilities:

X-XSS-Protection

Status: Deprecated, do NOT use

Why: This header enabled browsers' built-in XSS filters, but research showed these filters could be exploited to create vulnerabilities rather than prevent them.

Instead: Use Content-Security-Policy which provides far better XSS protection

Public-Key-Pins (HPKP)

Status: Deprecated

Why: Certificate pinning could permanently lock users out of sites if keys were lost

Instead: Use Certificate Transparency monitoring

How Security Headers Protect Against Common Attacks

Cross-Site Scripting (XSS)

Attack: Injecting malicious scripts into websites to steal data or hijack sessions

Protection: Content-Security-Policy prevents execution of unauthorized scripts by whitelisting approved sources and blocking inline scripts

Example: Even if an attacker injects <script>alert('hacked')</script> into a page, CSP refuses to execute it

Clickjacking

Attack: Tricking users into clicking invisible iframes that perform unintended actions

Protection: X-Frame-Options and frame-ancestors prevent malicious sites from embedding your pages in invisible iframes

Example: Attacker can't overlay your banking site's "Transfer Money" button over a fake game to trick users into authorizing transfers

Man-in-the-Middle (MITM) Attacks

Attack: Intercepting communication between browser and server to steal or modify data

Protection: HSTS forces HTTPS, preventing attackers from downgrading connections to unencrypted HTTP

Example: Public WiFi attackers can't intercept your HSTS-protected site's traffic by redirecting to HTTP

Code Injection

Attack: Uploading malicious files that browsers execute as scripts

Protection: X-Content-Type-Options prevents MIME-type confusion, ensuring uploaded images aren't executed as JavaScript

Example: User uploads "image.jpg" containing JavaScript; nosniff prevents browser from executing it

Implementing Security Headers

Web Server Configuration

Headers are typically set in web server configuration:

Nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'" 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=(), camera=(), microphone=()" always;

Apache:

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

Application-Level Headers

Many frameworks allow setting headers in application code:

Express.js:

const helmet = require('helmet');
app.use(helmet());

Next.js:

// next.config.js
module.exports = {
  async headers() {
    return [{
      source: '/:path*',
      headers: [
        {
          key: 'Strict-Transport-Security',
          value: 'max-age=31536000; includeSubDomains'
        }
      ]
    }]
  }
}

Cloud Provider Settings

Many hosting platforms provide security header configuration:

Cloudflare: Transform Rules and Page Rules AWS CloudFront: Lambda@Edge or CloudFront Functions Vercel: vercel.json headers configuration Netlify: _headers file or netlify.toml

Testing and Validation

After implementing security headers, validate the configuration. Scan your live site right here — the analyzer fetches your headers and grades each one with specific fixes:

Loading interactive tool...

Online Scanners

Security Headers: securityheaders.com provides grades (A+ to F) Mozilla Observatory: observatory.mozilla.org comprehensive scanning Our tool: Security Headers Analyzer

Browser Developer Tools

Check actual headers received:

  1. Open Developer Tools (F12)
  2. Navigate to Network tab
  3. Reload page
  4. Click on the main document request
  5. View Response Headers

Verify all expected security headers are present with correct values.

CSP Reporting

Implement CSP reporting to monitor violations:

Content-Security-Policy: default-src 'self'; report-uri /csp-report

This sends reports of blocked resources to your endpoint, helping identify issues before enforcing stricter policies.

Common Implementation Mistakes

Starting Too Strict

Mistake: Implementing highly restrictive CSP immediately, breaking functionality

Solution: Start with report-only mode, monitor reports, gradually tighten policy:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

This is the single most important CSP habit — see what CSP report-only mode is for the full staged-rollout workflow, and how to handle CSP for third-party resources when analytics, ads, or embeds get blocked.

Inconsistent Headers

Mistake: Headers set on some responses but not others

Solution: Configure at web server level to ensure all responses include headers

Allowing 'unsafe-inline'

Mistake: CSP with 'unsafe-inline' to avoid refactoring code

Solution: Use nonces or hashes for legitimate inline scripts/styles

Forgetting Subdomains

Mistake: HSTS without includeSubDomains, leaving subdomains vulnerable

Solution: Include includeSubDomains directive and test all subdomains

Conclusion

HTTP security headers provide crucial protection against common web attacks including XSS, clickjacking, code injection, and man-in-the-middle attacks. These headers act as an additional defense layer that browsers enforce, protecting users even when application code has vulnerabilities.

Every website should implement at minimum: Content-Security-Policy (to prevent XSS), Strict-Transport-Security (to enforce HTTPS), X-Frame-Options/frame-ancestors (to prevent clickjacking), X-Content-Type-Options (to prevent MIME confusion), and Referrer-Policy (for privacy).

Start with basic implementations, test thoroughly, monitor for issues, and progressively strengthen policies. Avoid deprecated headers like X-XSS-Protection that can create vulnerabilities.

Proper security headers are no longer optional—they're essential for protecting your users and your website from modern threats.

Want to check your website's security headers? Try our free Security Headers Analyzer to scan your site and receive a detailed grade with specific recommendations for improvement.

Frequently Asked Questions

What are HTTP security headers?

HTTP security headers are response headers a web server adds to instruct the browser how to handle a page safely. They act as a browser-enforced defense layer that keeps working even when your application code has a vulnerability. The core set is Content-Security-Policy (blocks unauthorized scripts and XSS), Strict-Transport-Security (forces HTTPS), X-Frame-Options and CSP frame-ancestors (stop clickjacking), X-Content-Type-Options (stops MIME sniffing), Referrer-Policy (controls referrer leakage), and Permissions-Policy (gates browser features like camera and geolocation). The cross-origin isolation trio — COOP, COEP, and CORP — protects against side-channel and cross-window attacks.

What are the most important security headers to set first?

Start with four that give the biggest protection for the least risk of breaking your site: Strict-Transport-Security to enforce HTTPS, X-Content-Type-Options nosniff to stop MIME sniffing, X-Frame-Options DENY or SAMEORIGIN to stop clickjacking, and Referrer-Policy strict-origin-when-cross-origin to limit referrer leakage. These four almost never break a working site. Content-Security-Policy is the most powerful header but the most likely to break things, so add it last and roll it out in report-only mode first.

What is the difference between X-Frame-Options and CSP frame-ancestors?

Both control whether other sites can embed your page in a frame to prevent clickjacking. X-Frame-Options is the older header and only supports DENY or SAMEORIGIN — its ALLOW-FROM value is deprecated and unreliable. CSP frame-ancestors is the modern replacement: it accepts a list of allowed origins, supports wildcards, and is what current browsers honor when both are present. Best practice is to send both so old browsers get X-Frame-Options and modern ones enforce frame-ancestors.

Will Content-Security-Policy break my website?

It can, if you deploy a strict policy all at once — CSP blocks any script, style, image, or font from a source you did not explicitly allow, which frequently breaks inline scripts, analytics, ads, and third-party widgets. The safe path is to deploy Content-Security-Policy-Report-Only first, collect violation reports for a week or two, add the legitimate sources you find, and only then switch to the enforcing header. Use nonces or hashes instead of 'unsafe-inline' so you keep protection while allowing your own inline code.

Which security headers should I never use?

Avoid X-XSS-Protection — it enabled a legacy browser XSS filter that was itself exploitable and is now removed from modern browsers; Content-Security-Policy replaces it. Avoid HTTP Public Key Pinning (HPKP), which is deprecated because a lost or rotated key could permanently lock every visitor out of your site; use Certificate Transparency monitoring instead. Also drop the non-standard, deprecated X-Frame-Options ALLOW-FROM in favor of CSP frame-ancestors.

How do I test my security headers?

Load your site in a browser, open DevTools, go to the Network tab, click the main document request, and read the Response Headers. For a graded report, use an online scanner such as securityheaders.com or Mozilla Observatory, or the InventiveHQ Security Headers Analyzer, which flags missing headers and weak values with specific fixes. Re-test after every deployment, because a config change can silently drop headers on some responses.

What do COOP, COEP, and CORP headers do?

They are the cross-origin isolation headers that defend against side-channel attacks like Spectre and cross-window leaks. Cross-Origin-Opener-Policy (COOP) severs the link between your page and any window that opened it or that it opens. Cross-Origin-Embedder-Policy (COEP) requires every cross-origin resource to explicitly opt in before it can load. Cross-Origin-Resource-Policy (CORP) lets a resource declare who is allowed to embed it. Setting COOP same-origin plus COEP require-corp puts the page in a "cross-origin isolated" state, which is also what unlocks powerful APIs like SharedArrayBuffer.

Where should security headers be configured?

Set them at the highest layer that applies to every response so nothing is missed. That is usually the web server (Nginx add_header, Apache Header set), a security middleware such as Helmet for Express, framework config like next.config.js headers(), or an edge layer such as Cloudflare Transform Rules, CloudFront Functions, Vercel, or a Netlify _headers file. Setting them per-route in application code is the most error-prone approach because it is easy to leave a response uncovered.

HTTP headersweb securityXSS protectionCSPHSTS