HSTS Header (Strict-Transport-Security) Explained

The HSTS header tells browsers to always use HTTPS when connecting to your website. Once cached, the browser will refuse to connect over HTTP for the duration of max-age — even if the user types http:// explicitly.


The HSTS header — formally Strict-Transport-Security — is an HTTP response header that instructs browsers to refuse all future connections over HTTP and use HTTPS exclusively. It is one of the most important security headers for any site that has deployed TLS, protecting visitors from downgrade attacks, cookie hijacking, and accidental insecure connections.

What Is the HSTS Header?

HSTS stands for HTTP Strict Transport Security. When a browser receives the Strict-Transport-Security header in an HTTPS response, it caches a rule: for the specified duration, always connect to this domain over HTTPS, regardless of what the user types or what links they follow.

If the user types http://example.com or follows an HTTP link while the HSTS policy is cached, the browser converts the request to HTTPS internally — the HTTP request is never sent. This prevents network attackers from intercepting the initial unencrypted request and injecting malicious content.

HSTS is only sent over HTTPSThe Strict-Transport-Security header is ignored when served over HTTP. Browsers only process it when received on a secure HTTPS connection, which is the correct behaviour — sending it over HTTP would be meaningless since the connection is already insecure.

HSTS Header Syntax

The header has three directives, each controlling a different aspect of the policy:

bash
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
DirectiveRequiredDescription
max-age=<seconds>YesHow long the browser caches the HSTS rule, in seconds. 31536000 = 1 year.
includeSubDomainsNoApplies the HSTS policy to all subdomains of the domain. Requires all subdomains to support HTTPS.
preloadNoSignals readiness for submission to the browser preload list. Does not activate preloading alone — submission to hstspreload.org is required.

What max-age Controls

The max-age value is a countdown in seconds. Each time the browser receives the HSTS header on a successful HTTPS response, the timer resets. If the browser visits the site daily, the effective protection is continuous. If the user doesn't visit for longer than max-age, the policy expires and the next visit may use HTTP again.

Common values:

  • 300 — 5 minutes. Useful during testing before committing to a long policy.
  • 86400 — 1 day. Suitable for initial rollout while monitoring for issues.
  • 2592000 — 30 days. A reasonable intermediate value.
  • 31536000 — 1 year. The recommended value for production sites. Required for preload submission.

How to Enable HSTS

Before enabling HSTS, ensure all of the following are in place:

  1. A valid TLS certificate is installed and covering the domain (and subdomains if using includeSubDomains).
  2. All HTTP traffic redirects to HTTPS with a 301 permanent redirect.
  3. The site is fully functional over HTTPS — no mixed content warnings.

Nginx

nginx
server { listen 443 ssl http2; server_name example.com www.example.com; # Add HSTS header to all HTTPS responses add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; }

Apache

apache
<VirtualHost *:443> ServerName example.com # Requires mod_headers Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" </VirtualHost>

Caddy

text
example.com { # Caddy enables HSTS automatically when serving HTTPS # To customise, use the header directive: header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" }

Why HSTS Matters for Security

Without HSTS, even a site that always redirects HTTP to HTTPS is vulnerable to a class of attacks called SSL stripping. An attacker positioned between the user and the server (on public Wi-Fi, for example) can intercept the initial HTTP request before it is redirected and serve a fake HTTP version of the page — capturing credentials and sensitive data in plaintext.

HSTS prevents SSL stripping by making the browser refuse to send the initial HTTP request at all. The redirect never happens over the network — it happens entirely within the browser.

HSTS and SEOHTTPS is a confirmed Google ranking signal. Using HSTS ensures every visit stays on the secure canonical URL, preventing duplicate content issues from HTTP/HTTPS variants and signalling stable HTTPS implementation to search engines.

includeSubDomains: When to Use It

Adding includeSubDomains extends the HSTS policy to every subdomain of your domain — www, mail, api, and any others. This is important for full protection, but it also means any subdomain that does not have a valid HTTPS certificate will become inaccessible via HTTPS (and blocked by HSTS).

Only enable includeSubDomains after confirming that every subdomain you use supports HTTPS with a valid certificate.

Common HSTS Mistakes to Avoid

  • Setting a long max-age before testing. Start with 300 seconds, verify everything works, then increase incrementally to one year.
  • Enabling includeSubDomains prematurely. An HTTP-only subdomain will break immediately. Audit all subdomains first.
  • Sending HSTS on HTTP responses. The header must only appear on HTTPS responses; on HTTP it is meaningless and ignored.
  • Forgetting the always flag in Nginx. Without always, the header is only sent on 200 responses, not on redirects or error pages.
  • Submitting to the preload list prematurely. Removal is a slow process that can take a year to fully propagate across all browser versions.

Verifying Your HSTS Configuration

After enabling HSTS, confirm the header is correctly served:

bash
# Check HSTS header on your domain curl -I https://example.com | grep -i strict-transport-security # Expected output: # strict-transport-security: max-age=31536000; includeSubDomains; preload

You can also use these tools to validate your setup:

Frequently Asked Questions

What happens if my TLS certificate expires while HSTS is active?

Users will see a browser error and will not be able to access your site — HSTS means the browser will not fall back to HTTP. Renew your certificate before it expires. Set up automated renewal (e.g. with Let's Encrypt and Certbot) to prevent this scenario.

Can a user manually clear the HSTS policy?

Yes. In Chrome and Edge, visit chrome://net-internals/#hsts and delete the domain. In Firefox, you can clear site preferences for the domain. However, if the domain is on the preload list, clearing the cached policy has no effect — the browser still enforces HTTPS from its built-in list.

Does HSTS work on all browsers?

HSTS is supported by all major modern browsers: Chrome, Firefox, Safari, Edge, and Opera. Internet Explorer 11 does not support HSTS fully. For users on unsupported browsers, the HTTPS redirect still works — it just doesn't cache a proactive HSTS rule.

Is max-age=31536000 mandatory for preload submission?

Yes. The HSTS Preload list at hstspreload.org requires a max-age of at least 31536000 (one year), along with includeSubDomains and the preload directive, before a domain can be submitted.

Should I set HSTS on the HTTP virtual host to redirect users?

No. The HSTS header must be served only on HTTPS responses. The HTTP virtual host should issue a 301 redirect to the HTTPS version — it should not attempt to set the Strict-Transport-Security header, as browsers ignore it over HTTP.

Related Articles