Understanding HSTS: Enforcing HTTPS
HTTP Strict Transport Security (HSTS) is a response header, defined in RFC 6797, that tells a browser to only ever connect to your domain over HTTPS — and to do the http→https upgrade itself, before any request leaves the device. A server sends Strict-Transport-Security: max-age=31536000 over an HTTPS response; the browser remembers that policy for the max-age duration (one year in this example) and, for that whole period, silently rewrites every http://yoursite URL to https://yoursite instead of sending an unencrypted request. That closes the one gap even a correctly configured HTTPS site leaves open: the first, plaintext HTTP request that a redirect has to answer.
That's the summary an AI Overview would give you. Here's what a summary can't show: why that first plaintext hop is dangerous, exactly which packet an attacker grabs, and how the three HSTS directives (max-age, includeSubDomains, preload) each change the browser's behavior. The animated diagram below traces the same visit with and without HSTS so you can see the vulnerability window open and close, and the decision table further down tells you which header value to ship for your situation.
The Problem HSTS Solves
Consider a user visiting your website:
Without HSTS:
- User types "example.com" in the browser
- Browser initiates HTTP request to example.com (unencrypted)
- Server responds with a redirect to HTTPS
- Browser follows redirect to HTTPS
- Connection is now encrypted
The vulnerability window: Between steps 1-3, an attacker with network access (corporate network, coffee shop WiFi, ISP, etc.) can:
- Intercept the HTTP request
- Respond with their own content or redirect
- Steal credentials, inject malware, or redirect to phishing sites
Even though the eventual connection is HTTPS, the initial HTTP request is unencrypted and vulnerable.
With HSTS:
- Browser has previous history of visiting example.com with HSTS enabled
- Browser automatically upgrades example.com to HTTPS before making any request
- No HTTP request is ever made
- The vulnerability window is eliminated
How HSTS Works
HSTS is communicated through an HTTP header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Breaking this down:
max-age=31536000 - The duration (in seconds) that the browser should enforce HTTPS. 31536000 seconds is one year. This tells the browser: "For the next year, always use HTTPS for this domain."
includeSubDomains - Applies HSTS to all subdomains. Without this, only the exact domain (example.com) requires HTTPS; subdomains like api.example.com could use HTTP.
preload - Opts your domain into the HSTS preload list (explained below).
The HSTS Preload List
The HSTS preload list is a hardcoded list of domains that should always use HTTPS, maintained by the Chromium project and consumed by every modern browser. When Chrome, Firefox, Safari, and Edge are built, they ship this list — now well over 100,000 domains — baked into the binary.
This solves the bootstrapping problem: the first time a user visits your website, there's no HSTS header to enforce HTTPS. With preloading, your domain is already in the browser's list, eliminating the first-visit vulnerability.
To get your domain on the preload list:
- Implement HSTS with all three parameters (max-age, includeSubDomains, preload)
- Ensure all subdomains work over HTTPS
- Submit your domain to https://hstspreload.org/
- The submission is reviewed and added in the next browser release
Once preloaded, every browser automatically enforces HTTPS for your domain even on first visit.
Which HSTS Header Should You Ship?
The right directive combination depends on how much of your infrastructure is provably HTTPS-ready and how permanent your commitment is. Use this table to pick a value instead of copying the maximal header blindly.
| Your situation | Recommended header | Why |
|---|---|---|
| Rolling out for the first time / still verifying HTTPS | max-age=3600 | Short window so a misconfiguration self-heals in an hour, not a year |
| Production apex only, subdomains not all HTTPS-ready | max-age=31536000 | One-year enforcement on the exact host without breaking HTTP-only subdomains |
| Production apex and every subdomain serves HTTPS | max-age=31536000; includeSubDomains | Extends protection to api., cdn., mail., etc. — standard production config |
| Committed to HTTPS forever, want first-visit protection | max-age=31536000; includeSubDomains; preload | Only combination eligible for the browser preload list |
| Need to turn HSTS off | max-age=0 | Expires the cached policy on the visitor's next HTTPS request |
| Internal API / microservice | max-age=31536000 | Enforce HTTPS without joining the public preload list |
| Which should I use? | Start at 3600, ramp to 31536000; includeSubDomains, add preload only after months of clean HTTPS | Ramp lets you catch broken assets before they become a year-long outage |
The one-way-door rule:
includeSubDomainsand especiallypreloadare hard to reverse (preload removal takes 1–2 browser release cycles). Never add them until you can prove every host under your domain answers on HTTPS with a valid certificate.
HSTS Effectiveness Against Attacks
Man-in-the-Middle (MITM) Attack Prevention:
- Attacker cannot intercept and redirect HTTP traffic
- Attacker cannot serve phishing pages over HTTP
- Attacker cannot steal unencrypted credentials
SSL Stripping Attack Prevention:
- Attackers often downgrade HTTPS to HTTP to intercept traffic
- HSTS prevents downgrade because browser won't use HTTP
- Even if attacker intercepts, browser won't connect via HTTP
Cookie Theft Prevention:
- Cookies sent over HTTP are vulnerable
- With HSTS enforcing HTTPS, cookies are only sent over encrypted connections
- Session tokens and authentication cookies are protected
HSTS Side Effects and Considerations
Subdomain Inclusion:
Strict-Transport-Security: max-age=31536000; includeSubDomains
This applies HSTS to ALL subdomains. Every subdomain (api.example.com, cdn.example.com, mail.example.com, etc.) must support HTTPS. If you forget to secure even one subdomain, it becomes inaccessible once HSTS is cached.
Permanent Application: Once set, HSTS persists in the browser's cache for the specified duration (typically one year). If you remove HSTS or your HTTPS certificate fails, the domain remains inaccessible via HTTP until the cache expires.
Preload List Permanence: Removing your domain from the preload list takes a long time (multiple browser release cycles, 1-2 years). Plan HSTS carefully if you might need to disable it later.
Implementation Best Practices
Gradual Rollout:
# Week 1: Short duration to test
Strict-Transport-Security: max-age=3600
# Week 2: Increase duration
Strict-Transport-Security: max-age=86400
# Week 3: Add includeSubDomains
Strict-Transport-Security: max-age=31536000; includeSubDomains
# After 1 year: Submit for preload
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Start with short max-age values while ensuring all your infrastructure supports HTTPS. Gradually increase as you gain confidence.
Before Implementing HSTS, Ensure:
- All pages serve over HTTPS
- All resources (CSS, JS, images) load over HTTPS
- All subdomains support HTTPS
- Redirects from HTTP to HTTPS work correctly
- You never need to revert to HTTP for this domain
Testing with Browser Dev Tools: Most browsers allow you to inspect HSTS status in developer tools, helping verify implementation.
HSTS in Different Contexts
APIs and Microservices:
Strict-Transport-Security: max-age=31536000
APIs should use HSTS without preload (unless the API domain is public-facing and suitable for preload).
Mobile Apps: Most mobile apps make HTTP requests directly, ignoring HTTP-level headers. HSTS helps only with web-based APIs or web views.
Third-Party Content: HSTS applies to the domain that sends the header. Third-party resources (ads, analytics) aren't affected unless those third parties also implement HSTS.
Relationship to Other Security Headers
HSTS and Content-Security-Policy: CSP can be used to enforce HTTPS:
Content-Security-Policy: upgrade-insecure-requests
This upgrades insecure requests to HTTPS. HSTS is stronger—it prevents HTTP entirely.
HSTS and HTTPS Redirects:
# Without HSTS: HTTP → HTTPS redirect
# With HSTS: Skip HTTP entirely
HSTS makes explicit HTTP redirects unnecessary and prevents the vulnerability window they create.
Checking HSTS Implementation
SSL Checker examines HSTS configuration:
- Check "Security Headers" section
- Look for "Strict-Transport-Security" header
- Verify max-age is appropriate (31536000 for production)
- Check if includeSubDomains is present
- Check if preload is present (only if applicable)
A properly implemented HSTS header should show:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Common Mistakes
Setting HSTS on HTTP URL:
# Wrong: Sent over unencrypted HTTP
http://example.com returns HSTS header
HSTS is only transmitted over HTTPS. Setting it on HTTP responses is ineffective for first-time visitors.
Not Including SubDomains Without Planning:
If you include includeSubDomains without ensuring all subdomains support HTTPS, you'll break those subdomains.
Too-Short max-age:
Strict-Transport-Security: max-age=300 # 5 minutes
Too short and the header expires quickly, reducing effectiveness. Use 31536000 (one year) or longer.
Forgetting Wildcard Subdomains: If you use wildcard DNS (*.example.com), ensure all potential subdomains can support HTTPS.
Real-World Attack Scenario
Without HSTS:
- Corporate network intercepts HTTP request to example.com
- Attacker redirects to https://attacker-example.com (certificate warning shown)
- User ignores warning (common behavior)
- Attacker captures credentials
With HSTS:
- Browser has example.com in HSTS cache
- Browser automatically uses HTTPS
- Attacker cannot intercept HTTP (no HTTP request made)
- Attacker cannot present fake certificate (browser expects real example.com certificate)
- Attack fails
HSTS and Public Suffixes
Domains on public suffix lists (like .github.io, heroku.com) often have HSTS with includeSubDomains to protect all user-controlled subdomains.
If you're on a shared platform, pay attention to HSTS headers set by the platform—they may restrict your ability to use HTTP.
Performance Impact
HSTS has minimal performance impact:
- No additional network requests
- Small header size (~70 bytes)
- Browser stores HSTS in local cache (negligible storage)
The only performance consideration is that any user visiting HTTP is redirected to HTTPS, adding one extra redirect. This is actually desirable (the extra security is worth one additional hop).
Recommendations
- Implement HSTS - Essential security control for all HTTPS sites
- Use max-age=31536000; includeSubDomains - Standard production configuration
- Test thoroughly - Ensure all subdomains support HTTPS before implementing
- Plan for permanence - Don't implement HSTS unless you're committed to HTTPS long-term
- Submit for preload - After running HSTS successfully for months
- Monitor with SSL Checker - Regularly verify HSTS is properly configured
- Document policy - Note why HSTS is configured and what it protects
Conclusion: HSTS Is Essential for Modern HTTPS
HSTS is one of the most important security headers you can implement. It eliminates the first-visit and SSL-stripping vulnerabilities that plague even properly-implemented HTTPS sites. Combined with valid certificates, proper cipher configuration, and other security headers, HSTS creates comprehensive protection against man-in-the-middle attacks. Every website with HTTPS should implement HSTS—it's simple, effective, and has become a baseline expectation of modern web security.