HTTP Strict Transport Security (HSTS) is a security mechanism that forces browsers to communicate with your site exclusively over HTTPS. Once a browser receives a valid HSTS header, it will automatically convert every http:// request to https:// for the duration specified — no redirect required, no window of vulnerability.
HSTS is a cornerstone of modern HTTPS deployment and one of the key headers covered in our complete guide to HTTP security headers. This article explains exactly how HSTS works, how to configure it properly, and how to get onto the browser preload list for maximum protection.
Without HSTS, a typical HTTPS deployment relies on a 301 redirect from HTTP to HTTPS. The problem is that the very first request is still sent over plain HTTP. An attacker performing a man-in-the-middle attack (for example, on public Wi-Fi) can intercept that initial request and use a tool like sslstrip to downgrade the connection, keeping the user on HTTP while proxying to the real HTTPS site. The user sees no certificate warning because they were never on HTTPS to begin with.
HSTS eliminates this attack vector. When the browser receives the Strict-Transport-Security header over a valid HTTPS connection, it records the policy internally. For all subsequent visits within the max-age window, the browser upgrades the connection to HTTPS before sending any request at all. This is a client-side enforcement that happens before the network layer is involved.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadThe max-age directive specifies how long (in seconds) the browser should remember the HSTS policy. Recommended values:
max-age=300 (5 minutes) — use this while verifying your setup.max-age=86400 (1 day) — monitor for issues over 24 hours.max-age=63072000 (2 years) — this is required for preload submission and reflects confidence that HTTPS will remain fully operational.This directive extends the HSTS policy to all subdomains. It is critically important because without it, an attacker could set up an HTTP connection to http://sub.example.com, set a cookie scoped to .example.com, and potentially hijack sessions on the main domain. Enabling includeSubDomains prevents this, but you must first verify that every subdomain supports HTTPS — otherwise they will become unreachable.
The preload directive is not part of the HSTS RFC but is recognized by browser vendors. It signals your intent to be included in the HSTS preload list — a list hardcoded into browsers (Chrome, Firefox, Safari, Edge) that forces HTTPS even on the very first visit, before any header has been received.
server {
listen 443 ssl http2;
server_name example.com;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Redirect HTTP to HTTPS
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}The always parameter ensures the header is sent even on error responses (e.g., 404, 500).
<VirtualHost *:443>
ServerName example.com
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# ... SSL config ...
</VirtualHost>
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>To be accepted into the preload list at hstspreload.org, your site must meet all of these requirements:
max-age of at least 31536000 (1 year), and include both includeSubDomains and preload directives.Warning: Preload list removal takes months. Only submit after you are fully confident that HTTPS works on every subdomain.
includeSubDomains.After deploying, verify your configuration:
curl -sI https://example.com | grep -i strict to see the raw header.chrome://net-internals/#hsts to query and manage the browser's local HSTS cache.HSTS is one part of a layered security strategy. Combine it with the other headers described in our security headers guide, including a strong Content Security Policy and proper cookie security attributes.