← Back to Blog

Cloudflare SSL Too Many Redirects: Fix ERR_TOO_MANY_REDIRECTS in Minutes

You just enabled Cloudflare on your domain. You visit your site and Chrome hits you with ERR_TOO_MANY_REDIRECTS. Every page is broken. You clear cookies, try a different browser, switch to incognito. Nothing works. The problem is almost always a single setting in your Cloudflare dashboard, and you can fix it in about 90 seconds.

TL;DR: The 90-Second Fix

1. Go to Cloudflare Dashboard, select your domain, then navigate to SSL/TLS.

2. Set SSL mode to "Full (Strict)". If your origin has no SSL cert, set to "Full".

3. Never use "Flexible" if your origin forces HTTPS. That is the number one cause of redirect loops.

4. Remove any duplicate HTTPS redirect rules from your .htaccess, nginx config, or CMS settings.

5. Clear your browser cache and test. The loop should be gone.

The Redirect Loop Explained

Before we fix anything, you need to understand what is actually happening. A redirect loop means your browser is bouncing back and forth between two URLs and never landing anywhere. After about 20 bounces, the browser gives up and shows ERR_TOO_MANY_REDIRECTS.

Here is what the loop looks like when Cloudflare SSL is set to "Flexible" and your origin server forces HTTPS:

Browser requests https://yourdomain.com

Cloudflare terminates SSL, connects to origin over HTTP (port 80)

Origin sees HTTP request, sends 301 redirect to HTTPS

Cloudflare receives redirect, connects to origin over HTTP (port 80) again

Origin sends 301 redirect to HTTPS again

... infinite loop ... ERR_TOO_MANY_REDIRECTS

The key insight is that Cloudflare Flexible mode always connects to your origin over plain HTTP, regardless of whether the visitor used HTTPS. Your origin has no idea the visitor's connection is encrypted. It just sees an HTTP request and does what it was told to do: redirect to HTTPS. But Cloudflare keeps sending HTTP. Round and round it goes.

Step 1: Check Your Cloudflare SSL Mode

The SSL/TLS mode in Cloudflare controls how traffic flows between Cloudflare's edge servers and your origin. This single setting is responsible for the vast majority of redirect loops. Let me walk you through all four options so you understand exactly what each one does.

Off (Not Recommended)

No encryption at all. Traffic from the visitor to Cloudflare and from Cloudflare to your origin is plain HTTP. Cloudflare will not serve your site over HTTPS. If someone types https:// in the address bar, they get an error. There is almost no reason to use this setting in 2026.

Flexible

Encrypts traffic between the visitor and Cloudflare, but sends plain HTTP to your origin. This is the setting that causes redirect loops. The visitor sees a padlock in their browser, but the connection between Cloudflare and your server is completely unencrypted. Cloudflare created this mode for origins that have no SSL certificate at all and cannot install one. It was never meant to be a permanent solution.

Full

Encrypts traffic end to end. Cloudflare connects to your origin over HTTPS but does not validate the origin certificate. This means your origin can use a self-signed certificate, an expired certificate, or even a certificate for a different domain. Cloudflare will accept it without complaint. This is a good middle ground if you have some kind of certificate on your origin but it is not properly signed by a trusted CA.

Full (Strict)

Encrypts traffic end to end and validates the origin certificate. Cloudflare will only connect to your origin if it presents a valid, non-expired certificate signed by a trusted CA or by Cloudflare's own origin CA. This is the recommended setting for production sites. It provides genuine end-to-end encryption with no room for man-in-the-middle attacks between Cloudflare and your origin.

If you take one thing from this article, let it be this: set your SSL mode to Full (Strict) and install a Cloudflare origin certificate. That single change prevents redirect loops, secures the connection to your origin, and costs nothing.

Step 2: The Flexible Mode Trap

Flexible mode is the default on many Cloudflare setups, and it is a trap. Here is why it causes so many problems.

When you enable Cloudflare with Flexible SSL, Cloudflare handles the HTTPS connection from the visitor. But it talks to your origin over HTTP on port 80. Your origin server has no idea that the original request was HTTPS. It just sees a plain HTTP request coming in.

