HTTP to HTTPS Redirect via .htaccess
Make sure your SSL certificate is already installed on the domain before setting up the redirect — without it, the redirect will send visitors to a certificate error page instead of a working site. See the article on enabling free SSL to check.
Universal Redirect
Open the .htaccess file in your site root and add:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Status code 301 means "moved permanently" — that is exactly what an HTTPS redirect needs, so search engines and browsers remember the new address instead of caching the old HTTP version. A temporary 302 redirect is the wrong tool here.
Redirect from www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
Redirect in WordPress
In WordPress, open Settings → General and set both addresses to https://. WordPress will add the required rules itself and rewrite internal links in the database to the new scheme.
Combining www and HTTPS in One Rule
If the HTTPS redirect and the www redirect are set up as separate blocks, a visitor coming from http://www.yourdomain.com goes through two hops in a row: first to https://www.yourdomain.com, then to https://yourdomain.com. Every extra hop is an extra round trip to the server and a small hit to load speed. It is better to combine both conditions into a single rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC,OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://yourdomain.com/$1 [L,R=301]
This way a visitor lands on the final address in a single step, no matter which variant they typed.
Real Errors When Setting Up a Redirect
The most common problem is an infinite redirect loop, which the browser shows as:
ERR_TOO_MANY_REDIRECTS
It happens when the site sits behind Cloudflare or another proxy in "Flexible" SSL mode: Cloudflare forwards the request to the origin server over HTTP, .htaccess sees HTTP and redirects to HTTPS, Cloudflare opens a new HTTP connection — and the loop repeats forever. The fix is to switch Cloudflare's SSL mode to "Full" or "Full (strict)", or to check the X-Forwarded-Proto header instead of the HTTPS variable directly. A second error shows up if the rule is added twice in different .htaccess files (the root one and one in a subdirectory):
Internal Server Error
500 - RewriteRule: bad flag delimiters
It signals a syntax error in the rule — most often an extra space or an unescaped special character in the regular expression.
Redirect Methods Compared
| Method | Configured where | Risk of conflicting with Cloudflare |
|---|---|---|
| .htaccess RewriteRule | A file on the hosting account | High in Flexible mode |
| WordPress settings | The CMS admin panel | Medium, depends on the caching plugin |
| Always Use HTTPS in Cloudflare | The Cloudflare dashboard | Low, redirects before the origin server |
When a .htaccess Redirect Is Not the Right Fit
- The site sits behind Cloudflare or another CDN — it is better to enable the redirect at the proxy level (Always Use HTTPS) rather than duplicate it in .htaccess
- The site is static and served without Apache (for example, through Nginx or a CDN host) — .htaccess directives simply are not read there
- You need a conditional redirect (by country, device, language) — the standard HTTPS redirect is not built for that, and separate application logic is needed
- The site's browsers aggressively cache redirects — an old rule can "stick" even after .htaccess is fixed
The Next Step: HSTS
An HTTPS redirect only protects visitors who already sent at least one HTTP request — that very first request is still exposed to interception. To make the browser reach the site over HTTPS immediately, without a single HTTP request, add the HSTS header to .htaccess:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Enable this header only after the HTTPS redirect has been tested and works reliably across every subdomain — browsers remember HSTS for the stated period (a year in this example), and there is no simple way to undo it early just by disabling the redirect.
Checking the Redirect
- Run
curl -I http://yourdomain.com— the response should include anHTTP/1.1 301status and aLocation: https://yourdomain.com/header - Check the www variant too:
curl -I http://www.yourdomain.com - Use the redirect-checker.org service to inspect the full redirect chain — if it is longer than one hop, search engines lose part of the page's ranking weight at every step
If the site runs through Cloudflare, the encryption modes and how they affect redirects are covered in the article on Cloudflare SSL/TLS modes. General .htaccess rules, including protection against direct file access, are in the article .htaccess: redirect and optimization rules.