Guides Create account 🇬🇧 🇩🇪

Security guide

HTTP security headers, explained

Response headers are one of the cheapest, highest-impact ways to protect the people who visit your website. This guide walks through the six headers that matter most, what each one does, why it is worth setting and exactly how to configure it in nginx.

Scan my headers Jump to the headers

01 Why they matter

Small headers, big protection

A browser trusts whatever your server tells it. Security headers are short instructions in every HTTP response that tell the browser how to behave: which connections to trust, what content it may load and how much information to leak. Set them well and entire classes of attack, from protocol downgrades to clickjacking and cross-site scripting, simply stop working. Leave them out and the browser falls back to permissive defaults.

02 The headers

Six headers worth setting today

Strict-Transport-Security HSTS

What it does. Tells the browser to only ever reach your site over HTTPS, and to remember that decision for the given max-age. After the first visit, the browser upgrades every request to HTTPS itself, before any traffic leaves the device.

Why it matters. Without it, an attacker on the network can strip the first plain-HTTP request and downgrade the connection. HSTS closes that window and makes secure transport non-negotiable.

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Content-Security-Policy CSP

What it does. Defines an allow-list of the sources a page may load scripts, styles, images and other resources from, and can forbid inline scripts entirely.

Why it matters. It is the single strongest defence against cross-site scripting (XSS). Even if an attacker injects a script tag, the browser refuses to run it unless the policy allows its source. Start in report-only mode, then enforce.

add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;

X-Frame-Options

What it does. Controls whether your pages may be embedded in a frame or iframe on another site. DENY blocks all framing; SAMEORIGIN allows only your own origin.

Why it matters. It stops clickjacking, where an attacker overlays your site invisibly on theirs to trick users into clicking. Modern browsers also honour the CSP frame-ancestors directive, but this header covers older clients.

add_header X-Frame-Options "DENY" always;

X-Content-Type-Options

What it does. Set to nosniff, it tells the browser to trust the declared Content-Type and never try to guess (sniff) a different one.

Why it matters. MIME sniffing can turn an innocent-looking upload into an executable script. Disabling it removes a whole category of content-confusion attacks with a single, safe value.

add_header X-Content-Type-Options "nosniff" always;

Referrer-Policy

What it does. Decides how much of the referring URL is sent when a visitor clicks a link away from your site or loads a third-party resource.

Why it matters. Full referrers can leak paths, tokens or search terms to other sites. A strict policy shares just enough for analytics while keeping sensitive URLs private.

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Permissions-Policy

What it does. Lets you switch off powerful browser features such as camera, microphone and geolocation for your site and anything it embeds.

Why it matters. If your site never needs the camera, disabling it means a compromised or malicious embed cannot ask for it either. It shrinks your attack surface to only the features you actually use.

add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

03 Putting it together

A safe starting point

Add the directives inside the server block that serves your site, reload nginx and test. Roll out Content-Security-Policy carefully: begin with Content-Security-Policy-Report-Only, watch what would have been blocked, then switch to the enforcing header once the policy fits your site.

server { add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" 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; }

See which headers your site is missing

Our free Quickscan checks your live response headers alongside data protection, sustainability, accessibility, SEO and performance, then explains every finding in plain language.

Scan a website Latest scans
Recent scans Guides Pricing API Data protection Imprint © 2026 Erseni