Security Headers Explained: HSTS, CSP, X-Frame-Options and More
HTTP security headers tell browsers how to protect visitors. Learn what HSTS, CSP, X-Content-Type-Options and Referrer-Policy do, and how to add them safely.
HTTP security headers are instructions your server sends along with each page, telling the visitor's browser to apply extra protections. They cost nothing, require no change to your visible design, and block whole categories of attack, such as clickjacking, content sniffing and some forms of script injection. They are also easy to get wrong, so it helps to know what each one does before you copy a snippet from a blog. Our security page gives the wider picture.
The most useful headers
| Header | What it does |
|---|---|
| Strict-Transport-Security (HSTS) | Tells browsers to use HTTPS only for your site for a set time |
| Content-Security-Policy (CSP) | Whitelists where scripts, styles, images and frames may load from |
| X-Content-Type-Options | Stops browsers guessing file types (MIME sniffing) |
| X-Frame-Options / CSP frame-ancestors | Controls whether other sites can embed yours in a frame |
| Referrer-Policy | Controls how much of the page address is sent to other sites |
| Permissions-Policy | Turns off browser features you do not use, such as camera or geolocation |
HSTS
Even if your site redirects http to https, the very first request can be made over unencrypted HTTP, which an attacker on the network can tamper with. HSTS tells the browser: for the next N seconds, always connect to this site over HTTPS, and refuse to continue if the certificate is invalid.
Strict-Transport-Security: max-age=31536000; includeSubDomains
Before turning it on, make sure HTTPS works on every page and every subdomain you include. Start with a short max-age, such as a day or a week, and increase it once you are confident. The preload option adds your domain to lists built into browsers and is very hard to undo, so only use it deliberately. See our article on SSL certificates for the HTTPS foundation HSTS builds on.
X-Content-Type-Options
Add X-Content-Type-Options: nosniff. It stops browsers treating a file as a different type from the one the server declared, which closes a path where an uploaded file could be run as a script. It is almost never a problem.
Clickjacking protection
Clickjacking tricks visitors into clicking something on your site hidden inside another page. Prevent your pages being framed with X-Frame-Options: SAMEORIGIN or, in modern form, the CSP directive frame-ancestors 'self'. If you legitimately allow embedding by a partner, list them explicitly instead.
Referrer-Policy and Permissions-Policy
Referrer-Policy: strict-origin-when-cross-origin is a sensible default: it sends full addresses within your own site but only the domain to other sites, and nothing over a downgrade to HTTP. Permissions-Policy lets you disable features you never use, so injected code cannot ask for them. For example, Permissions-Policy: camera=(), microphone=(), geolocation=() turns those off.
Content-Security-Policy
CSP is the most powerful header and the hardest to deploy. A policy lists trusted sources for each type of resource:
Content-Security-Policy: default-src 'self'; img-src 'self' data:; script-src 'self'
If a script injection attack inserts a script from an unlisted source, the browser refuses to run it. The difficulty is that real sites use many scripts, inline styles and third-party services, and a policy that is too strict breaks features. A safe path:
- Start with
Content-Security-Policy-Report-Only. The browser logs violations without blocking anything. - Review the reports and add the legitimate sources you find.
- Move away from inline scripts if you can, or use nonces or hashes for the ones you need.
- Switch to enforcing mode once reports go quiet, and keep monitoring.
Avoid 'unsafe-inline' and 'unsafe-eval' in script sources when you can, since they weaken the protection a lot. On WordPress, with many plugins injecting inline code, a strict CSP is a larger project. A moderate policy is still better than none.
How to add headers
- Apache: use
Header setdirectives in.htaccessor the virtual host. - nginx: use
add_headerin the server block. - Plesk: additional Apache or nginx directives can be set per domain in the panel.
- CDN or plugin: many CDNs and WordPress security plugins can add common headers without editing server files.
Test the result
- Open DevTools, Network tab, click the main document and read the Response Headers.
- Use a free online security header checker for a graded summary.
- Click through the site, forms and checkout, watching the browser console for CSP or mixed-content errors.
A starter set you can deploy
For a typical brochure site on HTTPS, a conservative set of headers looks like this:
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
These five rarely break anything on a standard site and give an immediate improvement. Leave CSP for a second phase, after you have run it in report-only mode and understand which scripts and services your pages depend on. If your site uses embedded maps, video or payment forms from other domains, those need to be allowed in the CSP, and the Permissions-Policy lines above need adjusting if you actually use one of those features.
Common mistakes with headers
- Enabling HSTS before every subdomain supports HTTPS, locking visitors out of an internal tool.
- Setting a very long HSTS lifetime and the preload flag as a first step.
- Copying a strict CSP from another site and breaking checkout, forms or analytics.
- Setting headers in several places, for example the server, a plugin and the CDN, so values conflict or duplicate.
- Forgetting that error pages and static files need the headers too.
Headers are one layer
Headers protect against browser-side attacks, but they do not replace updates, strong authentication or backups. They work best alongside HTTPS everywhere. Every Zebra Hosting Cloud plan includes free SSL certificates; learn more on the SSL page.