HTTPS and security headers without the slowdown
Which security headers to set, what each does, how they touch speed and caching, and how to roll them out in a safe order: HTTPS, HSTS, nosniff and CSP.
In this guide
HTTPS first
The 2025 Web Almanac security chapter found that 98.8% of requests on mobile were sent over HTTPS, and that 97.3% of mobile home pages were served over it, up from 95.6%. Browsers helped: Chrome, Firefox and Safari try HTTPS first, then fall back to HTTP and often show a warning.
Lighthouse 13.5 puts it in its Best Practices category. The Uses HTTPS audit has a weight of 5 and Redirects HTTP traffic to HTTPS has a weight of 1. Lighthouse's own text says all sites should be protected with HTTPS, even ones that do not handle sensitive data, and that HTTPS is a prerequisite for HTTP/2 and many new web platform APIs. The speed side, a TLS 1.3 handshake, one clean redirect and HSTS, is in TLS and HTTPS speed.
Mixed content
A page loaded over HTTPS that still pulls a file over HTTP has mixed content. MDN says browsers upgrade requests for images, video and audio from HTTP to HTTPS, and block insecure requests for all other types, such as scripts and stylesheets. The result on your site can be a missing script or style, with no obvious error on the page. Use https addresses for everything, and look for http:// in your templates and database.
The headers that matter
| Header | What it tells the browser | A common starting value |
|---|---|---|
Strict-Transport-Security | Use only HTTPS for this host from now on | max-age=31536000; includeSubDomains once you are sure |
X-Content-Type-Options | Trust the content type the server sent | nosniff |
Referrer-Policy | How much of the page address to send to other sites | strict-origin-when-cross-origin |
Content-Security-Policy with frame-ancestors, or X-Frame-Options | Who may put your page in a frame | frame-ancestors 'self', or X-Frame-Options: SAMEORIGIN |
Permissions-Policy | Which browser features the page and its frames may use | camera=(), microphone=(), geolocation=() if you use none |
Content-Security-Policy | Which sources may load scripts, styles and more | Start in report-only mode |
HSTS. MDN explains that the browser remembers the host and upgrades future http requests to https, and that it will not let the visitor click through certificate errors. Browsers ignore the header over plain HTTP. The preload directive is non-standard and needs a max-age of at least one year and includeSubDomains. Lighthouse recommends a rollout in stages, starting with a low max-age, because a mistake is remembered by visitors for the full time.
nosniff. MDN says it has two effects. For scripts and stylesheets, the browser blocks a response whose content type does not match. For other files, it uses the type you sent rather than guessing from the content.
Referrer-Policy. MDN lists strict-origin-when-cross-origin as the default. Setting it in the header makes your choice explicit.
Framing. MDN says X-Frame-Options avoids clickjacking by stopping your content being embedded in other sites, and points to the CSP frame-ancestors directive as the more complete option. The old ALLOW-FROM value is obsolete and ignored by modern browsers. If a form of yours is meant to be embedded on a partner's site, do not block it.
Permissions-Policy. MDN marks the header experimental. It lets a page allow or deny features such as the camera, microphone or location, for itself and for its iframes.
Content-Security-Policy. MDN describes a CSP as instructions that limit what the page's code is allowed to do, mainly as a defense against cross-site scripting. It can also restrict embedding and upgrade insecure requests. MDN recommends a strict policy built on nonces or hashes, not a list of allowed domains.
How common they are
Adoption is uneven. In the Almanac, Strict-Transport-Security was on 36% of mobile pages, up 6 points in a year. The X-Content-Type-Options header led the group at nearly 50% of mobile sites. A CSP was on 21.9% of pages. Permissions-Policy was on 3.7%. The Almanac says the strongest risers over the year were HSTS, CSP and nosniff. Lighthouse reports the CSP, HSTS, clickjacking, Cross-Origin-Opener-Policy and Trusted Types checks, but gives each a weight of zero, so they do not change the score.
Where security meets speed
The headers are small. I measured a set of five, with a simple CSP, at 333 bytes in HTTP/1.1. HTTP/2 compresses headers, so repeats cost less. See HTTP/2 and HTTP/3.
Nonces and caching. MDN says a nonce must be different for every HTTP response and unpredictable, and that this means the server cannot serve static HTML, because it must insert a new nonce each time. A cache that stores finished HTML would hand everyone the same nonce, which defeats it. MDN says hashes can be static, so they suit static pages. For a cached WordPress page, ask whether your CSP uses hashes, or whether the server or the edge inserts a fresh nonce on each response.
Content types. With nosniff, a stylesheet or script sent as the wrong type is blocked. Check the Content-Type of your files, as the video and SVG guides also advise.
Third parties. A policy that lists allowed domains grows quickly: MDN quotes a report that integrating one analytics service meant adding 187 domains. With a strict policy, a script that loads other scripts fails unless the strict-dynamic keyword extends trust to them. See third-party scripts.
Reports. A policy can send violation reports to an endpoint you name. That is a few extra requests, and it is how you find out what a policy would break.
Roll them out in order
- Fix mixed content and make sure every
httpaddress redirects once tohttps. - Add the quiet headers:
X-Content-Type-Options,Referrer-Policyand a framing rule. - Add HSTS with a short
max-age, then raise it as you gain confidence. AddincludeSubDomainsonly when every subdomain works over HTTPS. - Add `Permissions-Policy` if you use none of the features it names.
- Add a CSP in report-only mode. MDN advises testing with
Content-Security-Policy-Report-Onlyfirst, collecting reports, and fixing what would break, such as inline event handlers andeval(). Then switch to enforcing. - Test after each step: forms, checkout, embeds, the chat widget and the admin. See how to test speed changes safely.
Set the headers in your server or CDN, the same way as cache headers. The HTTP caching headers guide shows Apache and Nginx syntax and the add_header inheritance trap.
How to check
- Look at the response headers in the Network panel, or run
curl -sI https://example.com/and read the lines. - Run Lighthouse and open the Best Practices section.
- Check a cached page and an uncached one. A header added in one layer can be missing in another.
- Check the console for blocked resources after each change.
Mistakes to avoid
- A long `max-age` for HSTS on day one.
- `includeSubDomains` with a subdomain that has no HTTPS.
- A CSP enforced before it was tested.
- A nonce-based CSP behind a page cache that stores one copy of the HTML.
- Wrong content types with
nosniffon. - Blocking framing on a page that is meant to be embedded.
- Setting a header in one place and having another layer remove it.
- `http://` addresses left in templates.
Check your own page
Run the free audit and read the Best Practices findings. Then run curl -sI against your home page and a deep page, and list which of the six headers are present.
Sources
- Security chapter, Web Almanac 2025: HTTPS, HSTS, CSP, Permissions Policy and header adoption.
- MDN: Strict-Transport-Security, X-Content-Type-Options, Referrer-Policy, X-Frame-Options, Permissions-Policy, Content Security Policy, the CSP implementation guide and mixed content.
- Ensure CSP is effective against XSS attacks in the Lighthouse documentation, and the Lighthouse 13.5 default configuration and audit texts: which checks exist and their weights.
Start here
Free website audit
Live Google data for any public page: mobile and desktop.
Mobile + desktop · Lighthouse lab test · Real-user Chrome data when Google has it
Rather have this done for you? Technical SEO · Book a call