Strict-Transport-Security
response headersecurity
Tells browsers to use only HTTPS for the site for a set period, blocking downgrade attacks.
Once a browser has seen HSTS over HTTPS, it rewrites every http:// request for that domain to https:// before sending it, for max-age seconds. That closes the window in which an attacker on the network could intercept the first plain-HTTP request. Chrome DevTools shows these local rewrites as '307 Internal Redirect'.
Syntax
Strict-Transport-Security: max-age=<seconds>[; includeSubDomains][; preload]
Defined in RFC 6797 — HTTP Strict Transport Security.
Values
| max-age=<seconds> | how long the browser remembers to use HTTPS only |
|---|---|
| includeSubDomains | apply to every subdomain too |
| preload | consent to inclusion in browsers' built-in HSTS list |
Examples
Strict-Transport-Security: max-age=31536000; includeSubDomains
one year, all subdomains — a common production value
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
two years, all subdomains, eligible for preloading
Strict-Transport-Security: max-age=300
five minutes — start small while testing
Good to know
- Browsers ignore HSTS received over plain HTTP; it must arrive over HTTPS.
includeSubDomainscovers every subdomain, including internal ones that may not have certificates yet.- Preloading (hstspreload.org) is slow to undo: removal takes months to reach users.
- Ramp
max-ageup gradually — minutes, then a week, then a year or two.
Further reading: Security headers checklist · Security headers generator
How to set Strict-Transport-Security
res.set("Strict-Transport-Security", "max-age=31536000; includeSubDomains");module.exports = {
async headers() {
return [
{
source: "/(.*)",
headers: [{ key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains" }],
},
];
},
};add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Check it
Fetch only the response headers and filter for Strict-Transport-Security. In the browser, it's under Response Headers in DevTools → Network.
curl -sI https://example.com/ | grep -i '^strict-transport-security:'
To compare response headers across many URLs at once, use the HTTP Status Checker.
Frequently asked questions
What does '307 Internal Redirect' mean in Chrome?
HSTS at work: Chrome rewrote http:// to https:// locally because the site sent Strict-Transport-Security earlier or is preloaded. No request reached the server.
How do I turn HSTS off?
Send Strict-Transport-Security: max-age=0 over HTTPS; browsers that see it forget the policy. Preloaded domains must also be removed from the preload list.