Strict-Transport-Security
Send `Strict-Transport-Security: max-age=31536000; includeSubDomains` over HTTPS to make browsers refuse plaintext connections to your domain for a year.
Send this header. There is no meaningful downside for a typical site.
What it does
HSTS closes the gap between a user typing `example.com` and the redirect that upgrades them to HTTPS. That first request goes out in plaintext, and anyone positioned on the network can answer it before your server does — the attack is old enough to have a tool named after it (sslstrip). Once a browser has seen a valid HSTS header from your site over a trusted HTTPS connection, it stops sending that first plaintext request at all: it rewrites `http://` to `https://` internally, before anything touches the network.
The header only counts when it arrives over HTTPS. A browser ignores `Strict-Transport-Security` on a plaintext response, deliberately — otherwise an attacker who could inject a header could also pin a victim to a hostname they control. This is why the header does nothing for a first-time visitor who has never reached you securely, and why the preload list exists.
The commitment is real and it is one-directional. The `max-age` you send is not a suggestion a browser will reconsider if your certificate later breaks; it is a period during which that browser will refuse to load your site over HTTP and will not offer a click-through past a certificate error. Shortening `max-age` later only affects browsers that come back and see the new value. This is the header to stage carefully.
What to send
Strict-Transport-Security: max-age=31536000; includeSubDomainsA year is the shortest `max-age` the preload list accepts, and long enough that the window for a downgrade attack is negligible. `includeSubDomains` matters more than it looks: without it, a single unprotected subdomain can set a cookie the parent domain will read, so the protection on the apex is partly theoretical. Add `preload` only once you are sure every subdomain — including internal, staging and vendor-hosted ones — serves valid HTTPS, because removal from the preload list takes months.
Directives and values
How long the browser should enforce HTTPS, refreshed on every visit. Required. `31536000` is one year; `0` tells the browser to forget the policy for this host, which is the correct way to back out.
Applies the policy to every subdomain, including ones that do not exist yet. Also the part that breaks internal hosts on the same domain if any of them are HTTP-only.
A signal that you consent to the domain being hardcoded into browsers via hstspreload.org. Not part of the HSTS specification — it is a submission token Google reads. Ships in Chrome, Firefox, Safari and Edge, so it applies before a user has ever visited.
Common mistakes
- Preloading before every subdomain is ready. Preload plus `includeSubDomains` means every host under your domain must serve valid HTTPS — including the legacy intranet box, the vendor status page and anything with a self-signed certificate. Once the domain ships in a browser release, removal requires a request to hstspreload.org and then waiting for the next several browser releases to propagate. Plan for months, not days.
- Sending the header on the HTTP response. Browsers ignore HSTS on plaintext responses, so a config that sets it in a shared server block before the redirect is silently doing nothing. Verify against the HTTPS response specifically.
- Testing with a short max-age and forgetting to raise it. Staging with `max-age=300` is the right move. Shipping it is not: a five-minute policy means anyone whose browser last saw your site more than five minutes ago is unprotected again, which is nearly everyone.
- Assuming HSTS replaces the redirect. It does not help a browser that has never seen your site. Keep the 301 from HTTP to HTTPS in place permanently — HSTS protects the second visit onward, the redirect protects the first.
Browser support
Universal in current browsers, and has been since roughly 2012. The preload list is maintained by the Chromium project but consumed by Firefox, Safari and Edge as well. Note that HSTS state is per-host and is cleared by clearing site data, which makes local testing confusing — use a fresh profile rather than trusting a hard refresh.
Frequently asked questions
What is a good max-age for HSTS?
One year — `max-age=31536000`. That is the minimum the preload list accepts and it is long enough that a returning visitor is always covered. Use a short value such as `max-age=300` only while testing, and raise it once you have confirmed every host under the domain serves valid HTTPS.
Does HSTS protect the very first visit to a site?
No. A browser only enforces HSTS after it has received the header over a trusted HTTPS connection, so the first plaintext request is still exposed. The HSTS preload list exists to close that gap: domains on it are hardcoded into browser releases and are enforced before the first visit.
How do I remove HSTS from a domain?
Send `Strict-Transport-Security: max-age=0` over HTTPS and keep serving valid HTTPS until every browser has revisited and picked up the new value. If the domain is on the preload list you must additionally submit a removal request at hstspreload.org and wait for browser releases to ship the change, which typically takes several months.
Should I use includeSubDomains?
Yes for most sites, but audit first. It applies to every host under the domain, including ones that do not exist yet, so any subdomain that cannot serve valid HTTPS will become unreachable. Without it, an HTTP-only subdomain can still set cookies your main site reads, which undermines much of the protection.
Does HSTS break my staging or internal subdomains?
It can. With `includeSubDomains`, a host such as `internal.example.com` serving HTTP or a self-signed certificate will be refused by the browser with no click-through option. Either give those hosts valid certificates, or move them to a domain that is not covered by the policy.
The free Security Headers Checker reads Strict-Transport-Security from a live response and grades it alongside every other header on this reference — no account needed.
For the longer treatment, read HTTP Security Headers: HSTS, CSP, X-Frame-Options & More in the Learning Center.
Related headers
The most powerful and most misconfigured security header. Most deployed policies provide no XSS protection at all.
One value, one line, no downside worth mentioning. Stops browsers second-guessing your Content-Type.
Controls how much of your URL is sent to other sites. The default leaks more than most teams expect.