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.
Here is the process step by step:
Strict-Transport-Security header in the response.http:// URL to https:// before sending the request.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 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:
max-age=300 (5 minutes) and test thoroughly.max-age=86400 (1 day) once you are confident.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.
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.
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:
max-age of at least 31,536,000 (1 year).includeSubDomains flag.preload flag in the header.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.
Without HSTS, a typical HTTPS site has this redirect chain:
http://yourdomain.com (plaintext).https://yourdomain.com.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.
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
<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
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.
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.
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.
Run a free scan and get a full report on your HSTS header, SSL configuration, and other security settings.
Free Security Scan