Code Beautifier
Security & Auth

HTTP security headers in plain English

What HSTS, CSP, X-Frame-Options, Referrer-Policy and Permissions-Policy each prevent, safe default values, and how to check a live response.

Security headers are the cheapest security work a web application can do. Each one is a single line in a response that instructs the browser to refuse a category of attack on your behalf. They cost nothing at runtime, they need no library, and most sites ship none of them — because the names are opaque and the documentation assumes you already know what a "clickjacking" is. This is the plain-language version: what each header stops, and the value to start with.

Strict-Transport-Security: never downgrade to HTTP

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

HSTS tells the browser: for the next year, talk to this host over HTTPS only, even if a link or a typed address says http://. Without it, the first request to http://yoursite is a plain-text request that an attacker on the same network can intercept and answer, and the user never reaches the real site. With it, the browser rewrites the request to HTTPS before it leaves the machine.

Start with a short max-age (a day) to confirm nothing breaks, then raise it. Add preload only once every subdomain serves HTTPS, because preloading is hard to undo.

Content-Security-Policy: only run code from where you say

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

CSP is the header that stops cross-site scripting from executing. Even if an attacker gets a <script> tag into your page, the browser refuses to run it unless the policy allows scripts from that origin. 'self' means your own origin; inline scripts and eval are blocked unless you explicitly allow them, which you should avoid.

It is also the header most likely to break something, because it forbids inline scripts and styles that many sites rely on. Deploy it as Content-Security-Policy-Report-Only first, collect the violations, fix them, then enforce.

X-Frame-Options and frame-ancestors: no embedding in other sites

X-Frame-Options: DENY

Clickjacking is an attacker's page loading yours in an invisible iframe and tricking the user into clicking something in it — "Delete account", say, positioned exactly under a fake "Play video" button. DENY tells the browser never to render your page inside a frame. SAMEORIGIN allows your own site to frame itself.

The modern equivalent is frame-ancestors inside CSP, which supports a list of allowed origins. Send both while older browsers exist.

X-Content-Type-Options: trust the declared type

X-Content-Type-Options: nosniff

Browsers historically "sniffed" content: if a response said text/plain but looked like JavaScript, some would run it. That let an attacker upload a file that was text to your server and script to the browser. nosniff disables the guessing and makes the Content-Type header authoritative. There is no reason not to send it.

Referrer-Policy: what you tell the next site

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

When a user clicks a link, the browser tells the destination where they came from, including the full URL — which may contain a session token, a search query, or a document ID. This value sends only your origin (https://yoursite) to other sites, and the full URL only to your own. It is also now the browser default in Chromium and Firefox, but sending it explicitly removes the dependence on defaults.

Permissions-Policy: features the page will never use

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

Every browser feature a page does not use is a feature an injected script could abuse. Listing them with an empty allowlist disables them for the page and every frame in it. Start from the features your application genuinely does not need; a formatter site has no reason to touch the camera.

Two headers that are not about security but get graded

Access-Control-Allow-Origin is about which other sites may read your API's responses, and its interaction with credentials has its own failure mode — the wildcard with credentials is the one that breaks logins. Set-Cookie attributes (Secure, HttpOnly, SameSite=Lax) are not headers of their own but are worth the same scrutiny.

Checking a real response

Reading a policy off a document is not the same as seeing what the server sends. Copy the response headers from the browser's network panel — or from curl -I — and paste them into HTTP Headers Inspector. It grades each of the headers above, keeps repeated headers like Set-Cookie as a list rather than overwriting them, and reports the CORS conflict if it is present. Nothing you paste is uploaded, so an authenticated response from a staging environment is safe to check.

The values above, with the alternatives and their tradeoffs on one page, are on the HTTP security headers cheat sheet. The status codes you will see while testing are on the status codes reference.

HTTP Security Headers Cheat Sheet

Printable reference for the response headers that harden browsers against clickjacking, XSS, MIME confusion, and insecure transport.

Open cheat sheet

HTTP Status Codes & Headers Reference

A quick reference guide for HTTP response codes, REST API conventions, and essential HTTP request/response headers.

Open cheat sheet