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 year
  • includeSubDomains — the rule also applies to all subdomains
  • preload — 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 minutes
  • 86400 = 1 day
  • 31536000 = 1 year

My strong recommendation: start small.

A safe rollout might look like this:

  1. start with 5 minutes
  2. move to 1 day after verifying everything works
  3. 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.com
  • api.example.com
  • admin.example.com

But also less obvious or legacy stuff like:

  • old.example.com
  • dev.example.com
  • mail.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
  • includeSubDomains
  • preload
  • 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.

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 preload as 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.