Now, if your origin has any kind of HTTPS redirect rule (and most do), it will try to redirect that HTTP request to HTTPS. Cloudflare receives the redirect, but because it is in Flexible mode, it connects over HTTP again. Your origin redirects again. And again. And again.

The frustrating part is that this can work fine for weeks or months if you set up Cloudflare before adding HTTPS redirects to your origin. Then one day you install an SSL certificate on your origin, or a plugin adds a redirect rule, or you paste a common .htaccess snippet from Stack Overflow. Suddenly your entire site is down with a redirect loop, and you have no idea what changed.

How to check if Flexible mode is the problem

# Check what your origin does when hit with plain HTTP
curl -sI -o /dev/null -w "%{http_code} %{redirect_url}" http://YOUR_ORIGIN_IP \
  -H "Host: yourdomain.com"

# If this returns "301 https://yourdomain.com/" then your origin
# redirects HTTP to HTTPS. Combined with Flexible mode, that is your loop.

Step 3: Fix for Apache (.htaccess Redirect Conflicts)

Apache is the most common web server I see with redirect loop issues. The problem is usually a rewrite rule in .htaccess that forces HTTPS without checking whether the request already came through Cloudflare's proxy.

The problematic rule

This is the rule you will find in thousands of .htaccess files. It works perfectly without Cloudflare but causes an infinite loop behind it:

# This causes a redirect loop behind Cloudflare Flexible mode
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

The issue is that %{HTTPS} is always "off" when Cloudflare connects over HTTP, even though the visitor is using HTTPS.

Option A: Fix it at the Cloudflare level (recommended)

The cleanest fix is to switch your Cloudflare SSL mode to Full or Full (Strict). When Cloudflare connects to your origin over HTTPS, the %{HTTPS} variable is "on" and the rewrite rule does not fire. No code changes needed.

Option B: Fix the .htaccess rule to respect Cloudflare

If you must stay on Flexible mode (which I strongly advise against), you can modify the redirect rule to check the X-Forwarded-Proto header that Cloudflare sends:

# Safe HTTPS redirect that works behind Cloudflare
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

This rule checks both %{HTTPS} and the X-Forwarded-Proto header. If either indicates HTTPS, the redirect is skipped. Cloudflare always sends X-Forwarded-Proto: https when the visitor connected over HTTPS, so the loop is broken.

Pro Tip: After changing .htaccess rules, always clear your browser cache completely. Browsers cache 301 redirects aggressively. If you test in the same browser without clearing, you will keep seeing the old cached redirect even after fixing the rule. Use incognito mode or curl -I to test changes.

Step 4: Fix for Nginx (Return 301 Conflicts)

Nginx redirect loops behind Cloudflare work the same way as Apache, but the fix lives in your server block instead of .htaccess.

The problematic config

# This causes a redirect loop behind Cloudflare Flexible mode
server {
    listen 80;
    server_name yourdomain.com;
    return 301 https://$server_name$request_uri;
}

Every request on port 80 gets redirected to HTTPS. Cloudflare Flexible mode always connects on port 80. Loop.

Option A: Switch to Full or Full (Strict) (recommended)

Same as with Apache. Change your Cloudflare SSL mode so that Cloudflare connects over HTTPS. Your nginx HTTPS server block handles the request directly and the port 80 redirect never fires.

Option B: Check the X-Forwarded-Proto header

# Safe HTTPS redirect for Nginx behind Cloudflare
server {
    listen 80;
    server_name yourdomain.com;

    # Only redirect if the original visitor used HTTP
    if ($http_x_forwarded_proto != "https") {
        return 301 https://$server_name$request_uri;
    }

    # If X-Forwarded-Proto is https, serve the request normally
    root /var/www/html;
    index index.php index.html;

    # ... rest of your config
}

This checks whether the visitor's original connection was HTTPS before redirecting. If Cloudflare says the visitor used HTTPS (via the X-Forwarded-Proto header), nginx serves the request instead of redirecting.

Step 5: Fix for WordPress

