If you’re using Cloudflare in front of your site, turning on HSTS is one of those small changes that can meaningfully tighten security with almost no ongoing maintenance. But it’s also one of those settings that’s easy to misunderstand, and if you flip it on carelessly, you can absolutely lock yourself into HTTPS behavior before your site is fully ready.
So let’s do this the practical way: what HSTS actually does, what Cloudflare changes, the safe rollout path, and exactly where to click.
What HSTS does
HSTS stands for HTTP Strict Transport Security. It tells browsers:
- always use HTTPS for this site
- never allow a downgrade to HTTP for a defined period
- optionally apply the rule to all subdomains
- optionally make the domain eligible for browser preload lists
In plain English, once a browser sees your HSTS header, it remembers that your site must only be accessed over HTTPS. That blocks protocol downgrade attacks and helps prevent users from accidentally visiting the insecure version of your site.
A typical HSTS header looks like this:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
The key parts are:
max-age=31536000— browsers remember the rule for 1 yearincludeSubDomains— the rule also applies to all subdomainspreload— signals intent for preload list submission
What Cloudflare does differently
If your site is proxied through Cloudflare, Cloudflare can send the HSTS header on your behalf. That means you usually don’t need to configure it on your origin server at all, although you still can if you prefer origin-managed headers.
For a lot of teams, enabling HSTS in Cloudflare is the easiest option because:
- it’s fast to turn on
- it applies at the edge
- you don’t need to touch Apache, Nginx, or app code
- it’s easy to test
That said, Cloudflare can only safely enforce HSTS if your site is actually ready for HTTPS everywhere.
Before enabling it, make sure:
- your site works over HTTPS without mixed-content issues
- all important subdomains support HTTPS if you plan to enable
includeSubDomains - HTTP requests are redirected to HTTPS
- your Cloudflare SSL/TLS mode is configured correctly
Before you enable HSTS: check SSL/TLS mode
This matters more than people think.
In Cloudflare, go to your domain and look at the SSL/TLS mode. The common options are:
- Off
- Flexible
- Full
- Full (strict)
If possible, use Full (strict). That means:
- browser to Cloudflare uses HTTPS
- Cloudflare to your origin also uses HTTPS
- Cloudflare validates the origin certificate
This is the setup you actually want for real security.
If you’re using Flexible, be careful. Flexible means the visitor connects to Cloudflare with HTTPS, but Cloudflare may connect to your origin over plain HTTP. That’s not a setup I’d recommend long term, and it’s not a great foundation for HSTS. If you’re serious enough about HTTPS to enable HSTS, you should usually be serious enough to move to Full or Full (strict).
Step 1: Make sure HTTP redirects to HTTPS
Before HSTS, your site should already redirect HTTP traffic to HTTPS.
In Cloudflare, you can do this with the Always Use HTTPS setting.
Go here:
- Cloudflare Dashboard
- Select your site
- SSL/TLS
- Edge Certificates
Find Always Use HTTPS and turn it on.
This makes Cloudflare redirect visitors from http:// to https://.
Why do this first? Because HSTS only takes effect after the browser has seen the HSTS header over a valid HTTPS response. Redirecting HTTP cleanly is part of the normal transition path.
Step 2: Enable HSTS in Cloudflare
Now for the actual setting.
In Cloudflare:
- open your domain
- go to SSL/TLS
- open Edge Certificates
- scroll to HTTP Strict Transport Security (HSTS)
- click Enable HSTS
Cloudflare will usually show a warning. Read it. This is one of the few warning dialogs worth taking seriously.
You’ll then be asked to configure a few HSTS options.
Step 3: Choose the right HSTS settings
Cloudflare exposes the main HSTS controls you care about.
Max Age
This controls how long browsers remember the HTTPS-only rule.
Example values:
max-age=300
max-age=86400
max-age=31536000
What they mean:
300= 5 minutes86400= 1 day31536000= 1 year
My strong recommendation: start small.
A safe rollout might look like this:
- start with 5 minutes
- move to 1 day after verifying everything works
- move to 1 month or 1 year once you’re confident
That lets you catch mistakes without creating a long-lived problem in user browsers.
If you immediately set max-age=31536000 and then discover a broken subdomain or certificate issue, you’ve created a frustrating recovery situation.
Include Subdomains
This adds includeSubDomains to the header.
Example:
Strict-Transport-Security: max-age=86400; includeSubDomains
Only enable this if every subdomain that matters is HTTPS-ready.
That includes obvious things like:
www.example.comapi.example.comadmin.example.com
But also less obvious or legacy stuff like:
old.example.comdev.example.commail.example.com
This is where people get burned. They think about the main site, forget about an old subdomain, then wonder why something broke for users with cached HSTS policy.
If you’re not 100% sure, leave this off initially.
No-Sniff Header
Cloudflare may also offer related browser security headers in nearby settings, but don’t confuse those with HSTS. HSTS is specifically the Strict-Transport-Security header. Useful, but separate.
Preload
This adds the preload token:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
This is a big commitment.
Browser preload means your domain can be hardcoded into browser HSTS preload lists, so browsers know to use HTTPS even on the very first visit.
That sounds great, and it is great for mature setups. But do not rush into it.
To be preload-eligible, you generally need:
- HTTPS working everywhere
- a long max-age, usually at least 1 year
includeSubDomainspreload- all subdomains served securely
If you’re not completely certain that your whole domain namespace is permanently HTTPS-only, don’t enable preload yet.
I’m opinionated here: preload is for stable production domains with disciplined infrastructure, not for “we’ll clean up the subdomains later.”
Example HSTS policies
Here are a few practical examples.
Cautious initial rollout
Strict-Transport-Security: max-age=300
Good for testing. Very forgiving.
Reasonable production policy
Strict-Transport-Security: max-age=31536000
Good if you only want to cover the exact host and not all subdomains yet.
Production with subdomains
Strict-Transport-Security: max-age=31536000; includeSubDomains
Good when all subdomains are known to support HTTPS.
Preload-ready policy
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Only for fully committed HTTPS-only environments.
Step 4: Save and test the header
After saving the HSTS settings in Cloudflare, test your HTTPS response headers.
You can use curl from a terminal:
curl -I https://example.com
You should see a response header like:
Strict-Transport-Security: max-age=31536000; includeSubDomains
If you want to test the www version too:
curl -I https://www.example.com
And if you want to verify the HTTP redirect behavior:
curl -I http://example.com
You should see a redirect to HTTPS, something like:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Test your HSTS configuration and other security headers at headertest.com - free, instant, no signup required.
Optional: enable HSTS via the Cloudflare API
If you manage infrastructure programmatically, you may prefer using the Cloudflare API instead of clicking around in the dashboard.
Cloudflare’s API evolves, so always verify the exact endpoint and payload structure in the current docs. But the general pattern is updating your zone’s settings related to HSTS.
A conceptual example looks like this:
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/security_header" \
-H "Authorization: Bearer API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"value": {
"strict_transport_security": {
"enabled": true,
"max_age": 31536000,
"include_subdomains": true,
"preload": false,
"nosniff": true
}
}
}'
Treat that as an example of the shape, not guaranteed copy-paste syntax for every account or API version. The important point is that HSTS can be automated, which is nice if you manage many zones.
Common mistakes
Enabling HSTS before HTTPS is fully working
This is the classic one.
If your certificate is broken, your redirects loop, or parts of the site still depend on HTTP assets, HSTS can turn a small configuration issue into a real outage for users.
Turning on includeSubDomains too early
If one forgotten subdomain doesn’t support HTTPS, browsers that cache the HSTS policy will refuse insecure access there.
Audit first. Then enable.
Using preload casually
Preload is not a badge. It’s a commitment.
If you preload your domain and later need a non-HTTPS subdomain, you’re going to have a bad time.
Forgetting Cloudflare is only part of the path
Cloudflare can send the header, but your origin and app still need to behave correctly over HTTPS. Watch for:
- mixed content
- insecure absolute URLs
- bad origin certs
- redirect loops between Cloudflare and origin
How to disable HSTS if you need to back out
In Cloudflare, you can turn HSTS off or reduce the max-age. If you need browsers to forget the policy, the standard approach is to serve:
Strict-Transport-Security: max-age=0
That tells browsers to clear the HSTS rule for the host.
But here’s the catch: browsers have to receive that header over a valid HTTPS connection first. If your HTTPS setup is already broken, some users may be stuck until the cached policy expires.
That’s another reason to start with a small max-age during rollout.
Also, if you’ve gone as far as preload, backing out is slower and more annoying because browser preload lists are not updated instantly.
Recommended rollout plan
If you want the boring, low-risk version, do this:
Phase 1
- fix HTTPS everywhere
- use Cloudflare SSL/TLS mode: Full (strict)
- enable Always Use HTTPS
- set HSTS max-age to 300
- do not enable includeSubDomains
- do not enable preload
Phase 2
After a day or two of testing:
- raise max-age to 86400
- test all important hostnames
- verify no certificate or redirect issues
Phase 3
When fully confident:
- raise max-age to 31536000
- optionally enable includeSubDomains if every subdomain is HTTPS-ready
Phase 4
Only if you truly mean it:
- enable preload
- submit the domain for preload inclusion if needed
This staged approach is not glamorous, but it’s the one that avoids panic later.
Final thoughts
Enabling HSTS in Cloudflare is easy. Enabling it safely is the part that matters.
The dashboard path is straightforward, and for many sites Cloudflare is the cleanest place to manage the header. But don’t let the simple UI fool you into treating HSTS like a reversible checkbox. Browsers cache this policy by design, and that’s exactly what gives it value.
My practical advice is simple:
- use Full (strict)
- redirect HTTP to HTTPS first
- start with a short max-age
- be conservative with
includeSubDomains - treat
preloadas permanent infrastructure, not an experiment
Do that, and HSTS becomes one of those rare security improvements that is both effective and mostly invisible. That’s usually the sweet spot.