HSTS header not eligible for preload
What is this issue?
This is advice, not a defect. The page sends an HSTS policy, but the header does not meet the requirements of the browser HSTS preload list.
HSTS normally only protects a visitor after their first visit, because that is when the browser first sees the header. The preload list closes that gap: Chrome, Firefox, Safari and Edge ship with a built-in list of domains that are HTTPS-only from the very first request.
To be accepted, the header must have all three of:
max-ageof at least31536000(one year)includeSubDomainspreload
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadWhy it is a suggestion. Preloading is a long-term commitment. Removal from the list takes months to reach users' browsers, and every subdomain must stay on HTTPS. It is the right end state for many sites, but it is a decision, not a fix.
A header that says preload but would be refused is called out
specifically: the site believes it asked for preloading, and the list will
reject the submission.
The header is only half of it. hstspreload.org also requires that the bare domain serves the header and redirects HTTP to HTTPS on the same host. This check looks at the header on each page; check the domain itself at hstspreload.org before submitting.
When this check stays silent
- Plain HTTP pages. Browsers ignore HSTS sent over HTTP (RFC 6797 §8.1), and the page is already reported as not served over HTTPS.
- No usable policy. A missing header, a header with no
max-age, andmax-age=0are all reported by "No Strict-Transport-Security header" (#41). This check only looks at policies that browsers would actually apply, so the two never describe the same header.
Why it matters
It protects the very first visit. Without preloading, a first-time visitor's initial
http://request can be intercepted before the HSTS header is ever seen. Preloaded domains are never requested over HTTP at all.It removes the redirect hop. Browsers go straight to HTTPS for preloaded domains, saving a round trip on visits typed or linked as
http://.It is a strong trust signal. Major banks, government services and technology companies preload their domains, and security reviews look for it.
Effect on the health score
None. This is a suggestion and never deducts.
How to fix it
Make sure every subdomain serves HTTPS. Preloading covers all of them, permanently from the browser's point of view.
Send the full header from the bare domain (and, ideally, everywhere):
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;Redirect HTTP to HTTPS on the same host before redirecting anywhere else (
http://example.com→https://example.com→https://www.example.com).Check and submit at hstspreload.org. It reports any remaining problem with the domain.
When to leave it alone
If you are not ready to commit every subdomain to HTTPS for the long term, do
not add preload. Removing a domain from the list takes months to reach
browsers.
Examples
Example 1: Preload-ready
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadPasses.
Example 2: Everything except the token
Strict-Transport-Security: max-age=31536000; includeSubDomainsSuggested: missing preload.
Example 3: Asks for preload but would be refused
Strict-Transport-Security: max-age=86400; preloadSuggested, with the "would reject it" message: missing a one-year
max-age and includeSubDomains.
Example 4: Any order, any case
Strict-Transport-Security: PRELOAD; IncludeSubDomains; Max-Age="63072000"Passes: order does not matter, names ignore case and values may be quoted.
How PixyScan detects this
Only HTTPS pages with a usable HSTS policy are checked. If the site sends no HSTS at all, that is "No Strict-Transport-Security header" instead.
Checks the three header requirements of hstspreload.org:
max-ageof at least 31,536,000,includeSubDomains, andpreload.Raises one suggestion per page listing every unmet requirement, in
missingRequirements.Uses a different message when
preloadis present but the other requirements are not, because that header will be rejected on submission.Does not check the domain-level requirements (apex domain, HTTP redirect) — those are properties of the domain, not of a page's header.
How the header is read
PixyScan reads the header the way RFC 6797 tells a browser to:
- Only the first header field counts. If the server sends the header twice, browsers use the first one and ignore the rest, and so does this check.
- Directive names ignore case.
includeSubDomains,INCLUDESUBDOMAINSandincludesubdomainsare the same directive. - Values may be quoted.
max-age="31536000"is valid. - A repeated directive makes the header invalid. Browsers ignore a header
like
max-age=600; max-age=700entirely, so this check says nothing about it rather than giving advice about a policy no browser applies.
What we store
Storage Level
Page Level
Database Table / Prisma Model
PageSecurityHeader, and the finding on audit_issues.details
Fields Used
| Field | Type | Description |
|---|---|---|
| page_security_headers.hsts_header | String | The Strict-Transport-Security header exactly as the page sent it |
Stored Fields on the finding
| Field | Type | Description |
|---|---|---|
| message | String | What is missing from the policy and why it matters |
| hstsHeader | String | The header as sent |
| missingRequirements | String[] | The unmet requirements: max-age of at least 31536000, includeSubDomains, preload |
| declaresPreload | Boolean | Whether the header already carries preload |
Detection Dependencies
- HTTP Response headers
- HTTPS (the check only applies to pages served over HTTPS)