WordPress is especially prone to redirect loops because HTTPS redirects can come from three different places at once: the web server, the WordPress database, and WordPress plugins. You need to check all three.

Check wp_options (siteurl and home)

WordPress stores your site URL in the database. If siteurl and home are set to https:// but your server is receiving HTTP from Cloudflare, WordPress will try to redirect every request to the HTTPS URL stored in the database.

# Check your WordPress URL settings via WP-CLI
wp option get siteurl
wp option get home

# If these return https:// URLs and you are on Flexible mode,
# that is part of your loop. Either:
# 1. Switch Cloudflare to Full/Full (Strict) (recommended)
# 2. Or set them to http:// (not recommended, breaks mixed content)

Check Really Simple SSL and similar plugins

The Really Simple SSL plugin (and similar plugins like WP Force SSL) adds its own HTTPS redirect logic on top of whatever your web server does. If your web server already redirects and the plugin also redirects, they can conflict.

If you are using Cloudflare Full (Strict) mode with a valid origin certificate, you do not need Really Simple SSL at all. Cloudflare handles the HTTPS termination. Deactivate the plugin and test. If your site loads fine without it, leave it deactivated. One less thing to break.

Add the Cloudflare detection snippet to wp-config.php

If you must use Flexible mode with WordPress (again, not recommended), add this to the top of your wp-config.php file, before the "That's all, stop editing!" line:

// Tell WordPress to trust Cloudflare's forwarded protocol
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

This tells WordPress that the request is HTTPS even though it arrived over HTTP from Cloudflare. WordPress stops trying to redirect because it thinks HTTPS is already active.

Step 6: Fix for Laravel

Laravel applications behind Cloudflare Flexible mode have the same redirect loop problem, but the fix involves Laravel's trusted proxy middleware.

Check APP_URL in .env

# In your .env file, make sure APP_URL uses https
APP_URL=https://yourdomain.com

# If APP_URL is http:// and Cloudflare forces HTTPS,
# or if APP_URL is https:// and your origin receives HTTP,
# you get redirect loops.

Configure TrustedProxy middleware

Laravel needs to know that Cloudflare is a trusted proxy so it reads the X-Forwarded-Proto header correctly. In Laravel 10 and 11, edit app/Http/Middleware/TrustProxies.php:

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    // Trust all proxies (Cloudflare IPs rotate frequently)
    protected $proxies = '*';

    // Trust all forwarded headers from the proxy
    protected $headers =
        Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB;
}

Setting $proxies = '*' tells Laravel to trust the X-Forwarded-Proto header from any IP. Since Cloudflare's IP ranges change, wildcarding is the practical choice. Laravel will now correctly detect HTTPS requests coming through Cloudflare and stop issuing unnecessary redirects.

Is Your SSL Certificate Properly Configured?

Redirect loops are just one symptom of SSL misconfiguration. An incomplete certificate chain or expired cert can cause different but equally frustrating errors. Check your full SSL setup in seconds.

Check Your SSL Free

Step 7: Install a Cloudflare Origin Certificate

The permanent fix for all of this is to install a proper SSL certificate on your origin and set Cloudflare to Full (Strict). Cloudflare gives you a free origin certificate that lasts up to 15 years. Here is how to set it up.

Generate the origin certificate

  1. Go to Cloudflare Dashboard, select your domain
  2. Navigate to SSL/TLS, then Origin Server
  3. Click Create Certificate
  4. Choose "Let Cloudflare generate a private key and a CSR"
  5. Add your domain and wildcard: yourdomain.com and *.yourdomain.com
  6. Set validity to 15 years
  7. Click Create. Copy the Origin Certificate and Private Key

Install on Apache

# Save the certificate and key
sudo nano /etc/ssl/cloudflare-origin.pem    # Paste the certificate
sudo nano /etc/ssl/cloudflare-origin.key    # Paste the private key

# Set permissions
sudo chmod 644 /etc/ssl/cloudflare-origin.pem
sudo chmod 600 /etc/ssl/cloudflare-origin.key

# Update your Apache virtual host
<VirtualHost *:443>
    ServerName yourdomain.com
    SSLEngine on
    SSLCertificateFile /etc/ssl/cloudflare-origin.pem
    SSLCertificateKeyFile /etc/ssl/cloudflare-origin.key

    # ... rest of your config
