Critical Headers 6 min read

HTTP Strict Transport Security (HSTS) Guide

HSTS is a one-line header that permanently forces HTTPS for your domain. It eliminates an entire class of attacks that target the first unprotected connection a user makes to your site. Once deployed correctly, browsers will refuse to connect over plain HTTP — even if the user types it.

What HSTS Does

When a browser receives an HSTS header, it records that your domain must always be accessed over HTTPS. For the duration specified by max-age, any attempt to load the site over plain HTTP is automatically upgraded to HTTPS by the browser itself — the request never reaches the network as HTTP.

Without HSTS, the first connection a user makes might be over HTTP — perhaps because they typed example.com without the https prefix, or followed an old bookmark. That first HTTP request is vulnerable to a man-in-the-middle attack called SSL stripping.

SSL Stripping: The Attack HSTS Prevents

In an SSL stripping attack, an attacker positioned between the user and server (on a coffee shop Wi-Fi, for example) intercepts the first HTTP request and responds with a fake HTTP page instead of the expected HTTPS redirect. The user's browser shows the site over HTTP, the attacker can read all traffic, and the user may not notice because the site appears to work normally.

HSTS defeats this by ensuring the browser never sends that initial HTTP request in the first place. Once a user has visited your site and received the HSTS header, all subsequent visits go directly to HTTPS with no HTTP step that can be intercepted.

The HSTS Header

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

The three parameters each serve a distinct purpose:

max-age

The number of seconds the browser should remember to enforce HTTPS. Common values:

Start with a low max-age (300 or 3600) and ramp up over weeks. If you ever need to serve plain HTTP — for a subdomain that doesn't support HTTPS, or during a migration — you need the browser to forget HSTS quickly.

includeSubDomains

This flag extends the HSTS policy to all subdomains of your domain. If you set HSTS on example.com with includeSubDomains, then api.example.com, mail.example.com, and any other subdomain will also be forced to HTTPS.

Risk: If any subdomain doesn't support HTTPS and you set includeSubDomains, that subdomain will become completely unreachable to browsers that have cached your HSTS policy. Audit all your subdomains before adding this flag.

preload

The preload flag signals that you want your domain included in browser HSTS preload lists. These are hardcoded lists built into Chrome, Firefox, Safari, and Edge. Domains on the preload list are forced to HTTPS from the very first visit — even before the browser has received an HSTS header from your server.

Preloading solves the HSTS bootstrap problem: the first-visit attack window disappears entirely. To be eligible, your domain must serve a valid HSTS header with max-age of at least 31536000, includeSubDomains, and the preload flag. You then submit it at hstspreload.org.

Preloading is very hard to undo. Once on the preload list, removal takes months and browsers may take longer to update. Only preload if you are 100% certain every subdomain of your domain will always support HTTPS.

How to Add HSTS

Nginx

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

Apache

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

Cloudflare

Cloudflare supports HSTS natively. In your dashboard, go to SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS). The Cloudflare UI lets you set max-age and toggle includeSubDomains and preload safely.

Common Mistakes

Recommended Rollout Order

  1. Ensure all pages and assets load correctly over HTTPS with no mixed content.
  2. Deploy Strict-Transport-Security: max-age=300 and monitor for one week.
  3. Increase to max-age=2592000 and monitor for one month.
  4. Add includeSubDomains after auditing all subdomains.
  5. Increase to max-age=31536000.
  6. Submit to the preload list only if you're prepared for the commitment.

Is your HSTS configured correctly?

WebAudit checks your HSTS header, validates max-age, and flags missing includeSubDomains or unsafe configurations.

Check your site's security now →