Security Tools

How to set up HSTS headers correctly

Step by step guide to configuring Strict-Transport-Security headers. Learn about max-age, includeSubDomains, preload list enrollment, and safe incremental deployment.

SiteSecurityScore Team·10 min read·Updated Feb 17, 2026

What is HSTS and why every site needs it#

HTTP Strict Transport Security (HSTS) is a web security policy mechanism that tells browsers to only communicate with your server over encrypted HTTPS connections. Once a browser receives an HSTS header from your site, it will automatically convert any future HTTP requests to HTTPS before they ever leave the browser. This simple but powerful behavior eliminates an entire class of attacks that exploit the moment between an initial HTTP request and the HTTPS redirect.

Without HSTS, every first visit to your site (or every visit after the browser cache has been cleared) starts with an unencrypted HTTP request. Attackers on the same network, such as a public Wi-Fi hotspot, can intercept that first request and redirect the user to a malicious version of your site. This is known as a protocol downgrade attack or SSL stripping, and it is one of the most practical man-in-the-middle techniques still used in the wild. HSTS closes this window by instructing the browser to never make an unencrypted request in the first place.

Deploying HSTS is one of the highest-impact, lowest-effort security improvements you can make. It requires a single response header, has no performance cost, and protects every user who has visited your site at least once. Combined with the browser preload list, you can extend that protection to first-time visitors as well.

  • Prevents protocol downgrade attacks by forcing the browser to use HTTPS for all requests
  • Eliminates the insecure HTTP-to-HTTPS redirect, removing a man-in-the-middle opportunity
  • Improves perceived load time because the browser skips the redirect round-trip entirely
  • Signals trust and security maturity to users, search engines, and security auditors

Not sure whether your site already sends the HSTS header? Scan your site to check your current HSTS configuration and see where you stand.

Understanding max-age, includeSubDomains, and preload#

The HSTS header accepts three directives that control how aggressively the browser enforces HTTPS. Getting these right is the difference between solid protection and a false sense of security. Each directive serves a distinct purpose, and understanding them individually will help you make informed decisions when generating your header.

The max-age directive specifies how long, in seconds, the browser should remember that your site must only be accessed over HTTPS. A value of 31536000 equals one year, which is the minimum recommended for production sites and is required for preload list submission. During this period, even if the user manually types http:// in the address bar, the browser will silently upgrade to HTTPS.

The includeSubDomains directive extends the HSTS policy to every subdomain under your root domain. Without it, an attacker could potentially exploit an unprotected subdomain to set cookies that affect your main domain. The preload directive tells browser vendors that you consent to having your domain hardcoded into the browser's built-in HSTS list, providing protection even on the very first visit before any header has been received.

HSTS directives at a glance

  • max-age — Duration in seconds the browser enforces HTTPS. Use at least 31536000 (one year) for production.
  • includeSubDomains — Applies the HSTS policy to all subdomains. Required for preload list eligibility.
  • preload — Signals your consent to be included in browser preload lists for first-visit protection.

Here is what a fully configured HSTS header looks like with all three directives enabled:

HSTS Header
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

For a deeper look at HSTS behavior and how it interacts with your broader security posture, see our HSTS reference guide.

How to use the HSTS generator step by step#

Our generator is designed to produce a correctly formatted HSTS header in under a minute, even if you have never configured one before. The interface walks you through each directive so you understand what you are enabling and why. Here is the full walkthrough.

First, choose a max-age preset. The generator offers common durations: 5 minutes (for initial testing), 1 day, 1 week, 1 month, 6 months, 1 year, and 2 years. If you are deploying HSTS for the first time, start with a short value like 5 minutes so you can verify that nothing breaks. Once you are confident, increase to one year or two years for full protection.

Second, decide whether to toggle on includeSubDomains. If every subdomain under your root domain is served over HTTPS, enable it. If even one subdomain still relies on HTTP (for example, a legacy internal tool), leave it off until you have migrated that service.

Third, toggle the preload directive. This is only meaningful if you also have includeSubDomains enabled and a max-age of at least one year. Turning it on signals your intent to be added to the browser preload list, but you still need to submit your domain separately at hstspreload.org.

Finally, copy the generated header value. The generator outputs the complete header string ready to paste into your web server configuration, CDN settings, or application code. Try the HSTS generator to get started.

Here is an example of the output you will get after selecting a one-year max-age with both includeSubDomains and preload enabled:

Generated HSTS Header
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

The HSTS preload list and how to get on it#

The HSTS preload list is a collection of domains that are hardcoded into major browsers, including Chrome, Firefox, Safari, and Edge. When your domain is on this list, the browser enforces HTTPS from the very first connection, even before it has ever seen your HSTS header. This eliminates the trust-on-first-use vulnerability that standard HSTS alone cannot address.

