Security headers checker: test your site's headers and learn to fix them

Short answer: Security headers are instructions your site sends to the browser along with each page. They tell it to always use HTTPS, which scripts to trust, whether other sites may put your page in a frame, and more. They're free to add, usually in one config file, and they cut down common browser-side attacks. They don't fix problems in your code or database.

Only check sites you own or have permission to test. Last checked: Oct 17, 2026 · Source: OWASP HTTP Headers Cheat Sheet

The 6 headers that matter most, in plain words

HeaderWhat it doesA common starting value
Strict-Transport-Security (HSTS)Tells browsers to only ever load your site over HTTPS, even if someone types http://.max-age=63072000 (add includeSubDomains only after reading below)
Content-Security-Policy (CSP)Lists where scripts, styles, images and other files may load from. If an attacker manages to inject a script, the browser can refuse to run it.Depends on your app (see below)
X-Content-Type-OptionsStops the browser from "guessing" a file's type, so a file can't be passed off as a script.nosniff
CSP frame-ancestors / X-Frame-OptionsControls whether other sites can show your page inside a frame. Blocking that helps prevent "clickjacking", where someone hides your page under a fake button.frame-ancestors 'none' (in CSP) or X-Frame-Options: DENY
Referrer-PolicyControls how much of your page's address is shared with other sites when visitors click a link or load a file.strict-origin-when-cross-origin
Permissions-PolicyTurns off browser features you don't use, like camera, microphone or location, so injected code can't switch them on.camera=(), microphone=(), geolocation=()

A little more on each

HSTS. Once a browser sees this header over HTTPS, it remembers to use HTTPS for as long as max-age says (63072000 seconds is two years). includeSubDomains covers every subdomain too, so only add it if all of them work over HTTPS. There's also a preload option that gets your domain built into browsers' HTTPS-only lists (hstspreload.org). OWASP warns that a misconfigured HSTS setup can lock visitors out, so read the requirements first and treat preload as hard to undo. MDN: Strict-Transport-Security

CSP. This is the most powerful header and the easiest to get wrong. Too strict, and parts of your site stop loading. Too loose (for example 'unsafe-inline' scripts or * sources), and it protects little. The safe way to start is the Content-Security-Policy-Report-Only header: the browser reports what would be blocked without blocking anything. Fix what it reports, then switch to the real header. A simple starting point for a site that loads everything from its own domain:

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

Apps that load scripts from other domains (analytics, payments, chat widgets, your Supabase project URL for API calls) need to list those domains. MDN: CSP guide · OWASP CSP Cheat Sheet

X-Content-Type-Options. There's only one value, nosniff, and it's safe to add almost everywhere. Make sure your server sends the right Content-Type for each file. MDN

frame-ancestors vs. X-Frame-Options. Both control framing. frame-ancestors is the newer, more flexible option inside CSP, and OWASP recommends it where possible. Many sites send both, so older browsers are covered too. Use 'none' / DENY unless you actually need your pages embedded somewhere. MDN: frame-ancestors · MDN: X-Frame-Options

Referrer-Policy. Modern browsers already default to strict-origin-when-cross-origin, but OWASP suggests setting it explicitly instead of relying on the default. Use something stricter, like no-referrer, if your URLs can contain private details. MDN

Permissions-Policy. List the features your site doesn't use, with empty parentheses to turn them off. If your app does use the camera (for example, for video calls), leave that one out or allow only your own site. MDN

How to check your own site's headers

Only check sites you own or have permission to test.

Option 1: your browser. Open your site, then open DevTools (F12 or right-click → Inspect). Go to the Network tab, reload the page, click the first request (your page's address) and look under Response Headers. (Chrome DevTools: Network reference)

Option 2: the command line. Replace the address with your own domain:

curl -sI https://your-own-site.com

Look for the six header names in the output.

Option 3: a free Greenlight scan. Paste your site's address into the box at the top of this page. Greenlight's free scan checks whether common security headers are set, along with other basics (HTTPS, exposed keys). It checks that headers are present, not whether every value is right for your app. It's not a full security audit.

Check more than your homepage. Headers can differ between pages, files and API routes, especially when some pages are served by functions.

How to add security headers on common hosts

Vercel

Add a headers section to vercel.json in your project's root folder. This applies the headers to every path:

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
        { "key": "Content-Security-Policy-Report-Only", "value": "default-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'" }
      ]
    }
  ]
}

Using Next.js? You can set the same headers in next.config.js with an async headers() function instead. Use one place, not both, so they don't conflict. Next.js: headers

Netlify

Either add a plain-text _headers file to your publish folder (the folder that gets deployed, such as dist):

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

…or add the same values to netlify.toml:

[[headers]]
  for = "/*"
  [headers.values]
    X-Content-Type-Options = "nosniff"
    X-Frame-Options = "DENY"
    Referrer-Policy = "strict-origin-when-cross-origin"

Other hosts

Most hosts and servers (Apache, Nginx, Express and others) can set response headers too. OWASP's cheat sheet has short examples for several of them. OWASP HTTP Headers Cheat Sheet

After any change: redeploy, then check again with DevTools, curl -I or the scan above. Click through your app (login, payments, embeds) to make sure nothing broke.

What security headers don't do

Headers protect visitors' browsers. They don't protect your database or your API keys. If your app uses Supabase, two other things matter more for your data: whether your anon key is set up safely and whether Row Level Security is on with the right policies. A site can have perfect headers and still expose data through a table without RLS.

Run a free check →

Paid reports: coming soon.

FAQ

What is a security headers checker?
A tool that loads your page and reports which security-related response headers your site sends, such as HSTS, CSP and X-Content-Type-Options. You can also check by hand in your browser's DevTools.

Which security headers should every site have?
A good baseline is HSTS, X-Content-Type-Options, a frame-blocking rule (CSP frame-ancestors or X-Frame-Options), Referrer-Policy, Permissions-Policy, and a Content-Security-Policy tuned to your app.

Can adding security headers break my site?
Yes, mainly CSP and HSTS. A strict CSP can block scripts your site needs, so start with Content-Security-Policy-Report-Only. HSTS with includeSubDomains or preload can lock out subdomains that don't support HTTPS, so check them first.

Do I still need X-Frame-Options if I use CSP frame-ancestors?
frame-ancestors is the newer option, and OWASP recommends it where possible. Many sites send both, so older browsers are covered too.

Should I set X-XSS-Protection?
OWASP advises against relying on it and recommends either not setting it or setting it to 0, and using a CSP instead.

Does Vercel or Netlify add security headers automatically?
Vercel adds HSTS by default (see its Encryption docs). For the other headers on this page, plan to add them yourself on both hosts, as shown above.

Does Greenlight fix my headers?
No. The free scan checks whether common security headers are set and tells you which ones are missing. You add the headers yourself using the steps above. Paid reports are coming soon.

Sources

Related on Greenlight: Is the Supabase anon key safe to expose? · Supabase RLS for beginners · Will Supabase's October 30 change break your app?

Greenlight is independent and not affiliated with or endorsed by Vercel, Netlify, Next.js, Supabase, Mozilla or OWASP. Product names are used only to describe compatibility. This page is educational, not a security audit or a security guarantee.