HTTPS redirect

A user types example.com in the address bar. The browser assumes HTTP and connects to port 80. Your server needs to say: actually, I live on HTTPS, come back over there.

That is the HTTPS redirect. It is a one-line server config and the reason every link you paste into chat eventually resolves to an https:// page even when it was typed as http://.

Why redirect

Without a redirect, anyone who types the bare hostname lands on plaintext HTTP. You can ship a perfect TLS config at https://example.com, but if http://example.com returns a 200 with content, a meaningful share of your traffic still hits you over TCP/80 and gets an unencrypted response. Read-only from the user's side, but every cookie in that request leaks, every page they visit is visible to the network, every response can be modified.

The flow

Here is the minimum exchange. Watch the tone of the first two messages versus the last two.

Two requests, one userhttp://example.com/
  1. browserplaintext
    GET http://example.com/
  2. server :80plaintext
    HTTP/1.1 301 Moved Permanently
    Location: https://example.com/
  3. browserencrypted
    GET https://example.com/
  4. server :443encrypted
    HTTP/1.1 200 OK
    Strict-Transport-Security: max-age=31536000; includeSubDomains
The first request is still plaintext. An attacker on the network sees it, and can hijack before the 301 arrives. HSTS on the HTTPS response closes the gap on every subsequent visit; preload closes it on the first visit.

The first round trip is still plaintext. An attacker on the network between the browser and the server can answer the HTTP request themselves, serving a fake page before the real 301 arrives. That is SSL stripping. The redirect does not prevent it on the first visit. HSTS closes the gap for every subsequent visit; HSTS preload closes it on the first visit too.

Which status code

All the 3xx codes can redirect. Only a few make sense for HTTP-to-HTTPS.

Redirect status codesRFC 9110 §15.4
301Moved Permanentlypermanentmay change
308Permanent Redirectpermanentpreserved
302Foundtemporarymay change
307Temporary Redirecttemporarypreserved
For HTTP to HTTPS, use 301 on websites (SEO consolidation) and 308 on APIs (method preservation). 302 and 307 are temporary by definition, not what you want.

For a website, 301 is the right answer: permanent, SEO-friendly, and the method change on the follow-up is fine because the user was making a GET anyway. For an API, 308 is the right answer: method-preserving matters if a caller POSTed to http://api.example.com by accident. Never use 302 or 307 for HTTPS upgrade: both are temporary, and search engines will not consolidate signals.

Apex vs www

Pick one canonical hostname and redirect the other to it. Two common patterns:

  • Apex-canonical: www.example.com 301s to example.com. Cleaner URLs, modern default.
  • www-canonical: example.com 301s to www.example.com. Traditional, plays well with CDNs that do not support apex CNAMEs.

The redirect chain must end in one canonical URL. A chain of http://example.comhttps://example.comhttps://www.example.com costs two extra round trips on every first visit. Collapse to one hop: http://example.comhttps://www.example.com directly.

Pair with HSTS

The redirect alone is not enough. On every subsequent visit, the browser remembers it saw HTTPS and should go straight there, but only if you told it. The HTTPS response must include:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Now the browser never touches port 80 for this host again until max-age expires. See the HSTS article for the full rollout path.

Common mistakes

no redirect at all

HTTPS works at https://example.com, but plain example.com still returns a 200 over HTTP. Every user who types the bare hostname is on plaintext.

redirect with a broken cert on the target

301 to https://example.com, cert expired, user stuck at a "not secure" browser warning with no way forward. Worse than no redirect.

302 instead of 301

Search engines treat 302 as temporary and do not consolidate backlinks. Traffic from HTTP referrers keeps being treated as separate from HTTPS.

multi-hop chain

http://example.comhttp://www.example.comhttps://www.example.com. Two round trips before TLS kicks in, first hop still plaintext. Collapse to one 301 straight to the canonical HTTPS URL.

redirect in an HTML meta refresh

Delivers the HTML over plaintext first, then asks the browser to navigate. Every cookie leaks on that first response. Use a 301 at the HTTP layer.


Check whether port 80 returns a 301 to HTTPS, whether the chain is a single hop, and whether HSTS follows on the HTTPS response: scan your domain.