# How to force HTTPS on your website

> The redirect rule that sends every visitor to the secure version, and how to avoid a redirect loop while you do it.

Source: https://cwp.sg/tutorials/force-https/  
Author: Ben Johnson  
Last verified: 2026-09-21

**In short:** - A single line in `.htaccess` redirects HTTP to HTTPS for most sites: check `%{HTTPS}` is off and redirect with `R=301`. - If you use a proxy or CDN like Cloudflare, check `X-Forwarded-Proto` instead, or you will get a redirect loop. - Redirects alone do not fix mixed content warnings — update your site URL setting and change all links to HTTPS. - HSTS is optional and risky: do not enable it until the redirect works and you are sure you will keep the certificate.

If you have a working SSL certificate and your site still loads on plain HTTP, you need a redirect rule. One line in `.htaccess` does it for most sites. A different check is needed if you sit behind a proxy or CDN, because the normal method causes a redirect loop.

You need a certificate first. If you do not have one yet, follow the [free SSL tutorial](/tutorials/enable-free-ssl/) to get one from Let's Encrypt. The redirect will not work without it.

## The standard redirect rule

Create or edit `.htaccess` in your document root (usually `public_html`). Add these lines at the top, before any existing rules.

```
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
```

What each line does:

- `RewriteEngine On` — turns the rewrite engine on. This is required for any rule to work.
- `RewriteCond %{HTTPS} off` — checks that the connection is using plain HTTP. The rule only runs when this condition is true.
- `RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]` — captures the whole URL path and redirects it to the same address on HTTPS. `R=301` makes it a permanent redirect. `L` tells Apache to stop processing further rules on this pass.

Test it by visiting `http://yoursite.com/anything`. You should land on `https://yoursite.com/anything`.

If you are uncomfortable editing the file by hand, use the [.htaccess generator](/tools/htaccess-generator/) and paste the output.

## Behind a proxy or CDN: the infinite loop

If your site runs behind Cloudflare, a reverse proxy, or a load balancer, the connection between the visitor and the proxy is HTTPS, but the connection between the proxy and your server is HTTP. Apache sees `%{HTTPS}` as `off` every time, so it redirects to HTTPS, the proxy forwards that as HTTP again, and the loop runs forever. You get an `ERR_TOO_MANY_REDIRECTS` error.

The fix is to check the header that the proxy sends. Most proxies send `X-Forwarded-Proto` or `X-Forwarded-Scheme` with the value `https` when the original visitor used HTTPS.

```
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
```

The difference is the second line: `RewriteCond %{HTTP:X-Forwarded-Proto} !https`. It checks the forwarded protocol instead of the direct connection. If the proxy does not send that header, it falls through to the second condition and behaves like the standard rule.

If your proxy uses a different header, replace `X-Forwarded-Proto` with the correct one. Cloudflare uses `CF-Visitor` in some configurations, but `X-Forwarded-Proto` is more universal.

## The redirect alone is not enough

A redirect makes visitors use HTTPS, but it does not fix links that point to HTTP. Your site can still show mixed content warnings if images, scripts, or stylesheets load over HTTP.

Check your site for the [mixed content error](/errors/mixed-content/) by looking in the browser console. Fix everything by using protocol-relative URLs (start with `//` instead of `http://`) or by changing every link to `https://` explicitly.

You also need to update your site URL setting in the control panel or CMS. WordPress users should go to Settings → General and change both the WordPress Address and Site Address to `https://yourdomain.com`. If you only change the URL, visitors who typed `http://` still hit the old address — that is what the redirect fixes. If you add only the redirect without updating the site URL, every internal link your CMS generates still points to HTTP. The two changes work together.

## What about HSTS?

HSTS (HTTP Strict Transport Security) tells browsers to never connect to your site over HTTP at all. It is optional and has a trap. If you enable it and later need to serve your site over HTTP for any reason, the browser will refuse. The browser remembers the setting for as long as the `max-age` below says — a year, in the example.

If you decide to use it, add this line after the redirect rule:

```
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
```

That sets a one-year expiry. Do not add this until you have confirmed the redirect works and you have no plans to remove the certificate.

## Fixing the HTTPS loop

The proxy rule is the one most people miss. If your redirect loops, check whether you are behind a proxy. The `%{HTTP:X-Forwarded-Proto}` condition fixes the loop. If you still get a loop after adding it, check which header your proxy sends. Cloudflare, for example, can be set to send `X-Forwarded-Proto` in the dashboard under Network → Proxy settings.

Once the rule is in place and your site URL is updated, test with the browser developer tools open. Confirm you see a 301 or 308 redirect for the first request, then a 200 for the HTTPS page. No loops, no mixed content warnings.

---

Content Website Platform (cwp.sg) operates the free hosting it writes about; see https://cwp.sg/about/ for the methodology and the commercial disclosure.