</VirtualHost>

# Test and restart
sudo apachectl configtest
sudo systemctl restart apache2

Install on Nginx

# Save the certificate and key
sudo nano /etc/ssl/cloudflare-origin.pem    # Paste the certificate
sudo nano /etc/ssl/cloudflare-origin.key    # Paste the private key

# Set permissions
sudo chmod 644 /etc/ssl/cloudflare-origin.pem
sudo chmod 600 /etc/ssl/cloudflare-origin.key

# Update your Nginx server block
server {
    listen 443 ssl;
    server_name yourdomain.com;
    ssl_certificate /etc/ssl/cloudflare-origin.pem;
    ssl_certificate_key /etc/ssl/cloudflare-origin.key;

    # ... rest of your config
}

# Test and restart
sudo nginx -t
sudo systemctl restart nginx

Once the origin certificate is installed, go back to Cloudflare and set your SSL mode to Full (Strict). Cloudflare now connects to your origin over HTTPS, your origin sees HTTPS, no redirect is triggered, and the loop is gone forever.

Important note: Cloudflare origin certificates are only trusted by Cloudflare itself, not by browsers directly. If someone bypasses Cloudflare and hits your origin IP directly, their browser will show a certificate warning. That is expected and actually a good thing. It means only traffic through Cloudflare works smoothly, which is what you want. For more on certificate chain issues, see our guide on fixing incomplete SSL certificate chains.

Pro Tip: The "Always Use HTTPS" page rule trap. Cloudflare has a setting called "Always Use HTTPS" (under SSL/TLS, then Edge Certificates, or as a Page Rule). This tells Cloudflare to redirect all HTTP requests to HTTPS at the edge, before they reach your origin. This is fine on its own. But if your SSL mode is Flexible and your origin also forces HTTPS, the combination creates a loop. Always Use HTTPS redirects the visitor to HTTPS, Cloudflare connects to origin over HTTP (because Flexible), origin redirects to HTTPS, Cloudflare connects over HTTP again. Fix: switch SSL mode to Full or Full (Strict). The Always Use HTTPS rule then works perfectly because Cloudflare connects to your origin over HTTPS.

SSL Mode Comparison Table

Here is a quick reference for when to use each SSL mode and what behavior to expect.

SSL Mode Visitor to Cloudflare Cloudflare to Origin Origin Cert Required? When to Use
Off HTTP only HTTP only No Never. There is no valid reason in 2026.
Flexible HTTPS HTTP (port 80) No Only if your origin cannot install any cert. Causes redirect loops if origin forces HTTPS.
Full HTTPS HTTPS (no validation) Any cert (even self-signed) Origin has a certificate but it is self-signed or expired. Temporary use only.
Full (Strict) HTTPS HTTPS (validated) Valid cert (CA-signed or Cloudflare origin) Production sites. Always use this when possible. Free with Cloudflare origin cert.

Common Mistakes That Cause Redirect Loops

  1. Using Flexible mode with an origin that forces HTTPS. This is the number one cause. Cloudflare sends HTTP, the origin redirects to HTTPS, loop. Fix: switch to Full (Strict).
  2. Stacking multiple redirect rules. Your .htaccess redirects HTTP to HTTPS. Your CMS also redirects. A WordPress plugin also redirects. A Cloudflare page rule also redirects. Each one fires independently, and they can chain into a loop. Pick one place to handle the redirect and remove all others.
  3. Forgetting to clear the browser cache after fixing. Browsers cache 301 redirects for a long time. You fix the server config but your browser keeps following the old cached redirect. Always test in incognito or clear your cache completely.
  4. Enabling "Always Use HTTPS" with Flexible SSL mode. This combination guarantees a loop. Always Use HTTPS forces HTTPS on the edge. Flexible mode connects to origin over HTTP. Origin redirects to HTTPS. Loop. Either disable the Always Use HTTPS rule or switch to Full/Full (Strict).
  5. Mixed www and non-www redirects conflicting with HTTPS redirects. Your server redirects http://yourdomain.com to https://www.yourdomain.com. But another rule redirects www back to the bare domain. HTTP to HTTPS to www to non-www to HTTPS to www. Loop. Consolidate all redirects into a single rule that handles both www/non-www and HTTP/HTTPS in one step.
  6. Not setting the Cloudflare SSL mode per subdomain. You set your main domain to Full (Strict) but forgot that app.yourdomain.com is on a different origin with no certificate. The fix works for the main domain but the subdomain loops. Use Cloudflare Configuration Rules to set SSL mode per hostname if your subdomains have different certificate situations.

