surface

Learn · RFC 6797

HSTS

Tells the browser to never connect to your site over plain HTTP again.

Most sites redirect HTTP to HTTPS, and that redirect happens over HTTPS itself — which sounds safe, but the very first request, before that redirect has ever happened once, is often still plain HTTP. A browser that's never visited your site before, or a user who typed the domain without https:// or clicked an old http:// link, sends that first request unencrypted by default. That first request is exactly what an attacker positioned on the network — a hostile Wi-Fi network, a compromised router, anywhere on the path between the user and your server — can intercept and either read directly or use to redirect the user somewhere else entirely, a technique generally called SSL stripping. HSTS closes this specific gap: it's a response header that tells the browser to remember, for a set duration, that it should never connect to this domain over plain HTTP again — skip the insecure request and the redirect entirely, and go straight to HTTPS on every future visit for as long as the policy is remembered.

The header

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age — how long, in seconds, the browser should remember this policy after the last time it saw the header. 31536000 (one year) is the realistic minimum for the policy to be meaningful; 63072000 (two years) is required to qualify for the preload list.
  • includeSubDomains — extends the same rule to every subdomain of this one, not just the exact host that sent the header. Without it, an attacker can still target an HTTP-only subdomain even if the main domain is fully protected.
  • preload — a signal that you intend to submit the domain to the browser-vendor-maintained HSTS preload list (see below). The header flag alone does nothing by itself; actual preloading requires a separate submission step.

The preload list, and why it's a one-way door

HSTS as described above still has one gap: it only protects a browser that has visited the site at least once before and remembers the header from that visit. The very first connection, ever, from a given browser is still unprotected — there's nothing yet stored to say "always use HTTPS here." The preload list closes this by having the policy shipped directly inside the browser itself, hard-coded into Chrome, Firefox, Safari and Edge, so protection applies from the literal first connection with no prior visit required.

Getting on the list means submitting the domain at hstspreload.org, which requires max-age of at least a year, includeSubDomains, and the preload directive, all already live and correctly served. Once accepted, the domain ships baked into browser source code and update cycles — which means removing it later is slow and painful: it requires being removed from the source of multiple browsers and then waiting for that change to reach users through their normal update cycle, which can take months, during which every subdomain you have must keep serving valid HTTPS or those subdomains break outright for anyone on an already-updated browser. Submit only once every subdomain — including ones you might have forgotten about — is confirmed to actually serve HTTPS correctly.

This whole mechanism is what's known as trust-on-first-use: the browser only knows to enforce HTTPS because it was told to on some earlier visit, which means the very first connection to a domain it's never seen before is structurally unprotected no matter how the header is configured for every visit after that. The preload list is the only way to close that specific gap, by moving the "first use" from the user's first visit to the browser's own build process.

HSTS and cookies are not the same protection

It's easy to conflate HSTS with the Secure flag on a cookie, since both are about forcing HTTPS, but they protect different things and neither substitutes for the other. The Secure flag stops a specific cookie from ever being sent over a plain HTTP connection, which matters because a session cookie sent in the clear even once is enough to hijack that session — but it says nothing about the rest of the page load, and a site can set Secure on every cookie while still being fully vulnerable to SSL stripping on the page itself. HSTS protects the connection as a whole, for every request to the domain, cookies included. A site aiming for real protection needs both: HSTS for the connection, Secure (plus HttpOnly and SameSite) for every cookie riding on it.

Common failure modes

  • No HSTS header at all — every visit remains vulnerable to SSL stripping on the first connection and every connection after any period the browser's memory of a previous visit has expired.
  • max-age set too short — some deployments use a short value for testing and never raise it, which limits how long protection actually persists between visits and disqualifies the domain from preloading.
  • includeSubDomains added before every subdomain is verified to serve HTTPS — this is the header's sharpest edge: subdomains that only ever served plain HTTP become entirely unreachable the moment a browser has cached this policy, with no graceful fallback.
  • Preload submitted without every subdomain actually being ready — same failure, but locked in for the months-long removal timeline rather than just until the next deploy.

Set a long max-age immediately — there's no reason not to. Add includeSubDomains once, and only once, every subdomain is confirmed on HTTPS. Treat preload submission as the last step, not the first, since it's the one decision here that's genuinely difficult to walk back.

Is your domain actually covered?

Surface checks HSTS — and everything else on this page — against your real DNS and headers, free, in seconds.

Scan your domain →