Skip to main content

What is HSTS?

HSTS prevents browsers from ever opening an unencrypted HTTP connection to your site again — the most important defense against SSL-stripping attacks.

In short

HSTS stands for HTTP Strict Transport Security and is a response header that your web server sends to the browser. With it you tell the browser: "From now on and for the next X seconds, load this domain exclusively over HTTPS — no matter whether the user clicks an http:// link or types the address without a protocol." The browser remembers this instruction and connects directly via HTTPS on the next visit.

What problem does HSTS solve?

Without HSTS, the typical first visit looks like this: the user types example.com into the browser, the browser sends an HTTP request, and the server replies with an HTTPS redirect. That very first unencrypted request is the weak spot: an attacker on the same Wi-Fi can intercept the redirect, impersonate your site, and only establish the HTTPS connection between themselves and your server — meanwhile the user keeps talking unencrypted to the attacker (SSL stripping). With HSTS, the browser ignores the HTTP attempt and goes straight to HTTPS.

Header structure

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age=31536000 — how long (in seconds) the browser remembers the HSTS instruction. 31536000 = 1 year, which is the common value. Anything below 6 months is considered too short.
  • includeSubDomains — the instruction also applies to all subdomains (e.g. api.example.com, blog.example.com). Important: every subdomain must then actually speak HTTPS.
  • preload — you request inclusion in the browsers' HSTS preload list. This forces HTTPS on the very first visit, before the browser has ever seen the header.

HSTS Preload

The preload list is hard-coded into Chrome, Firefox, Safari, and Edge. Anyone listed there will never be requested via HTTP again — not even on the very first visit. Requirements: a valid certificate, all subdomains on HTTPS, a max-age of at least 31536000 (1 year), and both includeSubDomains and preload set.

Risks

HSTS is almost impossible to roll back. If you deploy max-age=31536000; includeSubDomains and then notice that one subdomain doesn't have HTTPS at all — that subdomain will be unreachable for a year, until each individual visitor's cache expires.

Recommendation: roll out in stages.

  1. Start with max-age=300 (5 minutes) without includeSubDomains.
  2. After a week, raise it to max-age=86400 (1 day).
  3. Move all subdomains to HTTPS, then add includeSubDomains.
  4. Finally, set max-age=31536000 and optionally preload.

Configuration examples

nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Cloudflare: in the dashboard under SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS).

Check it yourself: HTTP-Header

HSTS, CSP, X-Frame-Options & Co. Enter a domain and see in seconds how your HSTS is doing.

Also in the glossary