HSTS in WordPress: five minutes first, then six months
Updated by Nazmul Hasan Rupok on
HSTS in WordPress comes down to one response header, Strict-Transport-Security, that tells browsers to use only HTTPS for your site for a set time. Once a browser has seen it, it stops trying plain HTTP for your site at all. Unlike most security headers, its effect stays in visitors’ browsers after you take it away.
That last part is why the order you do things in matters. This guide covers what the header does, what max-age, includeSubDomains and preload mean, why a five-minute trial comes first, what HTTPS behind a proxy changes, and the exact steps in BetterShield. For the other headers a site can send, see WordPress security headers, explained.
Quick summary
- HSTS tells a browser to use only HTTPS for your site until a set time runs out, and to refuse plain HTTP even when the certificate has a problem.
- Turning it off stops the header, but it cannot reach browsers that already saw it. A five-minute trial limits the new policy duration; existing policies or cached headers can still apply.
includeSubDomainscovers every host name under the one that sent it. Choose it only when every one of them answers on HTTPS.- Preload asks for your domain to be built into browsers. BetterShield never adds it.
- Behind a proxy that handles the encryption, WordPress has to be told the request was secure, or the header is never sent.
What HSTS does
Without HSTS, a browser can still ask for your site over plain HTTP: an older browser following an http:// link or a typed address, for example, or a newer one that falls back to HTTP when its HTTPS attempt fails. Your server answers with a redirect to HTTPS, and the visit carries on securely. But that plain request travels unencrypted, and anything on the network between the visitor and your server can answer it in your server’s place.
HSTS removes that step for browsers that know your site. Once a browser has received the header over HTTPS:
- It rewrites http:// to https:// for your host name before anything leaves the browser: typed addresses, links, and files the page loads.
- It refuses plain HTTP for your site until the time in the header runs out.
- It treats a certificate error as final. The visitor gets an error page with no way past it.
Two limits are worth knowing. A browser has to visit once over HTTPS to learn the rule, so a first visit is not covered. And the rule belongs to the exact host name that sent it: a header from www.example.com says nothing about example.com.
Turning a setting off is not a recall
Follow one browser that has received an HSTS header.
- Header received
HTTPS becomes the rule.
- Server setting removed
The stored rule remains.
- Policy expires or is replaced
HTTPS still has to work.
Header received
- What this means
- The browser remembers a duration for the host. Each later HSTS response can refresh that duration.
- Your next check
- Read the actual header after redirects and check whether it includes subdomains.
Server setting removed
- What this means
- Omitting the header does not erase the browser’s earlier instruction. A cached response may also continue sending it.
- Your next check
- Check the CDN and server configuration before treating the header as removed.
Policy expires or is replaced
- What this means
- A browser can learn a replacement policy only from a valid HTTPS response. A broken certificate cannot deliver the fix to that browser.
- Your next check
- Restore valid HTTPS first; coordinate any policy reduction with the host.
Why start with five minutes
Most security headers work one response at a time: remove one and the next page is back to how it was. HSTS is remembered. A browser that saw a six-month setting insists on HTTPS for six months after its last response carrying that header, and only a newer header it receives on a later visit can change that.
That is harmless while HTTPS works everywhere it should. It hurts when something you forgot still needs plain HTTP, or HTTPS stops working: a page or file that only loads over plain HTTP, a subdomain nobody moved (if you cover subdomains), a certificate that fails to renew. With a long setting, that breaks for every visitor who has seen the header, for months, and switching the header off does not help them.
A five-minute setting behaves the same in every way but one: if something breaks, browsers forget the rule five minutes after their last response carrying that header. So send five minutes, use the site the way visitors do, and only then decide on six months. During the trial:
- Type your domain without https:// and check you land on the HTTPS home page.
- Sign in, use the dashboard, send a form, and place a test order if you run a store.
- If you plan to cover subdomains, open each one over HTTPS.
max-age, includeSubDomains and preload in plain terms
| Part | What it means | What BetterShield sends |
|---|---|---|
max-age | How many seconds the browser should insist on HTTPS. Each response carrying HSTS refreshes the expiry. | 300 (five minutes) or 15768000 (six months) |
includeSubDomains | The rule also covers every host name under the one that sent it. | Only when you choose Every subdomain as well |
preload | A request to be written into a list browsers ship with, so even a first visit uses HTTPS. | Never |
includeSubDomains
It covers names under the host that sent the header. For a site at example.com, that means www, shop, staging, mail and anything else under it, including names set up years ago. For a site at www.example.com, it covers only names under www.
Before choosing it, list every subdomain in your DNS and open each one over HTTPS. One that answers only on plain HTTP stops opening in every browser that saw the header. BetterShield’s own field says it plainly: “Only if every subdomain you have is on HTTPS too.”
preload
Preload goes further: your domain is added to a list compiled into browsers, so even a first visit uses HTTPS. Getting on the list is a submission you make, and getting off it is slow. In the fix’s words: “Never adds preload: that is a submission to a list built into browsers, and removal from it takes months.” If you ever want it, treat it as a separate decision to make with your host after living with the long setting.
Before you turn it on
- The site address is HTTPS. Check Settings › General in WordPress. BetterShield does not offer the fix until it is: the row reads Not available here.
- The certificate renews on its own. BetterShield’s audit reports The site’s certificate is close to expiring from 21 days before expiry, and the fix asks you to renew first when expiry is that close.
- WordPress knows when a request is encrypted. On many hosts it does without help. Behind a proxy, read the next section.
HTTPS behind a proxy, load balancer or CDN
Many hosts put something in front of WordPress that handles the encryption, then pass the request on over plain HTTP. WordPress does not read X-Forwarded-Proto, so unless the server or wp-config.php sets the HTTPS variable, it believes every request arrived over plain HTTP. Browsers ignore HSTS on a plain-HTTP response, so BetterShield sends the header only on requests WordPress sees as encrypted, and in this setup it never goes out.
BetterShield spots the mismatch. When the site address is HTTPS but the request reached WordPress as plain HTTP, the row explains that “applying this changes nothing” until wp-config.php sets the HTTPS server variable for those requests.
When your front end sends an X-Forwarded-Proto header, the usual fix is a few lines in wp-config.php, above the line that says to stop editing:
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
Use it only when your server can be reached through that front end alone, because otherwise anyone can send the header. Ask your host which header theirs sends; some already set the variable for you. If your CDN or host can add HSTS itself, choose one place to send it from. The Server compatibility guide covers the rest of this setup.
How to turn on HSTS in WordPress with BetterShield
The fix is Strict HTTPS (HSTS), under What browsers are told on BetterShield › Protection › Hardening.
- Leave How long browsers should insist at Five minutes, to prove it works and Include subdomains at This domain only. Both are preselected.
- Press Preview the change. Its first line ends with the exact header,
max-age=300, and nothing is changed. - Turn the switch on. The row shows the value with a Copy button, and “Confirmed on a page a visitor received” once a visitor has loaded a page over HTTPS.
- Work through the trial list above.
- To move to six months, turn the switch off, choose Six months, once you have lived with the short one, and turn it on again. The header becomes
max-age=15768000.
It goes out on front-end pages, the sign-in page, the dashboard and the REST API, on HTTPS requests only. If WordPress or another plugin already sets the header, BetterShield leaves it exactly as it is.
From the terminal, wp bettershield harden hsts --user=<login> applies five minutes on this domain only, and --mode=long asks for six months. A connected AI assistant may apply only the five-minute, this-domain-only form on its own; six months, or every subdomain, needs your agreement first. Every option is in the HSTS guide.
What undo can and cannot reach
Turning the switch off stops the header at once. Browsers that already saw it keep their rule until their own period ends, counted from their last HSTS response.
| What a browser saw | After you turn the fix off |
|---|---|
max-age=300 | That policy expires five minutes after the last HSTS response, unless another applicable policy remains. |
max-age=15768000 | It keeps insisting on HTTPS for up to six months. |
Either, with includeSubDomains | The same, for every host name under yours. |
One thing does reach them: a newer header. A browser replaces its stored rule each time it receives the header over HTTPS. So to step down from six months, do not leave the fix off. Turn the switch off, choose Five minutes, to prove it works (and This domain only, if you had chosen every subdomain), and turn it straight back on. Browsers that come back pick up the short rule; browsers that never come back keep the old one until it runs out.
Testing with a clean browser profile can help separate stored policy from the current server response. Clearing local browser state never repairs visitors’ policies or a broken certificate.
What nothing can reach is a visitor whose browser holds a six-month rule while your HTTPS is broken. Preventing that is what the trial and a self-renewing certificate are for.
Confirm the host and the header you are changing
Test the hostname visitors actually use. The apex domain, www and a staging hostname can have different policies, redirects and certificates. HSTS applies to browser connections to those hosts; a mail subdomain matters if someone uses its web interface, not because HSTS configures SMTP or IMAP.
A read-only header check for your own site is:
curl -sS -D - -o /dev/null https://example.com/
Replace the example host with yours and inspect the Strict- value. Check redirect destinations separately. This reads a response; it does not prove certificate renewal is reliable or reproduce every browser’s stored policy.
Worked example (fictional): the production host has valid HTTPS but staging.example.com serves an old internal page over HTTP. Keep This domain only while the host team fixes or retires staging. Do not include every subdomain merely because the production home page loads correctly.
For rollback, distinguish three jobs: stop sending the unwanted policy, make valid HTTPS available, and let browsers receive the revised instruction. A host can send max-age=0 over valid HTTPS to remove that host’s learned policy, but this does not erase a parent’s coverage, independently stored subdomain policies or preload. BetterShield’s short setting reduces the duration for browsers that receive it. MDN explains the browser’s stored HSTS policy.
Common mistakes
- Starting at six months. The five-minute trial costs nothing and shows what still needs plain HTTP.
- Choosing every subdomain without a list. A forgotten staging or mail subdomain on plain HTTP stops opening for months.
- Assuming it works behind a proxy. Read the row. If WordPress sees plain HTTP, the header never goes out.
- Leaving it off to shorten it. That leaves the long rule in place. Turn it off, choose five minutes, turn it straight back on, and keep it on for a while.
- Sending it from two places. If your host or CDN adds HSTS too, pick one, so visitors get one header.
Frequently asked questions
Does BetterShield add HSTS preload?
No. Preload writes your domain into a list browsers ship with, and removal takes months, so the fix never adds it.
What happens if my certificate expires while HSTS is on?
Visitors whose browsers saw the header get an error page they cannot click past until the certificate is renewed. BetterShield’s audit reports The site’s certificate is close to expiring from 21 days before: Medium at first, High within 7 days and Critical within 2. Renewing is done with your host or certificate provider.
My site already redirects to HTTPS. Do I still need HSTS?
The redirect and HSTS work together. The redirect answers a plain-HTTP request once it arrives; HSTS stops a browser that knows your site from sending one. Keep the redirect either way, because first visits still rely on it.
Does HSTS work on a multisite network?
Each site turns the fix on for itself. On the main site of a subdomain network, Every subdomain as well covers every site, and the field says all of them must already be on HTTPS. On a subdirectory network all sites share one host name, so a header from any of them covers the rest.
Conclusion
HSTS in WordPress is a small header with a long memory. Make sure the site address is HTTPS and WordPress can tell when a request is encrypted, prove it at five minutes, then move to six months. Leave subdomains out unless you know each one, and leave preload alone.
BetterShield is free on WordPress.org. The HSTS guide covers every option, the WP-CLI flags and each line the row can show.