HomeServicesPricingFAQBlogAboutContactFree Scan

What Is the HSTS Header and Why Does It Matter?

QUICK ANSWER

HSTS (HTTP Strict Transport Security) is a header that tells browsers to always connect to your site over HTTPS, never HTTP. Without it, attackers can intercept the initial HTTP request before it redirects to HTTPS. Once a browser sees the HSTS header, it refuses to make any HTTP connections to your domain for the duration you specify.

Most websites that use HTTPS still accept HTTP connections. When someone types yourdomain.com into their browser without the https:// prefix, the browser first tries HTTP. The server then redirects to HTTPS. That brief window, the initial HTTP request before the redirect happens, is where the danger lies.

An attacker on the same network (public Wi-Fi, compromised router, corporate network) can intercept that plaintext HTTP request. This is called SSL stripping. The attacker downgrades the connection, reads the traffic, and forwards it to the real server. The visitor never realises their connection was compromised.

HSTS eliminates this problem entirely. Once a browser has seen the HSTS header from your site, it refuses to make HTTP connections to your domain. It converts any http:// request to https:// before it even leaves the browser. No interception window. No downgrade possible.

How HSTS works

Here is the process step by step:

  1. A visitor loads your site over HTTPS for the first time.
  2. Your server includes the Strict-Transport-Security header in the response.
  3. The browser stores this instruction locally, alongside the max-age you specified.
  4. For every subsequent request to your domain, the browser checks its HSTS cache.
  5. If HSTS is active, the browser converts any http:// URL to https:// before sending the request.
  6. No HTTP connection is ever made. The interception window disappears.

The catch is that first visit. If the very first connection is intercepted before the browser sees the HSTS header, HSTS cannot help. This is where HSTS preload comes in (see below).

The max-age directive

The max-age value tells the browser how long, in seconds, to remember the HSTS instruction. We recommend setting it to at least one year.

Strict-Transport-Security: max-age=31536000

That is 31,536,000 seconds, or exactly 365 days. Every subsequent visit resets the timer.

Start small, then increase. A sensible rollout approach is:

  • Start with max-age=300 (5 minutes) and test thoroughly.
  • Increase to max-age=86400 (1 day) once you are confident.
  • Move to max-age=31536000 (1 year) when everything works reliably.

The reason to start small is that HSTS is sticky. If you set a long max-age and then discover a problem (a subdomain that only supports HTTP, for instance), every visitor who received the header is locked out for the duration. You cannot revoke HSTS from the server side. You have to wait for it to expire in each browser.

The includeSubDomains flag

Adding includeSubDomains extends the HSTS rule to every subdomain of your domain:

Strict-Transport-Security: max-age=31536000; includeSubDomains

This means blog.yourdomain.com, shop.yourdomain.com, staging.yourdomain.com, and every other subdomain must also support HTTPS. If any subdomain only works over HTTP, visitors will be locked out.

Common mistake: Enabling includeSubDomains without verifying that every subdomain has a valid SSL certificate. Check all your subdomains first, including internal and staging environments that may be publicly accessible.

The preload list

HSTS preload solves the "first visit" problem. When you submit your domain to the HSTS preload list at hstspreload.org, your domain is hardcoded into browsers as HTTPS-only. This means even the very first connection will use HTTPS, because the browser already knows about your domain before it ever visits.

To qualify for preload, you must:

  • Serve the header with max-age of at least 31,536,000 (1 year).
  • Include the includeSubDomains flag.
  • Include the preload flag in the header.
  • Have a valid SSL certificate on your main domain and all subdomains.
  • Redirect all HTTP traffic to HTTPS on the same host.

Your header should look like this:

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

Important: Preload is effectively permanent. Removing your domain from the preload list takes weeks to months because it requires a browser update. Do not submit for preload unless you are certain you will support HTTPS on your domain indefinitely.

The redirect chain problem HSTS solves

Without HSTS, a typical HTTPS site has this redirect chain:

  1. Browser sends request to http://yourdomain.com (plaintext).
  2. Server responds with a 301 redirect to https://yourdomain.com.
  3. Browser makes a new request to https://yourdomain.com (encrypted).

Step 1 is the vulnerability. The request is sent in plaintext and can be intercepted. With HSTS active, step 1 never happens. The browser converts the URL to HTTPS internally and goes straight to step 3.

This also improves performance. One fewer redirect means one fewer round trip, which shaves tens to hundreds of milliseconds off the initial page load.

How to implement HSTS

nginx

server {
    listen 443 ssl;
    server_name yourdomain.com;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # ... rest of your SSL config
}

Always use the always keyword so the header is included even on error responses. Reload nginx after changes: sudo nginx -t && sudo systemctl reload nginx

Apache

<VirtualHost *:443>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    # ... rest of your SSL config
</VirtualHost>

Ensure mod_headers is enabled: sudo a2enmod headers

WordPress

Many WordPress hosting providers set HSTS automatically when you enable SSL. If yours does not, you can add it in your wp-config.php:

header('Strict-Transport-Security: max-age=31536000; includeSubDomains');

Or use a plugin like Really Simple SSL which handles HSTS configuration through its settings panel.

Testing your HSTS configuration

Open your browser's developer tools (F12), go to the Network tab, load your site over HTTPS, and look for the Strict-Transport-Security header in the response. Check that the max-age value is what you expect.

You can also use an online tool like hstspreload.org which will verify your header and tell you if your domain qualifies for the preload list.

For a complete check that covers HSTS along with all your other security headers, SSL configuration, and more, try PulseShield's free security scan.

Common issues with HSTS

Too short max-age. Values under 30 days provide minimal protection. Aim for at least one year.

Forgetting to test before preload. Once you submit to the preload list, removing your domain is slow and difficult. Test thoroughly with includeSubDomains and preload flags before submitting.

Mixed content on subdomains. If a subdomain loads resources over HTTP, HSTS will block them. Make sure all subdomains serve all resources over HTTPS.

Not setting the header on error pages. Without the always keyword in nginx or the always flag in Apache, the header may not be sent on 404 or 500 pages, which can cause the browser's HSTS cache to expire.

Related guides

Check if your site uses HSTS correctly

Run a free scan and get a full report on your HSTS header, SSL configuration, and other security settings.

Free Security Scan