Fix WordPress redirect loop (.htaccess)

Seeing “Request exceeded the limit of 10 internal redirects” or “ERR_TOO_MANY_REDIRECTS”? That usually means conflicting rules in .htaccess or mismatched WordPress URLs. Follow this safe sequence to restore the default rules, confirm home/siteurl, and add clean HTTPS/WWW redirects without creating loops, even behind Cloudflare or a reverse proxy.

What’s the quickest safe fix for a WordPress redirect loop?

Quick reset (safe order)

  1. Back up & reset .htaccess: rename .htaccess to .htaccess.bak, then visit Settings → Permalinks and click Save to regenerate default rules. This writes the official WordPress rewrite block.
  2. Verify WordPress URLs: in Settings → General, make sure WordPress Address (URL) and Site Address (URL) are correct (usually identical and including https://). You can also check/update via WP‑CLI:
    wp option get home
    wp option get siteurl
    wp option update home 'https://example.com'
    wp option update siteurl 'https://example.com'

    These govern how WordPress generates links.

  3. Clear caches: purge plugin/page cache and any CDN after changes.

If the site loads now, add any HTTPS/WWW redirect carefully (see the next answer) so you don’t reintroduce a loop.

What should the default .htaccess look like?

Default WordPress .htaccess (Apache)

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Regenerate this block by saving Settings → Permalinks if needed.

How do I force HTTPS and/or WWW without creating another loop?

Canonical HTTPS/WWW rules (place above the WordPress block)

Choose ONE of the following and replace example.com with your domain. Put it above “# BEGIN WordPress”.

Force HTTPS (keep host as is)

RewriteEngine On
# If behind a proxy that sets X-Forwarded-Proto, also check it:
RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Force HTTPS + non‑www

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Force HTTPS + www

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

Why the proxy condition? If you’re on Cloudflare Flexible SSL or any SSL‑terminating proxy, the origin may think the request is HTTP and keep redirecting. Checking X‑Forwarded‑Proto, or using Cloudflare’s Full/Full (strict) mode, prevents loops.

I use Cloudflare and just switched on SSL. Now I get loops. What should I change?

Cloudflare loop fix

  1. In Cloudflare → SSL/TLS, switch encryption from Flexible to Full (or Full (strict)) so Cloudflare connects to your origin via HTTPS.
  2. Remove duplicate HTTPS rules at the origin (keep either origin redirects or Cloudflare’s Always Use HTTPS, not both).
  3. Optionally install Cloudflare’s WordPress plugin and enable Automatic HTTPS rewrites to reduce mixed‑content issues.

We’re behind a load balancer/reverse proxy. Login works over HTTP but loops on HTTPS.

Reverse proxy/load balancer (HTTPS detection)

Tell WordPress it’s actually being requested via HTTPS when a proxy sets X‑Forwarded‑Proto:

// Add near the top of wp-config.php, before "require_once ABSPATH . 'wp-settings.php';"
if ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
    $_SERVER['HTTPS'] = 'on';
}

This prevents is_ssl() mis‑detecting the scheme and causing redirect loops. WooCommerce/WordPress dev docs recommend this approach for proxied sites.

What if WordPress is installed in /wordpress but I want the site at the domain root?

Subdirectory installs (common loop source)

  1. Make sure Site Address (URL) is the root (e.g., https://example.com) and WordPress Address (URL) points to the subdir (e.g., https://example.com/wordpress) if you’re intentionally running that layout.
  2. Use the default WordPress rewrite block at the domain root (see the default snippet above). Avoid stacking multiple WordPress blocks for both / and /wordpress—that can loop.

How do I prove there’s a loop and where it’s happening?

Confirm the loop (CLI & browser)

  • cURL: follow redirects and inspect status/location:
    curl -I -L https://example.com
  • DevTools: open Network tab, reload, and watch the 301/302 chain (often http↔https or www↔non‑www bouncing).

When you see alternating targets, look for duplicate HTTPS or host‑canonical rules in .htaccess or proxy/CDN settings. (cURL -L follows redirects.)

Any other common pitfalls?

Other things that commonly cause loops

  • Two HTTPS enforcers at once (e.g., host panel “Force HTTPS” + .htaccess rule + CDN rule).
  • Mismatched URLs (admin uses https://www, front uses https://non‑www) — align both home and siteurl.
  • Plugin rewrite blocks left behind in .htaccess after uninstall—compare against the default block and remove or re‑add the plugin.
  • Cache (page/object/CDN) serving old redirects—purge after every change.

Need human WordPress help?

WP Assistant is a free tool created by Atiba Software, a WordPress design and development company located in Nashville, TN. If you need more personalized WordPress assistance let us know, and we’ll get back to you ASAP!