---
title: "Your site runs HTTPS. Why is the first request still exposed?"
description: "HSTS is a header that tells the browser to open your site over HTTPS only, even when someone types http. Start with one day, check every subdomain, then raise it to two years."
url: https://ihsanalapsi.dev/articles/hsts-strict-transport-security
lang: en
date: 2026-11-03
updated: 2026-11-03
tags: ["App security", "Web development"]
author: Ihsan Alapsi (إحسان العبسي)
---
# Your site runs HTTPS. Why is the first request still exposed?

You type `example.com` in the browser without `https://`, and your site has a valid certificate and a redirect to HTTPS. Even so, the first request goes out over plain http, and the redirect comes after it. By the end of this article you will know how to close that request with one header, and in what order to turn it on so you don't lock out a subdomain that still runs on http.

## What is HSTS?

HSTS is a header your site sends over HTTPS that tells the browser this site opens over HTTPS only, for a set number of seconds.

Its full name is HTTP Strict Transport Security, and it arrives as one line in the response:

```
Strict-Transport-Security: max-age=86400; includeSubDomains
```

According to [MDN's page on the header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security), `max-age` is the number of seconds the browser remembers that the site opens over HTTPS only, and `includeSubDomains` extends the same rule to every subdomain. The browser ignores the header when it arrives over http, so that someone sitting in the middle can't plant it for a site with no HTTPS, or cut its time short.

## What does HSTS protect you from?

HSTS protects the visitor from an attacker in the middle of the network, on the requests that would have gone out over http.

[OWASP's HSTS cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html) names three cases:

- The visitor types the address with `http://` or opens a bookmark with http in it, and there is a man-in-the-middle attacker.
- Your site is meant to be HTTPS only and has http links by mistake: the browser upgrades them to HTTPS by itself.
- The certificate is invalid: HSTS does not let the visitor override the certificate message and go on.

The third case matters a lot on a café or airport network. If someone shows a forged certificate for your site, the visitor finds no button to go on, so the forged page does not open for them.

## Why isn't the server redirect enough?

The redirect from http to HTTPS on the server works after the exposed request has already arrived, while HSTS makes the browser not send that request at all.

Once the browser sees the header, it keeps the policy for the time in `max-age`. On the next visit, if you type `http://`, the browser switches it to `https://` before the request leaves your device, so there is nothing on the network for anyone to answer.

One door stays open: the first visit. The same MDN page says the weakness of HSTS is that it does not take effect before the first secure connection to the site, and that preloading eases this problem. The preload list is a list of domains kept by the major browsers (such as Chromium, Edge and Firefox), so the browser knows your site is HTTPS only before it ever visits. That list is not part of the HSTS specification itself.

## In what order do you turn on HSTS without locking out a subdomain?

You turn on HSTS safely when you start with a short time and raise it only after you have checked that every subdomain runs on HTTPS.

The risk here comes from you, not the attacker: with `includeSubDomains`, any subdomain served over http only stops working for visitors for the whole time you set. Go in this order:

1. List all your subdomains: the site, the API, the admin panel, email, and any old one you forgot. Open each one with `https://`; it has to open with a valid certificate.
2. Send the header for one day, like the rollout example in the OWASP cheat sheet: `max-age=86400; includeSubDomains`. If a subdomain you forgot shows up, it stops for one day only.
3. After a while with no complaints, raise it to two years: `max-age=63072000; includeSubDomains`. 63072000 seconds is two years, the value in the OWASP examples.
4. Leave preload for last. With `preload`, MDN asks for a `max-age` of at least 31536000 (one year) together with `includeSubDomains`, and OWASP warns that sending `preload` can have permanent consequences.

If you need to back out: send `max-age=0` over HTTPS. The browser drops the policy only when it gets that response over a secure connection, and there is no way to turn it off over http.

## How do you check that the header arrives?

You check that the HSTS header arrives by requesting the page over HTTPS and looking for it in the response.

```bash
curl -sI https://example.com | grep -i strict-transport-security
```

Replace `example.com` with your domain, and try an inner page and a subdomain too, not only the home page. If no line comes back, the header does not reach that address. And don't test over `http://`: the browser ignores the header there, so having it on http protects nobody.

If you are reviewing the security headers on your site, go on to [checking your session cookie](/articles/session-cookie-flags-check). OWASP says that leaving out `includeSubDomains` allows cookie attacks from subdomains, and that the `secure` flag on every cookie stops some of them but not all, so the two work together.

## Where do you start now?

Start with the list of subdomains: it decides whether `includeSubDomains` protects your site or locks part of it. Then send the header for one day, check it with `curl`, and raise the time once you are sure.

If your site loads scripts from a CDN, HSTS protects the connection only, not the file's content: for that you need [locking scripts with Subresource Integrity](/articles/subresource-integrity-cdn-scripts). And if you want someone to go through all your site's settings before someone else finds a gap, that is the work of [Muhassan](/muhassan).

What is the last subdomain you opened, and does it still open over HTTPS?

## FAQ

**Does HSTS replace the http to https redirect on the server?**

No. The browser does not know the policy until it gets the header over a secure connection, so the first request still goes over http. The redirect takes the visitor to HTTPS that time, and after that HSTS makes the browser go to HTTPS by itself.

**How do I turn HSTS off after I enable it?**

Send the header with max-age=0 over HTTPS. The browser drops the policy only when it requests the site over HTTPS and gets that response, and there is no way to turn it off over http.

**Do I have to put my site on the preload list?**

No. The list closes the first-visit gap, but OWASP warns that sending preload can have permanent consequences, so join it only when every subdomain you have runs on HTTPS.

**Does HSTS protect the session cookie?**

It helps, but not on its own. OWASP says that leaving out includeSubDomains allows cookie attacks from subdomains, and that the secure flag on every cookie stops some of them, not all.
