Back to Blog
June 1, 2025Β·9 min read

Website Security Headers: The Complete Guide (CSP, HSTS, X-Frame-Options)

Security headers protect your website from XSS, clickjacking and data injection attacks. Learn what each header does and how to implement them β€” with a free checker.

HTTP security headers are one of the most overlooked aspects of website security. They're simple lines in your server configuration that can prevent a wide range of attacks β€” yet most websites are missing several of them. Here's everything you need to know.

What Are Security Headers?

Security headers are HTTP response headers that instruct browsers on how to handle your site's content. They tell the browser whether to allow embedding in iframes, which external resources to trust, and whether to enforce HTTPS connections. They're set at the server level and take effect on every page load.

Content-Security-Policy (CSP)

CSP is the most powerful β€” and most complex β€” security header. It defines which sources of content (scripts, styles, images, fonts) the browser is allowed to load. A properly configured CSP is one of the most effective defenses against Cross-Site Scripting (XSS), which is consistently in the OWASP Top 10.

  • βœ“Blocks inline scripts (a common XSS vector) unless explicitly allowed with nonces
  • βœ“Prevents loading of scripts from unauthorized domains
  • βœ“Can report policy violations to a specified endpoint for monitoring
  • βœ“Minimum starting point: Content-Security-Policy: default-src 'self'

Strict-Transport-Security (HSTS)

HSTS tells browsers to only connect to your site over HTTPS β€” even if the user types 'http://' or clicks an HTTP link. This prevents SSL stripping attacks and ensures all connections are encrypted.

  • βœ“Recommended value: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • βœ“The preload directive allows inclusion in browser HSTS preload lists
  • βœ“Do not enable before your site is fully on HTTPS β€” it can lock users out of HTTP fallback

X-Frame-Options

X-Frame-Options prevents your site from being embedded in iframes on other domains β€” protecting against clickjacking attacks, where attackers overlay invisible frames to trick users into clicking malicious content.

  • βœ“X-Frame-Options: DENY β€” never allow framing by any page
  • βœ“X-Frame-Options: SAMEORIGIN β€” only allow framing by the same domain
  • βœ“Modern alternative: use CSP's frame-ancestors directive for more granular control

X-Content-Type-Options

This header prevents browsers from 'sniffing' the MIME type of a response and interpreting files differently from what your server declared. Without it, a browser might execute a file uploaded as an image but containing JavaScript. Always set: X-Content-Type-Options: nosniff.

Referrer-Policy

Controls how much referrer information is included when users navigate away from your site. Without this header, the full URL (including query parameters that might contain user IDs or tokens) is sent to external sites. Recommended: Referrer-Policy: strict-origin-when-cross-origin.

Permissions-Policy

Formerly known as Feature-Policy, this header controls which browser features and APIs your page can use β€” camera, microphone, geolocation, payment, etc. Restricting these protects users if your site is compromised by a malicious third-party script.

β†’

Check which security headers your website is missing with Scanlei's free security scanner. Get a detailed report with remediation steps in under 60 seconds.

Scan your website free

How to Add Security Headers

In Next.js

Add a headers() function to your next.config.js or next.config.ts to apply security headers to all routes. This is the recommended approach for Next.js applications and takes effect on every server response.

In Vercel

Add a headers array to vercel.json with source patterns and header key-value pairs. Changes deploy automatically on your next push and apply globally to your deployment.

In Nginx

Use add_header directives in your server block. Apply them at the server level to ensure headers are sent with all responses, including static files.

Priority Order for Implementation

  • βœ“1. HTTPS everywhere + HSTS β€” foundational, must come first
  • βœ“2. X-Content-Type-Options: nosniff β€” trivial to add, high impact
  • βœ“3. X-Frame-Options β€” simple one-liner, prevents clickjacking
  • βœ“4. Referrer-Policy β€” easy, protects user privacy from leakage
  • βœ“5. CSP β€” complex but most powerful; start in report-only mode
  • βœ“6. Permissions-Policy β€” fine-tune after other headers are stable

Common Mistakes to Avoid

  • βœ“Setting HSTS before full HTTPS migration β€” locks users out of HTTP fallback
  • βœ“CSP that's too restrictive β€” breaks your own scripts and styles, causes complaints
  • βœ“Forgetting subdomains β€” headers on the main domain don't cover subdomains automatically
  • βœ“Not testing after adding headers β€” always verify with a scanner after changes

Ready to scan your website?

25 free credits. No credit card required.