The list is maintained as part of the Chromium project and is shared across all major browser vendors. Once your domain is accepted, it is distributed in the next browser update cycle. In practice, this means full coverage can take several weeks to months as users update their browsers, but once it propagates, every single visitor gets protection from their very first request.

To submit your domain, visit hstspreload.org and enter your domain name. The tool will check whether your HSTS header meets all the requirements before allowing submission.

To qualify for the preload list, your HSTS header must meet all of the following requirements:

  • The max-age value must be at least 31536000 seconds (one year)
  • The includeSubDomains directive must be present
  • The preload directive must be present
  • Your site must serve a valid HTTPS redirect from the root domain (not just from www)

The preload list is effectively permanent

Once your domain is on the HSTS preload list, removing it is extremely difficult and time-consuming. Removal requests can take months to propagate through browser release cycles, and during that time every subdomain must continue serving valid HTTPS. Do not submit your domain unless you are absolutely certain that every subdomain, including any you may create in the future, will always support HTTPS. Test thoroughly with a short max-age before committing to preload.

For more context on how HSTS fits into your overall TLS configuration, read our TLS security guide.

Common HSTS mistakes and how to avoid them#

HSTS is a straightforward header, but a few common configuration mistakes can undermine its effectiveness or cause outages. Here are the most frequent issues we see when scanning sites, along with practical fixes for each one.

  • Setting max-age too short

    A max-age of a few minutes or hours provides almost no real-world protection because the policy expires before the user returns. Attackers only need to catch users during the gap between expiry and the next visit. Once you have verified that HTTPS works correctly across your site, set max-age to at least 31536000 (one year). During initial testing you can use a short value, but promote to a full year as soon as you are confident.

  • Forgetting to include subdomains

    Leaving out includeSubDomains means attackers can still target your subdomains over plain HTTP. Even if you do not think you have active subdomains, omitting this directive leaves the door open for cookie-based attacks where a compromised subdomain sets cookies for the parent domain. Include it unless you have a specific, documented reason not to.

  • Enabling preload without testing first

    Submitting to the preload list before verifying that every subdomain supports HTTPS can lock you into a configuration that breaks parts of your infrastructure. Always deploy HSTS with a short max-age first, monitor for issues over several weeks, then gradually increase the duration before submitting for preload.

  • Only setting HSTS on the HTTPS response

    Some servers are configured to send the HSTS header only on HTTPS responses, which is technically correct (browsers must ignore HSTS on HTTP), but they forget to set up the HTTP-to-HTTPS redirect itself. Without the redirect, first-time visitors on HTTP will never receive the HSTS header at all. Make sure your server redirects all HTTP traffic to HTTPS with a 301 status code before it sends the HSTS header on the secure response.

  • Setting max-age to zero by accident

    A max-age of 0 tells the browser to immediately stop enforcing HSTS. This is the correct way to disable HSTS intentionally, but it sometimes appears in production by mistake when configuration files use placeholder values. Always double-check your deployed header by running a scan or using browser developer tools to inspect the response headers.

Deploying HSTS safely with incremental rollout#

The safest way to deploy HSTS is to start small and increase the scope over time. This incremental approach lets you catch problems early, before a long max-age locks you into a broken configuration. Below is a recommended rollout strategy followed by server configuration examples for the most common platforms.

Start with a max-age of 300 seconds (5 minutes). Deploy this header and monitor your site for at least a few days to make sure all resources load correctly over HTTPS. Next, increase to 86400 (1 day) and test again. If everything looks good, jump to 604800 (1 week), then 2592000 (1 month). Once you are comfortable at one month, set the final value to 31536000 (1 year), add includeSubDomains, and optionally add preload. Only submit to the preload list after you have been running the full header in production for at least a month without issues.

Apache

Apache Configuration
# Add to your VirtualHost or .htaccess Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Nginx

Nginx Configuration
# Add inside your server block (HTTPS only) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Express (Node.js)

Express.js Configuration
// Using helmet middleware (recommended) const helmet = require('helmet'); app.use(helmet.hsts({ maxAge: 31536000, includeSubDomains: true, preload: true })); // Or set the header manually app.use((req, res, next) => { res.setHeader( 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload' ); next(); });

Deployment checklist

  • Confirm all pages and resources load correctly over HTTPS with no mixed-content warnings
  • Verify that HTTP requests return a 301 redirect to the HTTPS equivalent
  • Deploy with max-age=300 first and test for at least 48 hours
  • Gradually increase max-age through 1 day, 1 week, 1 month, then 1 year
  • Enable includeSubDomains only after confirming every subdomain supports HTTPS
  • Submit to the preload list only after running the full header in production for at least one month
  • Monitor your site after each change and check the HSTS header using browser dev tools or a scan
Was this helpful?
Share

Ready to configure your HSTS header?

Generate a properly configured Strict-Transport-Security header in seconds.