Frequently Asked Questions

Why does Cloudflare Flexible SSL cause a redirect loop?

Flexible mode sends traffic from Cloudflare to your origin over plain HTTP on port 80. If your origin has an HTTPS redirect rule (in .htaccess, nginx config, or your CMS), it sends a 301 back to the HTTPS version. Cloudflare receives that redirect, connects to your origin over HTTP again (because Flexible mode always uses HTTP to the origin), and the origin redirects again. This creates an infinite loop that never resolves. The fix is to switch to Full or Full (Strict) mode so Cloudflare connects to your origin over HTTPS. No redirect is triggered because the request is already HTTPS.

Do I need a paid SSL certificate to use Cloudflare Full (Strict) mode?

No. Cloudflare provides free origin certificates that are valid for up to 15 years. These certificates are trusted by Cloudflare but not by browsers directly. Since all browser traffic goes through Cloudflare anyway, this is perfectly fine. Go to SSL/TLS, then Origin Server, then Create Certificate. Install it on your origin and set SSL mode to Full (Strict). You pay nothing. Alternatively, you can use a free Let's Encrypt certificate, which is also trusted by Cloudflare and by browsers directly. Either option works for Full (Strict) mode.

I switched to Full (Strict) but still get redirect loops. What else could cause this?

Check three things. First, look for an "Always Use HTTPS" page rule or redirect rule in Cloudflare that might be conflicting with another redirect rule. Second, check your origin for duplicate HTTPS redirect rules in both your web server config and your application (WordPress siteurl/home, Laravel APP_URL, or plugin-level redirects). If both the web server and the app redirect, they can chain. Third, make sure your origin certificate is valid and not expired. An invalid cert on Full (Strict) causes a 526 error, not a redirect loop, but an expired cert on Full mode (without Strict) can cause unexpected behavior. Use our SSL Checker to verify the full certificate chain on your origin server.

Check Your Full Attack Surface

SSL redirects are just one piece of the puzzle. Exposed .env files, missing security headers, and DNS misconfigurations can leak information that attackers exploit even with Cloudflare in front. Run a free scan to check everything.

Run Free Security Scan

The Bottom Line

ERR_TOO_MANY_REDIRECTS behind Cloudflare is almost always caused by one thing: the SSL mode is set to Flexible while your origin forces HTTPS. The fix is straightforward. Switch to Full (Strict), install a free Cloudflare origin certificate, and remove duplicate HTTPS redirect rules from your origin. Total time: 5 to 10 minutes.

If you have already fixed the SSL mode and still see loops, work through the checklist: check your .htaccess or nginx config for redirect rules, check your CMS settings (WordPress siteurl/home, Laravel APP_URL), check for plugins that force HTTPS, and check for conflicting Cloudflare page rules. One of those will be the culprit.

The broader lesson here is that every proxy layer between the visitor and your origin server can change how your application sees the request. Cloudflare, load balancers, reverse proxies, and CDNs all terminate and re-establish connections. If your application does not account for that, redirects, headers, and protocol detection break in subtle ways. Always configure your application to trust the proxy headers (X-Forwarded-Proto, X-Forwarded-For) and always use end-to-end encryption when possible.

Related tools: SSL Checker, Exposure Checker, DNS Lookup, HTTP Status Codes Reference, and 70+ more free tools.

Related reading: Cloudflare WAF 403 Forbidden Fix, Fix Incomplete SSL Certificate Chain.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic platforms behind Cloudflare, and building zero-knowledge security tools. Read more about the author.