Skip to content

HSTS and the HSTS preload list

In-depth guide. Updated .

How Strict-Transport-Security works, how to raise max-age safely, what includeSubDomains can break, and the requirements and risks of preloading.

Why HTTPS alone is not enough

Most visitors reach a site by typing a name or following an old link that starts with http://. The server then redirects to HTTPS, but that first plain request can be intercepted on a hostile network. An attacker in the middle can keep the victim on HTTP and proxy the real site, a technique known as SSL stripping.

HTTP Strict Transport Security (RFC 6797) closes that gap for returning visitors. After a browser has seen the Strict-Transport-Security header over a valid HTTPS connection, it rewrites every future request for that host to HTTPS internally, before anything goes on the network. It also refuses to let the user click through certificate errors for that host.

First visit versus later visits with HSTSOn the first HTTPS visit the browser stores the HSTS policy; later requests to http:// are upgraded inside the browser, and certificate errors become fatal until max-age expires.First visit: https://example.comResponse includes Strict-Transport-Security:max-age=31536000Browser stores the policyHost example.com must use HTTPS for one yearLater: user types http://example.comBrowser upgrades to https:// before sendinganythingCertificate problem?Connection fails with no option to proceedPreloaded domainsThe policy ships with the browser, so even thefirst visit is protected
On the first HTTPS visit the browser stores the HSTS policy; later requests to http:// are upgraded inside the browser, and certificate errors become fatal until max-age expires.

The header

HSTS header
Strict-Transport-Security: max-age=31536000; includeSubDomains
HSTS directives
DirectiveMeaning
max-age=<seconds>How long the browser remembers the policy, renewed on every response that carries the header. 0 removes the policy.
includeSubDomainsApplies the policy to every subdomain of the host as well.
preloadNot part of RFC 6797; signals consent to inclusion in browser preload lists.

Browsers ignore the header when it arrives over plain HTTP, because an attacker could inject it there. Send it on HTTPS responses only, and on every response, including redirects and error pages, so the policy is refreshed whatever page a visitor hits.

nginx
server {
    listen 443 ssl;
    server_name example.com;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://example.com$request_uri;
}
Apache httpd
<VirtualHost *:443>
    ServerName example.com
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>

The always keyword matters

In nginx, add_header without always is skipped on error responses such as 404 or 500, and a header set in a location block replaces headers set at the server level. Check real responses, not just the configuration.

Rolling out HSTS safely

The risk with HSTS is not the header itself but its memory. If you set a year-long policy and later need plain HTTP on that host, or a certificate lapses, browsers that saw the header will refuse to connect until the policy expires. A staged rollout finds those problems while max-age is still short.

A staged max-age plan
StageHeaderWait before next stage
1. Testmax-age=300A day; check the site and key flows
2. Shortmax-age=86400A week; watch errors and support tickets
3. Subdomainsmax-age=86400; includeSubDomainsA week, after checking every subdomain
4. Monthmax-age=2592000; includeSubDomainsA month
5. Yearmax-age=31536000; includeSubDomainsLong term; consider preload

Before step 3, list every subdomain that exists in DNS and check that each one works over HTTPS with a valid certificate. The DNS Lookup and your DNS zone export are the starting point; do not forget printers, old intranet names and staging hosts that only people inside the company use.

Communicate each stage to the teams that run subdomains. A short note with the date and the planned max-age gives them a chance to raise an HTTP-only service before it breaks.

Check the header on your real responses with the HTTP Headers Checker. It reports the max-age in days and whether includeSubDomains and preload are present.

What includeSubDomains can break

includeSubDomains set on example.com applies to every name under it, including ones served by other teams or vendors. Any subdomain that must still be reached over plain HTTP becomes unreachable for browsers that have the policy. Typical victims are internal tools, network devices with self-signed certificates and legacy marketing microsites.

  • Internal hosts such as intranet.example.com served over HTTP inside the office network.
  • Devices with self-signed certificates, because HSTS removes the click-through option.
  • Vendor-hosted subdomains (help centres, status pages) where you do not control the certificate.
  • Captive portals or HTTP-only APIs on subdomains used by old clients.

The header is only honoured for the host that sent it and its subdomains. A policy with includeSubDomains sent by www.example.com covers *.www.example.com, not api.example.com. To cover the whole domain, the header must be sent by example.com itself, which means users need to visit the bare domain at least once, or the domain must be preloaded.

The preload list

HSTS protects a browser only after its first successful HTTPS visit. The preload list removes that first-visit gap: it is a list of domains compiled into Chromium and also used by Firefox, Safari and Edge, which treat those domains as HSTS from the start. Domains are submitted through hstspreload.org, which checks the requirements automatically.

Preload requirements (as published at hstspreload.org)
RequirementWhat it means in practice
Valid certificateThe bare domain serves HTTPS with a trusted certificate
Redirect HTTP to HTTPSIf port 80 is open, http://example.com redirects to HTTPS on the same host first
All subdomains on HTTPSIncluding www if it exists in DNS
HSTS header on the bare domainmax-age of at least 31536000, plus includeSubDomains and preload
Header on redirects tooAn HTTPS redirect from the bare domain must still send the header
Header eligible for preloading
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Removal is slow

Removing a domain from the preload list happens through the same site, but it only reaches users when browsers ship new versions and users update. Plan for months. Preload only when every current and future subdomain will be HTTPS-only.

Some top-level domains are preloaded as a whole, so every domain registered under them requires HTTPS in browsers from the first visit. If you use such a TLD, HSTS behaviour is already in place regardless of your header, and plain HTTP subdomains will not work.

