HSTS Checker Guide: Read a Strict Transport Security Header Correctly

The first time a browser visits a site over plain HTTP, an attacker on the same network can interfere before any encryption starts. That first-visit gap is what Strict Transport Security, or HSTS, closes. Once a browser has seen a valid HSTS header over a secure connection, it remembers the site and refuses to connect to it over plain HTTP for a set period, automatically upgrading every attempt to HTTPS. The HSTS Checker reads header text you paste and checks its structure: whether max-age is present and sensible, whether the includeSubDomains directive is there, and whether the preload directive is there. It works on pasted text, which is an important scope note: it validates the header you show it, it does not fetch your live site or prove that your server actually sends the header to visitors.

The header itself is short, and every part of it matters. It looks like this in general form: Strict-Transport-Security, followed by a max-age value in seconds, optionally followed by includeSubDomains, and optionally by preload. Max-age is the memory: how long the browser enforces HTTPS-only for the site. A max-age of zero switches HSTS off, which is used when removing the protection deliberately. IncludeSubDomains extends the rule to every subdomain, which is powerful and dangerous in equal measure: if any subdomain cannot serve HTTPS, it becomes unreachable to browsers that have seen the header. Preload goes further still, asking for the site to be baked into browsers' preload lists so that even the very first visit is protected. Preload is the strongest option and the hardest to undo, since removal from browser lists takes time and a deliberate process, so it should only be used when every subdomain is permanently ready for HTTPS.

How to read a header

Read the header left to right and ask four questions. Is max-age present at all? A header without max-age is invalid and browsers ignore it. Is max-age large enough to be useful? A value of a few minutes protects almost nothing, since the protection expires before most visitors return. Common practice for a settled site is one year, which is 31,536,000 seconds, since 365 days times 24 hours times 60 minutes times 60 seconds equals 31,536,000. Is includeSubDomains present, and is that safe for your subdomains? And is preload present, and if so, has the site actually been submitted to a preload list, since the directive alone does nothing until a browser ships the list entry? Also check the spelling and punctuation carefully: a misspelled directive is silently ignored by browsers, not flagged to visitors, so a typo in includeSubDomains looks identical to a deliberate omission from the outside.

Worked example

Take three sample headers, with values clearly labelled as illustrations. Header one: max-age of 300. That is 5 minutes, since 300 divided by 60 is 5, and it protects a visitor only until their next visit a week later, by which time the memory has expired; it is suitable for testing, not for production. Header two: max-age of 31,536,000 with includeSubDomains. That is one year, and it covers subdomains, so it is a strong production setting provided every subdomain serves HTTPS. Header three: max-age of 63,072,000 with includeSubDomains and preload. That is two years, since 63,072,000 divided by 31,536,000 is 2, and it is the common preload submission requirement of at least one year, exceeded. Now compare the risk: header one leaves 364 days and 23 hours and 55 minutes of the year unprotected after expiry, header two protects the main site and subdomains for a year, and header three adds first-visit protection once listed, but commits the operator to HTTPS on every subdomain for the foreseeable future. The arithmetic is simple; the judgement is in matching the setting to how ready the site really is.

Mistakes to avoid

The first mistake is enabling includeSubDomains before checking every subdomain, including forgotten staging or legacy subdomains that still serve plain HTTP; those become unreachable, and the fix requires waiting out the max-age or serving HTTPS there. The second is enabling preload casually: it is a long-term commitment, and removal is slow. The third is setting a long max-age during testing, then discovering a problem and being unable to turn the protection off quickly for returning visitors, since their browsers remember the old value until it expires. Test with a short max-age, such as 300 seconds, and raise it only when the site is stable. The fourth is pasting header text from documentation or another site into the checker and assuming the result describes your own server; check the header your server actually sends, copied from its real response. The fifth is believing HSTS fixes everything: it protects browsers that have seen the header, but it does not protect the first visit unless preloaded, and it does not replace a valid certificate or secure server configuration.

Putting it into practice

Roll HSTS out in stages. Start with a short max-age on the main site, confirm HTTPS works everywhere, then raise the max-age to a year, then consider subdomains, then consider preload, with a check at each stage. Keep a record of the exact header your server sends, and re-check it after server changes, migrations, or certificate renewals, which can quietly drop a header. Do not paste live secrets or internal hostnames into a checker along with the header; the header alone is enough. For related checks, the SSL Certificate Checker covers the certificate side, the CSP Checker covers content policy, and the HTTP Headers Checker reads a full pasted header set. The companion guide on CSP Checker explains how HSTS fits among the other headers that protect a site.

Key points

  • HSTS tells browsers to use HTTPS only for a site, for a set time, after the first secure visit
  • Max-age is in seconds, so a year is about 31,536,000 seconds, not a round number to guess
  • IncludeSubDomains and preload extend protection, but preload is hard to reverse
  • A checker reads pasted header text, it does not fetch a live site or prove the header is served

In short: HSTS is a browser memory that forces HTTPS, and its strength is set by max-age and its scope by two directives. Test short, raise gradually, check every subdomain before extending scope, and reserve preload for a site that is permanently ready for HTTPS everywhere.