Your site probably redirects to HTTPS already, and the padlock shows up just fine. But every time a returning visitor types your address without https://, their browser still sends one unencrypted HTTP request before your redirect kicks in. On hostile networks — airport Wi-Fi, hotel hotspots, a compromised router — that single request is the opening an attacker needs. HTTP Strict Transport Security (HSTS) closes it for good: one response header that tells browsers to never speak plain HTTP to your domain again.
The gap is real: according to W3Techs (July 2026), 90.1% of all websites now default to HTTPS, but only 34.1% send an HSTS header. Nine sites in ten encrypt; barely one in three actually enforces it.
What is HSTS?
HSTS (HTTP Strict Transport Security) is a web security policy mechanism standardized in RFC 6797 back in 2012. It consists of a single HTTP response header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
When a browser receives this header over a valid HTTPS connection, it remembers — for max-age seconds — that your host is HTTPS-only. From that moment:
- Every
http://link, bookmark, or typed address for your domain is rewritten tohttps://inside the browser (an internal 307 redirect), before a single packet leaves the device. - Certificate warnings on your site become non-bypassable: no "Proceed anyway" link. If the certificate is broken — or someone is intercepting the connection — the browser refuses, full stop.
All major browsers — Chrome, Edge, Firefox, Safari — have supported HSTS for roughly a decade, on desktop and mobile.
Why an HTTPS redirect alone isn't enough
A classic 301 redirect from HTTP to HTTPS happens server-side — the browser must first send the plain-HTTP request, and an attacker sitting between your visitor and your server sees it before your redirect ever answers. That is exactly how SSL stripping works, a downgrade attack demonstrated by Moxie Marlinspike back in 2009: the attacker silently keeps the victim on HTTP while talking HTTPS to the real server, reading everything in transit.
| Protection | 301 redirect only | HSTS | HSTS + preload |
|---|---|---|---|
| Later visits upgraded before any network request | ❌ | ✅ | ✅ |
| The very first visit protected | ❌ | ❌ | ✅ |
| Certificate errors non-bypassable | ❌ | ✅ | ✅ |
| Defeats SSL stripping (downgrade attacks) | ❌ | ✅ after first visit | ✅ always |
What each level of HTTPS enforcement actually protects.
Keep the redirect — you still need it for first-time visitors and for preload eligibility — but understand what it cannot do alone.
How HSTS works, step by step
-
First visit. The browser loads
https://example.com, the response carries theStrict-Transport-Securityheader, and the policy is cached. -
Every visit after that. Any attempt to reach
http://example.comis upgraded internally to HTTPS. A packet capture on the network would show no plaintext request at all. -
The timer slides. Each new HTTPS response containing the header resets
max-age, so regular visitors stay protected indefinitely. - Hard failure on bad certificates. Expired, self-signed, or man-in-the-middle certificates produce an error page that cannot be clicked through.
The three directives
| Directive | Required? | What it does | Recommended value |
|---|---|---|---|
max-age |
Yes | How long (in seconds) the browser enforces HTTPS-only |
31536000 (1 year); 63072000 (2 years) is also common |
includeSubDomains |
For preload | Extends the policy to every subdomain | Only after confirming all subdomains serve HTTPS |
preload |
For preload | Opts in to browsers' built-in preload list | After running at a 1-year max-age without issues |
How to enable HSTS on your server
Add the header only in the HTTPS configuration — browsers ignore HSTS sent over plain HTTP, as required by the spec.
nginx (inside the server block that listens on 443):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Apache (with mod_headers enabled, in the HTTPS vhost):
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
IIS (web.config):
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
</customHeaders>
</httpProtocol>
Cloudflare: SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS) → Enable, then set max-age and subdomain options in the dashboard.
Then confirm the header is actually served: open your site, check the Network tab in your browser's DevTools, and look for strict-transport-security among the response headers — or simply run the free FortifyNet scan, which flags a missing or weak HSTS policy.
Roll it out gradually
A mistaken HSTS policy locks visitors out of any broken HTTP-only resource for the full remaining max-age — you cannot take it back remotely except by serving max-age=0 over valid HTTPS to each affected browser. Ramp up instead:
| Stage | Header value | Hold for |
|---|---|---|
| 1 — Test | max-age=300 |
A day or two |
| 2 — Short | max-age=86400 |
A week |
| 3 — Medium | max-age=2592000 |
A month |
| 4 — Full | max-age=31536000; includeSubDomains |
3+ months |
| 5 — Preload | max-age=31536000; includeSubDomains; preload |
Permanent |
HSTS preload: closing the first-visit gap
Plain HSTS is trust on first use: the very first request from a brand-new visitor is still unprotected until the first header arrives. The preload list fixes that — your domain ships inside the browser itself as HTTPS-only, so even visit number one never touches plain HTTP.
Submission is free at hstspreload.org (the Chromium-maintained list, also consumed by Edge, Firefox, and Safari). The requirements:
- A valid TLS certificate.
- HTTP redirects to HTTPS on the same host (port 80 → 443).
- The HSTS header served on the HTTPS response of the base domain with
max-ageof at least 31536000 (1 year), plus bothincludeSubDomainsandpreload. - Every subdomain — including
www— reachable over HTTPS.
Treat preload as a one-way door. Removal from the list takes months to propagate through browser releases. Do not preload until every subdomain — including internal ones like intranet. or mail. — has working HTTPS.
Adoption in 2026: HTTPS everywhere, enforcement lagging
HTTPS is near-universal, yet only about a third of sites enforce it with HSTS (source: W3Techs, July 2026).
Browsers are pushing hard in the same direction. In Chrome 147 (April 2026), Google enabled "Always Use Secure Connections" for the 1 billion+ users with Enhanced Safe Browsing, and with Chrome 154 (October 2026) it becomes the default for everyone: Chrome will attempt HTTPS first and warn before loading public HTTP sites.
Does that make HSTS obsolete? No. Chrome's warning is bypassable by the user; HSTS is your server's own non-bypassable guarantee. It works in every browser regardless of settings, covers all your subdomains, and blocks certificate click-through. The two complement each other.
Common HSTS mistakes
-
Enabling
includeSubDomainsblind — one forgotten HTTP-only subdomain (intranet, staging, a printer portal) becomes unreachable for the wholemax-age. - Sending the header over HTTP — harmless but useless; browsers ignore it.
-
A
max-ageof a few minutes in production — near-zero protection, and it fails preload requirements. - Forgetting HSTS after a server or CDN migration — the policy silently expires and nobody notices.
Frequently asked questions
Does HSTS replace my HTTP→HTTPS redirect?
No. Keep the redirect: first-time visitors need it, and the preload list requires it.
Can I undo HSTS?
Serve Strict-Transport-Security: max-age=0 over HTTPS and browsers drop the policy on their next visit. Preload removal is much slower — months — which is why you ramp up carefully.
Does HSTS affect SEO?
Only positively: it guarantees users and crawlers land on one canonical HTTPS version of your site. There is no downside for rankings.
How do I know if my site sends HSTS?
Check the response headers in your browser's DevTools (Network tab) for strict-transport-security — or run a free FortifyNet scan, which checks HSTS along with the rest of your security headers.
Is HSTS all I need?
It is one of several headers a hardened site sends. Pair it with Content-Security-Policy, X-Content-Type-Options and friends — see our complete security headers guide.
Check your HSTS in 60 seconds
The free FortifyNet scan tests your SSL/TLS setup, HSTS and all other security headers, DNS and email authentication, and dark-web exposure — in about a minute, no signup required. If HSTS is missing or misconfigured, you will see exactly what to fix.
Related guides
- HTTP Security Headers: The Complete Guide for 2026
- HTTP Security Headers with nginx & Apache examples
- SSL Certificates: A+ Rating in SSL Labs — Complete Guide
- "Your Connection Is Not Private": What It Means and How to Fix It
Originally published on the FortifyNet blog. FortifyNet is a free 60-second website security audit — I'm the founder, happy to answer questions in the comments.
Top comments (0)