HTTP Strict Transport Security (HSTS) is one of the most impactful security headers you can add to your website. It is a simple, one-line change that eliminates an entire class of man-in-the-middle attacks. If your site supports HTTPS (it should), you need HSTS.

The Problem HSTS Solves

When a user types yoursite.com into their browser address bar, the browser's first request is typically plain HTTP (http://yoursite.com). Your server responds with a 301 redirect to https://yoursite.com. This redirect pattern — "HTTP Strict Redirect" — is how most sites enforce HTTPS.

The problem: that first HTTP request is vulnerable. On a public Wi-Fi network, an attacker performing a man-in-the-middle attack can intercept that initial HTTP request before the redirect occurs, serve a fake HTTP version of your site, and capture login credentials. This attack is called an SSL stripping attack, and it has been reliably exploitable since Moxie Marlinspike's 2009 Black Hat presentation.

How HSTS Works

HSTS tells the browser: "For this domain, always use HTTPS — never attempt plain HTTP." Once the browser has seen the HSTS header, it will not even attempt an HTTP connection for the domain. It upgrades HTTP requests to HTTPS internally, before any network request is made.

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

After receiving this header, the browser remembers the policy for max-age seconds (31536000 = 1 year). Every subsequent visit — for the next year — will automatically use HTTPS.

The Three Directives

max-age

How long the browser should remember and enforce the HTTPS-only policy, in seconds. Recommended minimums:

includeSubDomains

Extends the policy to all subdomains. If you set HSTS on yoursite.com with includeSubDomains, then api.yoursite.com, mail.yoursite.com, and all other subdomains are also covered. Only add this if all your subdomains support HTTPS.

preload

Indicates that you want your domain to be included in the HSTS preload list — a list of domains that is hardcoded into browsers (Chrome, Firefox, Safari, Edge). Users who have never visited your site before get HSTS protection on the very first request. The preload directive alone does not add you to the list — you must also submit your domain at hstspreload.org.

How to Add HSTS

Nginx:

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

Apache:

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

Flask:

@app.after_request
def add_hsts(response):
    if request.is_secure:
        response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
    return response

Cloudflare: Enable HSTS in SSL/TLS → Edge Certificates → HTTP Strict Transport Security. No code changes needed.

Before You Enable HSTS

HSTS is intentionally hard to reverse. If you enable it with a 1-year max-age and then need to serve HTTP (for example, if your SSL certificate expires and you cannot renew it in time), users who have visited your site will be unable to access it for up to a year. Follow these steps before enabling:

  1. Ensure all subdomains support HTTPS (if using includeSubDomains)
  2. Ensure your SSL certificate has plenty of time before expiry
  3. Start with a short max-age (300 seconds) to test
  4. Gradually increase to 1 year over several weeks
  5. Submit to the preload list only after you are confident in your HTTPS setup

HSTS and the HSTS Preload List

The preload list is maintained by Google and baked into Chrome's source code (and adopted by other browsers from the same list). Inclusion provides the strongest possible protection: zero HTTP requests, ever, from any browser. But it is a one-way door — removal from the preload list requires weeks of lead time and browsers update on their own schedule. Domains that get removed from the preload list can experience a gap in coverage during the transition period.

Submit your domain at hstspreload.org — the tool will verify your configuration meets requirements (max-age ≥ 31536000, includeSubDomains, preload) before accepting the submission.

Verifying HSTS Is Working

curl -sI https://yoursite.com | grep -i strict
# Should show: strict-transport-security: max-age=31536000; includeSubDomains; preload

In Chrome DevTools → Application → Storage → View site data — you can see whether HSTS is remembered for the current domain under "HSTS".