HSTS and Preload: Force HTTPS and Avoid Common Errors

HSTS and Preload: Force HTTPS and Avoid Common Errors

Encrypting everything is table stakes now, but simply redirecting HTTP to HTTPS still leaves a gap on the very first visit. A browser may try plain HTTP before it learns your site’s HTTPS policy, which exposes users to downgrade and cookie-injection tricks. HSTS closes that gap after the first secure load, and the preload list can even protect the very first navigation—if you deploy it carefully.

Below we verify how HSTS works, what the preload list does, the exact header values you should ship, and how to roll out, test, and (if needed) remove preload safely. We’ll also call out common footguns like breaking forgotten subdomains or setting the header on the wrong responses.

If you’ve inherited a messy estate with stray subdomains or legacy hosts, don’t rush. HSTS is simple but unforgiving. A staged rollout, a clean DNS inventory, and targeted tests will let you force HTTPS without surprises.

Why HSTS Matters for HTTPS-Only

HSTS (HTTP Strict Transport Security) tells browsers to only use HTTPS for a host and to block click-through on certificate errors. Once a browser receives the policy in an HTTPS response, it caches the rule for the max-age period and upgrades future http:// navigations to https:// before any request leaves the device. That eliminates first-hop downgrades that a plain 301 redirect can’t fully prevent.

How HSTS Works

Browsers learn policy from the Strict-Transport-Security response header, which must be sent over HTTPS only. The core directives are max-age (seconds to remember the policy), includeSubDomains (apply to all subdomains), and the non-standard preload token used to consent to inclusion in browser preload lists. Sending the header again refreshes the timer, so policy persists as long as clients keep visiting.

Header Syntax and Safe Lifetimes

Stage lifetimes upward to reduce blast radius. Practical steps look like 5 minutes, 1 week, 1 month, then 1–2 years long-term. Ship the header on every HTTPS response, including HTTPS redirects, so the policy refreshes even when pages bounce between origins or paths. Keep it off HTTP responses; browsers ignore STS over HTTP, and it can mislead operators during audits.

Strict-Transport-Security: max-age=300
Strict-Transport-Security: max-age=604800
Strict-Transport-Security: max-age=2592000
Strict-Transport-Security: max-age=31536000; includeSubDomains
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

IncludeSubDomains and Scope

includeSubDomains extends the rule to every present and future subdomain. That is powerful and risky. If any subdomain lacks a valid certificate or only serves HTTP, clients will be hard-blocked once they cache policy from the parent. Inventory and fix these before you turn it on. Internal hosts are in scope too; if DNS resolves and the client can reach it, the browser will enforce HTTPS.

Preload: When to Use It (and When Not to)

Preloading solves the “first-visit” problem by baking your domain and a strong HSTS policy into browsers. The very first navigation is already HTTPS, so bootstrap attackers can’t force an insecure first hop. It’s valuable for public sites where users are likely to land via old http:// links or hostile networks. But preload is sticky: removal propagates with browser releases and can take many weeks, so treat it as a one-way door.

Preload Submission Requirements

To be eligible you must: serve a valid certificate on the apex, redirect HTTP to HTTPS if you listen on port 80, ensure that subdomains (especially “www” if it exists in DNS) serve HTTPS correctly, and send on the apex an HSTS header with max-age ≥ 31536000, includeSubDomains, and preload. A common compliant header is shown here.

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

Preload Removal, Lead Time, and Knockout Entries

If you need to exit the list, remove the preload token but keep serving a valid HSTS header, then request removal through the form. Expect the change to reach most users in roughly one to three stable release cycles; other browsers may take longer. If you must fully disable HSTS after removal has propagated, serve a “knockout” header to clear cached policy on clients. Don’t expect max-age=0 to bypass preload while you’re still listed; static preload entries remain in force until the list updates on the client.

Strict-Transport-Security: max-age=0

A Safe Rollout Plan

Map your surface first. Enumerate subdomains from DNS and inventories, then verify each resolves to an endpoint that can serve HTTPS with a valid certificate. Confirm redirects and mixed content so the HTTPS upgrade doesn’t break critical paths. Roll out in stages: add the header with a 5-minute max-age, monitor, increase to one week, then a month, then one or two years. Only after running includeSubDomains at the final lifetime without issues should you add preload and consider submitting.

Minimal Configuration Examples

Use these baseline snippets and adapt them to your environment. Ensure they are scoped to HTTPS listeners only and consistently applied at your edge/CDN.

# Nginx (HTTPS server block)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Apache (set only when HTTPS is active)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS

# IIS (web.config fragment under <system.webServer>)
<httpProtocol>
  <customHeaders>
    <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
  </customHeaders>
</httpProtocol>

Testing and Verification

Use curl to verify headers and redirects from a clean vantage point. Check the apex and key subdomains independently; HSTS is stored per host, and a browser may hit a subdomain before the parent. In devtools, confirm no mixed content and that HTTPS responses include STS even when they are redirects or 304s served from your CDN/edge.

# Expect STS header on HTTPS
curl -I https://example.com | grep -i strict-transport-security

# Expect fast 301 from HTTP to HTTPS on same host
curl -I http://example.com

# Spot-check a subdomain
curl -I https://www.example.com

Preload-Specific Checks

Before submission, double-check that www resolves, serves HTTPS, and includes the same header. Confirm that internal or legacy subdomains either have valid certificates and HTTPS listeners or are not resolvable publicly. Run the preload form’s diagnostics and resolve any failures. Plan for the lead time; expect weeks for changes to land broadly as browsers update.

Common Errors and How to Avoid Them

Breaking a forgotten subdomain is the classic failure. Avoid it by auditing DNS and hosting before you ship includeSubDomains. Another frequent mistake is setting the header only on HTML routes and not on HTTPS redirects or static asset hosts; set it consistently at your edge. Don’t send the header on HTTP responses. Avoid enabling preload prematurely; make preload a deliberate, separate change after months of stable includeSubDomains at a long max-age.

Modern Browser Behavior and What It Means

Chrome already tries HTTPS first for most typed navigations and offers HTTPS-First Mode that warns before loading insecure HTTP, with the goal of broader enablement over time. That reduces—but doesn’t remove—the value of HSTS and preload, which still provide strict behavior like blocking certificate error click-through and protecting links from non-typed entry points.

Quick Reference

Use HSTS by default on public sites, prefer 1–2 years for max-age, enable includeSubDomains only after verifying every subdomain, and consider preload only when your whole zone is permanently HTTPS and you accept slow reversibility. Test with curl and devtools, stage the rollout, and if something breaks after a client has cached policy, fix the certificate or HTTPS listener—users can’t click through errors on HSTS hosts.

HSTS and Preload Best Practices (FAQ)

One to two years works well in practice; teams commonly pin at two years once all subdomains are proven HTTPS-only.

Yes, include it on HTTPS responses (including redirects) so clients refresh the policy; keep it off HTTP responses entirely.

Run a quick DNS Lookup for the apex and critical subdomains, and verify each points to an HTTPS-capable endpoint.

Yes, if a DNS record for www exists, it must serve HTTPS with the same header so preload and includeSubDomains don’t break it.

Plan for several release cycles; it often takes 6–12 weeks for one major browser and longer for others to reflect the change.

Confirm your egress with What Is My IP Address, then run curl checks from that vantage point to mirror real client paths.

Delay includeSubDomains or isolate that host under a different parent zone that won’t inherit the apex policy until it’s upgraded.

Use a Subnet Calculator to document ranges and certificate coverage so every endpoint gets a valid certificate before cutover.