HSTS checker

Check whether the Strict-Transport-Security header is configured for forced HTTPS connections

Free
No sign-up
Instant results

Check results

This check only covers HSTS. For a full picture of your page, run a page audit.

For issues across your whole site — duplicate titles, orphan pages, broken internal links — run a site audit.

Want us to fix what we found? Our team can help.

What is HSTS and why it matters

HSTS (HTTP Strict Transport Security, RFC 6797) is a response header that tells the browser "for this host, never use plain HTTP — always HTTPS, even if the user types http:// explicitly, even if a link points at HTTP." After the first HTTPS response with a Strict-Transport-Security header, the browser remembers the policy for the duration of max-age and rewrites every subsequent HTTP request to HTTPS internally, before any network traffic. This closes the SSL-strip attack window that exists with a regular HTTP→HTTPS redirect, where the first unencrypted request can be intercepted and rewritten by an attacker on the network path.

What this tool checks

  • Applicability — if the site runs on HTTP, HSTS is not meaningful (RFC 6797 §7.2 requires browsers to ignore HSTS over HTTP); the SSL checker handles the missing-HTTPS case separately
  • Header presence — whether the HTTPS response includes Strict-Transport-Security
  • Directive parsing — case-insensitive parse of max-age, includeSubDomains, and preload (per RFC 6797 §6.1)
  • max-age validity — flags very small values (under 1 day) as likely stale warm-up values left over from rollout
  • Preload compatibility — if preload is set, verifies that max-age ≥ 31536000 (1 year) and that includeSubDomains is also set, as both are required by hstspreload.org

How the three directives interact

  • max-age — how long (in seconds) the browser should remember the HSTS policy. Recommended production value: 31536000 (1 year). Longer is safer; shorter values should only appear during warm-up
  • includeSubDomains — applies the HSTS policy to every subdomain (api.example.com, mail.example.com, staging.example.com). Required for preload submission. Enable only after verifying every subdomain serves HTTPS
  • preload — the magic token that makes your domain eligible for the HSTS Preload List, a hardcoded table built into Chrome, Firefox, Safari, and Edge. Domains in the preload list are HSTS-protected from the very first visit, even if the user has never been to the site before. Submit at hstspreload.org

Good vs bad examples

Good — production-ready HSTS with preload:

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

Good — HTTPS-enforcing HSTS without preload (apex only, no subdomain commitment):

Strict-Transport-Security: max-age=31536000

Good — warm-up value during initial HSTS rollout (1 week):

Strict-Transport-Security: max-age=604800; includeSubDomains

Bad — very small max-age left over after warm-up was supposed to ramp up:

Strict-Transport-Security: max-age=300

Bad — preload requested but max-age too low to qualify:

Strict-Transport-Security: max-age=86400; includeSubDomains; preload
→ hstspreload.org will reject (requires ≥ 31536000)

Bad — preload requested without includeSubDomains:

Strict-Transport-Security: max-age=31536000; preload
→ hstspreload.org will reject (requires includeSubDomains)

Common mistakes

  • Enabling preload without meaning to — copy-pasting max-age=31536000; includeSubDomains; preload from a tutorial, then discovering a subdomain that only works over HTTP. Preload is effectively one-way — see the FAQ below
  • Forgetting subdomainsincludeSubDomains covers every subdomain, including the ones you forgot (mail, legacy admin panels, third-party integrations on custom subdomains). Enable only after a full subdomain audit
  • Stale warm-up max-age — deploying max-age=300 "just to test," then never ramping up. 5 minutes of HSTS protection is effectively no protection; the attack window is almost always open
  • HSTS on HTTP only — browsers ignore HSTS when received over HTTP (RFC 6797 §7.2); the header must come from an HTTPS response
  • Missing always in Nginxadd_header Strict-Transport-Security without always only sends the header on 2xx/3xx responses, not on error pages. Users hitting a 500 still see plain HTTP. Always use add_header Strict-Transport-Security "..." always;
  • Confusing HSTS with HTTP→HTTPS redirect — the redirect protects returning users on subsequent visits; HSTS protects returning users from the very first connection of each visit (no unencrypted request ever leaves the browser)

Frequently asked questions

Follow a staged warm-up: start with 300 (5 minutes) for the first deploy, confirm every page and every subdomain serves over HTTPS, increase to 86400 (1 day), then 604800 (1 week), and finally 31536000 (1 year). The 1-year value is the standard production setting and the minimum for HSTS Preload List submission. The reason to warm up instead of jumping straight to 1 year: if you discover a subdomain or an asset that only works over HTTP after enabling HSTS with a large max-age, every user who received the header is locked into HTTPS for the full max-age duration — they can't access the broken resource until they manually clear their HSTS state (which most users don't know how to do).
Practically speaking, yes — it's a one-way trap. Removal is technically possible (submit a request at hstspreload.org/removal/) but takes months: Chrome, Firefox, Safari, and Edge each need to ship an updated browser release with your domain removed from their hardcoded preload tables, and users need to install that update. During that period, every user with a preload-list-containing browser is locked into HTTPS for your domain. Only enable preload when you're 100% certain you'll serve HTTPS on the apex and every subdomain indefinitely. If there's any uncertainty — a legacy system you might inherit, a subdomain managed by another team, a planned rebranding — don't enable preload yet.
Yes — send Strict-Transport-Security: max-age=0 over HTTPS. Browsers interpret max-age=0 as "forget this domain's HSTS policy immediately." Users who visit the HTTPS version of the site after you deploy max-age=0 will clear their stored HSTS state and can once again access the HTTP version. The catch: users who don't visit the HTTPS version again before your old max-age expires on their end will stay locked into HTTPS. If you removed HTTPS entirely, they'd have no way to receive the max-age=0 header. And if your domain was on the preload list — see the previous answer — max-age=0 does nothing, since the preload entry is browser-hardcoded.
A 301 redirect from HTTP to HTTPS is a server-side instruction: the browser first sends an unencrypted HTTP request, receives the redirect response, then follows it to HTTPS. That first unencrypted hop is the SSL-strip attack window — an attacker on the network path can intercept the HTTP request and respond with modified content instead of forwarding the redirect. HSTS closes this window: once the browser has seen the HSTS header even once (or if the domain is in the preload list), it rewrites every http:// request to https:// internally, before any packet leaves the browser. You should use both: 301 redirect for first-time visitors who haven't received the HSTS header yet, plus HSTS to protect returning visitors.