Redirects that work with HSTS

A clean redirect chain matters for both HSTS and preloading. The recommended sequence is: http://example.comhttps://example.com (setting HSTS for the bare domain) → https://www.example.com if you use www. Redirecting straight from http://example.com to https://www.example.com skips the bare domain's HTTPS response, so it never sends its policy.

A preload-friendly redirect chain
http://example.com/        301 → https://example.com/
https://example.com/       301 → https://www.example.com/   (with Strict-Transport-Security)
http://www.example.com/    301 → https://www.example.com/
https://www.example.com/   200                               (with Strict-Transport-Security)

The Redirect Checker follows the chain from http:// and lists every hop, which makes it easy to confirm the first hop stays on the same host. The redirect guide covers loops and unnecessary hops.

Common mistakes

HSTS mistakes and their effect
MistakeEffectFix
Header only on the home pageVisitors who land elsewhere never get the policySend it on every HTTPS response
Header missing on 301 or error responsesRedirect-only hosts never set the policyUse always in nginx or Header always set in Apache
Year-long max-age on day oneMistakes stay cached in browsers for a yearRaise max-age in stages
includeSubDomains on www onlyBare domain and other subdomains are not coveredSend the header from the bare domain
preload added without submittingNo effect, but signals consent to preloadingRemove it unless you intend to preload
Two different headers from app and proxyBrowsers use the first valid oneSet the header in one layer only

The last row is common behind CDNs and reverse proxies: the application sends one value and the edge adds another. Decide which layer owns security headers and remove the other, then confirm the final response from outside with the HTTP Headers Checker.

Several newer features also push browsers toward HTTPS, and it helps to know how they relate. None of them replaces HSTS for a site you control, but they change what visitors experience on sites without it.

Mechanisms that upgrade connections to HTTPS
MechanismSet byScope
HSTS header (RFC 6797)Your serverYour host, optionally subdomains, remembered for max-age
HSTS preload listBrowser vendors, on your requestYour domain and all subdomains, before the first visit
HTTPS DNS records (RFC 9460)Your DNSBrowsers that support them can connect over HTTPS directly
HTTPS-first or HTTPS-only browser modesThe user or browserAll sites, with a warning when HTTPS fails
upgrade-insecure-requests (CSP)Your serverSubresources inside your pages, not navigation to your site

HSTS remains the mechanism you control that makes certificate errors non-bypassable and protects returning visitors on every browser that implements it. The others are useful additions, and upgrade-insecure-requests in particular pairs well with HSTS during clean-up of old content.

Living with HSTS

HSTS turns certificate problems into outages. Automate renewal, monitor expiry separately, and test renewals on staging hosts. A lapsed certificate on a site without HSTS shows a warning; on a site with HSTS, visitors simply cannot get in.

  • Monitor certificate expiry for every host covered by the policy, including subdomains.
  • Add new subdomains only with HTTPS from day one.
  • Keep the header on every HTTPS response, including CDN edge responses.
  • Document that the domain is HSTS or preloaded, so future teams do not plan HTTP-only services on it.
  • Pair HSTS with the other security headers; the CSP guide covers the most complex one.

Large organisations often have many domains, and HSTS decisions differ per domain. A product domain with a single web application is an easy candidate for a long max-age and preloading; a corporate domain with dozens of internal subdomains may only be ready for HSTS on specific hosts without includeSubDomains. Record the decision and its reasons per domain, so the next team knows what is safe.

When you acquire or inherit a domain, check whether it is already preloaded or sends HSTS before planning services on it. The HTTP Headers Checker shows the current header, and the preload site shows the list status. Discovering a preloaded domain after building an HTTP-only service on one of its subdomains is an avoidable surprise.

If you ever have to back out, send max-age=0 over HTTPS. Browsers that receive it forget the policy for that host. Visitors who do not return before their stored max-age expires keep the old policy until then, which is another reason to raise max-age gradually.

FAQ

What max-age should I use?

Start with minutes or a day, then raise it in steps. For a stable HTTPS-only site, one year (31536000) or two years (63072000) is common, and at least one year is required for preloading.

Does HSTS work on the first visit?

Not unless the domain is on the preload list. Otherwise the browser learns the policy from the first successful HTTPS response.

Can I set HSTS in a meta tag?

No. RFC 6797 requires the header; browsers ignore HSTS in HTML meta elements.

Should I send HSTS on HTTP responses?

It has no effect there, because browsers ignore it over plain HTTP. Redirect HTTP to HTTPS and send the header on HTTPS responses.

How do I remove HSTS?

Send max-age=0 over HTTPS and, if preloaded, request removal at hstspreload.org. Returning visitors drop the policy when they see the new header; preload removal waits for browser updates.

Why can I not click through a certificate warning on my own site?

Your browser has the HSTS policy for that host, so certificate errors are treated as fatal. Fix the certificate; for local development, use a different host name that is not covered by the policy.

Does HSTS affect APIs and mobile apps?

Only clients that implement HSTS, which mainly means browsers. API clients and apps should use HTTPS URLs directly and validate certificates; HSTS adds nothing for them.

Can includeSubDomains break email?

No. HSTS applies to HTTP requests in browsers. Mail servers, SMTP and IMAP connections are not affected, even for subdomains covered by the policy.

Should staging sites send HSTS?

Use a short max-age on staging, and keep staging on a host name that is not covered by production's includeSubDomains if it ever needs plain HTTP or test certificates.

Does HSTS replace redirects from HTTP to HTTPS?

No. First-time visitors and clients that ignore HSTS still need the redirect. HSTS protects the requests after that.

Sources