SSL/TLS & HTTPS

What Is HSTS and Why Is It Important?

Learn about HTTP Strict Transport Security, how it prevents man-in-the-middle attacks, HSTS preloading, and best practices for implementation.

By Inventive HQ Team

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.

HTTP request flow with and without HSTS Without HSTS, the first request travels over plain HTTP and can be intercepted; with HSTS the browser upgrades to HTTPS before any request leaves, so there is no plaintext packet to intercept.

A visit to example.com: the first request

WITHOUT HSTS — vulnerability window open Browser example.com attacker on path GET http://example.com (plaintext) intercepted here → SSL strip / phishing redirect WITH HSTS — upgraded before any packet leaves Browser HSTS policy cached example.com http→https rewrite GET https://example.com (encrypted) no plaintext packet exists to intercept

The Problem HSTS Solves

Consider a user visiting your website:

Without HSTS:

  1. User types "example.com" in the browser
  2. Browser initiates HTTP request to example.com (unencrypted)
  3. Server responds with a redirect to HTTPS
  4. Browser follows redirect to HTTPS
  5. 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:

  1. Browser has previous history of visiting example.com with HSTS enabled
  2. Browser automatically upgrades example.com to HTTPS before making any request
  3. No HTTP request is ever made
  4. 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:

  1. Implement HSTS with all three parameters (max-age, includeSubDomains, preload)
  2. Ensure all subdomains work over HTTPS
  3. Submit your domain to https://hstspreload.org/
  4. 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.

Advertisement

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 situationRecommended headerWhy
Rolling out for the first time / still verifying HTTPSmax-age=3600Short window so a misconfiguration self-heals in an hour, not a year
Production apex only, subdomains not all HTTPS-readymax-age=31536000One-year enforcement on the exact host without breaking HTTP-only subdomains
Production apex and every subdomain serves HTTPSmax-age=31536000; includeSubDomainsExtends protection to api., cdn., mail., etc. — standard production config
Committed to HTTPS forever, want first-visit protectionmax-age=31536000; includeSubDomains; preloadOnly combination eligible for the browser preload list
Need to turn HSTS offmax-age=0Expires the cached policy on the visitor's next HTTPS request
Internal API / microservicemax-age=31536000Enforce 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 HTTPSRamp lets you catch broken assets before they become a year-long outage

The one-way-door rule: includeSubDomains and especially preload are 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:

  1. All pages serve over HTTPS
  2. All resources (CSS, JS, images) load over HTTPS
  3. All subdomains support HTTPS
  4. Redirects from HTTP to HTTPS work correctly
  5. 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:

  1. Check "Security Headers" section
  2. Look for "Strict-Transport-Security" header
  3. Verify max-age is appropriate (31536000 for production)
  4. Check if includeSubDomains is present
  5. 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:

  1. Corporate network intercepts HTTP request to example.com
  2. Attacker redirects to https://attacker-example.com (certificate warning shown)
  3. User ignores warning (common behavior)
  4. Attacker captures credentials

With HSTS:

  1. Browser has example.com in HSTS cache
  2. Browser automatically uses HTTPS
  3. Attacker cannot intercept HTTP (no HTTP request made)
  4. Attacker cannot present fake certificate (browser expects real example.com certificate)
  5. 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

  1. Implement HSTS - Essential security control for all HTTPS sites
  2. Use max-age=31536000; includeSubDomains - Standard production configuration
  3. Test thoroughly - Ensure all subdomains support HTTPS before implementing
  4. Plan for permanence - Don't implement HSTS unless you're committed to HTTPS long-term
  5. Submit for preload - After running HSTS successfully for months
  6. Monitor with SSL Checker - Regularly verify HSTS is properly configured
  7. 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.

Frequently Asked Questions

What does the HSTS header actually do?

HSTS (defined in RFC 6797) sends the response header Strict-Transport-Security: max-age=<seconds> over HTTPS. Once a browser sees it, it refuses to make plain HTTP requests to that domain for the duration of max-age — it rewrites any http:// URL to https:// internally before a request leaves the machine. This kills the unencrypted first hop that SSL-stripping attacks depend on.

What is the recommended max-age value for HSTS?

Production sites should use max-age=31536000 (one year, or longer). The HSTS preload list requires at least 31536000. Start with a short value like 3600 (one hour) while you confirm every page and subdomain works over HTTPS, then ramp up. A too-short max-age (minutes) expires before it protects most repeat visits.

What is the difference between HSTS and an HTTP-to-HTTPS redirect?

A 301 redirect still requires the browser to make one unencrypted HTTP request first, which an attacker on the network can intercept before the redirect ever arrives. HSTS removes that request entirely — the browser upgrades to HTTPS on its own before any packet leaves. You still need the redirect for the very first visit (or use preload), but HSTS closes the window the redirect leaves open.

Is the HSTS preload list safe to join?

It is safe only if you are fully committed to HTTPS on the apex domain and every subdomain, indefinitely. Preloading hardcodes your domain into browsers, so there is no HTTP fallback even on a first visit. Removal requests take one to two years to propagate through browser releases, so never preload a domain you might need to serve over HTTP again.

What breaks if I add includeSubDomains?

Every subdomain — api., cdn., mail., internal dashboards, legacy dev hosts — must serve valid HTTPS, because the browser will refuse HTTP to all of them once the header is cached. A single subdomain that only listens on port 80, or has an expired certificate, becomes unreachable until the max-age expires. Inventory your subdomains before adding this directive.

Does HSTS require sending the header on HTTP responses too?

No — and browsers ignore it there. HSTS is only honored when delivered over a valid HTTPS connection. Sending Strict-Transport-Security on an HTTP response does nothing for first-time visitors. Send it on your HTTPS responses, and use the preload list to cover the very first request.

How do I remove or disable HSTS?

Serve Strict-Transport-Security: max-age=0 over HTTPS. This tells compliant browsers to expire the policy immediately on their next visit. Users who never return keep the old cached policy until it lapses. If your domain is on the preload list, you must also request removal at hstspreload.org, which takes several browser release cycles.

How can I check whether HSTS is configured correctly?

Inspect the response headers over HTTPS with curl -sI https://yourdomain and confirm a strict-transport-security line with an appropriate max-age. Our SSL Checker reports the header, its max-age, and whether includeSubDomains and preload are present, and hstspreload.org validates your domain against the exact preload requirements.

hstshttpssecurityheadersman-in-the-middle