Skip to content

Security

Security headers check

Five response headers do most of the work of protecting a website's visitors in the browser. Here is what each one does, a safe value to start from, and how to set them.

Check your site's headers

Free, no account. We grade these five headers, look for secret keys in the page's code and cookies without their protections, and list every error on five of your pages.

Check only sites you run or have permission to check.

Strict-Transport-Security

Tells browsers to use https for your site for a given time, even if someone types or follows an http:// link. Without it, a visitor's first request can go out over plain http, where a network in the middle can redirect or read it.

A safe value to start from
Strict-Transport-Security: max-age=31536000; includeSubDomains

Send this value only once every subdomain serves https, because browsers will then refuse http on all of them for a year. If unsure, start with a short max-age.

Content-Security-Policy

Lists where scripts, styles, images and connections may come from. If an attacker manages to inject a script tag (through a comment field, a compromised plugin), the browser refuses to run it because its source is not on the list.

A safe value to start from
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: https:; frame-ancestors 'none'

This is the hardest one to get right, because a strict policy breaks anything you left off the list. Ship it first as Content-Security-Policy-Report-Only, read what it would have blocked, then enforce it.

Framing protection (X-Frame-Options or frame-ancestors)

Stops other sites from showing yours inside a hidden frame and tricking visitors into clicking buttons they cannot see (clickjacking).

A safe value to start from
X-Frame-Options: DENY
# or, in the Content-Security-Policy:
frame-ancestors 'none'

Use SAMEORIGIN (or frame-ancestors 'self') if your own site frames its pages.

X-Content-Type-Options

Stops the browser guessing a file's type from its contents. Without it, an uploaded file that looks like a script can be run as one.

A safe value to start from
X-Content-Type-Options: nosniff

Safe to add everywhere, as long as your server sends correct content types (JavaScript as text/javascript).

Referrer-Policy

Controls how much of your page's address other sites see when a visitor follows a link or loads an image from them. Addresses can carry tokens, emails or search terms.

A safe value to start from
Referrer-Policy: strict-origin-when-cross-origin

This is also the browser's default today; setting it makes it explicit and stops an older default applying.

How to set them

Wherever your site is served from, headers are one block of configuration.

nginx, Next.js, Netlify, Vercel, Cloudflare
# nginx, in the server block
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Next.js, next.config.js
async headers() {
  return [{ source: "/(.*)", headers: [
    { key: "X-Content-Type-Options", value: "nosniff" },
    { key: "X-Frame-Options", value: "DENY" },
    { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  ] }];
}

# Netlify, a _headers file at the site's root
/*
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin

# Vercel (any framework): "headers" in vercel.json, same shape as Next.js
# Cloudflare: Rules → Transform Rules → Modify Response Header

Headers are one part

The leaks that cost the most have nothing to do with headers: a secret key shipped in the page’s JavaScript, a database open to anyone with its public key, an API route that does not check who is calling. The web app security checklist covers them.