"This page isn't working: example.com redirected you too many times" (Chrome's ERR_TOO_MANY_REDIRECTS) means the browser followed a chain of redirects that never reached a final page. On a site behind Cloudflare, the loop is almost always created by two systems each trying to enforce HTTPS or a hostname, and each undoing the other. This guide helps you identify which pair is fighting and gives the fix for each.
If your site runs WordPress, also read the WordPress too many redirects fix, which covers siteurl and plugin causes in more depth. For the general mechanics of redirects, see HTTP redirects: 301 vs 302.
Step 1: See the loop, do not guess
Browsers hide the chain. curl shows it.
curl -sIL --max-redirs 8 https://example.com/ | grep -iE "^(HTTP/|location|server|cf-ray)"
A loop looks like the same pair of URLs repeating:
HTTP/2 301
location: https://example.com/
HTTP/2 301
location: https://example.com/
Note two things: which status codes appear, and whether server: cloudflare and cf-ray show on every hop. The Redirect Checker and Redirect Debugger display the same chain in a table, and the CDN Detector confirms Cloudflare is in the path.
Now test whether the loop is at Cloudflare or at your origin by bypassing Cloudflare:
curl -sIL --max-redirs 8 --resolve example.com:443:ORIGIN_IP https://example.com/ | grep -iE "^(HTTP/|location)"
curl -sI --resolve example.com:80:ORIGIN_IP http://example.com/ | grep -iE "^(HTTP/|location)"
The second command is the key one. It reproduces what Flexible SSL does: an HTTP request to port 80 of the origin.
Cause 1: Flexible SSL plus an origin that forces HTTPS (the usual one)
How the loop forms:
- Visitor requests
https://example.com/. Cloudflare terminates TLS. - In Flexible mode, Cloudflare connects to your origin over plain HTTP.
- Your origin (Apache
RewriteRule, nginxreturn 301 https://..., a CMS "force SSL" option, or a hosting panel setting) answers: "redirect to HTTPS." - Cloudflare passes the redirect to the browser, which requests HTTPS again. Back to step 1.
If the test above shows the origin returning 301 to https://example.com/ on port 80, this is your problem.
Fix: install a valid certificate on the origin and change the SSL/TLS mode to Full (strict) (or Full if the certificate is self-signed). Cloudflare then talks HTTPS to the origin, which no longer redirects, and the loop ends. Setup details are in Cloudflare setup: DNS and SSL modes.
If you truly cannot install a certificate, the workaround is to stop the origin from redirecting HTTPS-forwarded traffic. Cloudflare sends an X-Forwarded-Proto header, and many apps can be told to trust it. Example for nginx:
# Only redirect if the original request was plain HTTP
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
And for Apache .htaccess:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Cloudflare also sends a CF-Visitor header containing the visitor's original scheme, which some apps can read. Prefer the real fix of using Full (strict) when possible.
Cause 2: Cloudflare redirect rules versus origin redirects
Cloudflare can redirect at the edge through several features: Always Use HTTPS, Redirect Rules, Bulk Redirects, and legacy Page Rules with "Forwarding URL." If one of these sends www to the apex while the origin sends the apex to www, they loop forever.
Check for opposing rules:
curl -sI https://example.com/ | grep -iE "^(location|server)"
curl -sI https://www.example.com/ | grep -iE "^(location|server)"
If the first redirects to www and the second redirects back to the apex, you have two canonical hostnames. Pick one and make every layer agree:
- Edge: one redirect rule from the non-canonical host to the canonical host.
- Origin: remove its own host redirect, or make it point to the same canonical host.
- CMS: set the site URL to the canonical host with
https://.
Edge redirects and origin redirects are easy to forget because they live in different dashboards. Search both when debugging. The legacy Page Rules and newer Redirect Rules can coexist, and a forgotten old rule can contradict a new one. Check the dashboard for rules on your zone and look for matching patterns.
Cause 3: CMS or application URL settings
An application that believes its address is http:// will redirect to what it thinks is correct, even if the visitor is on HTTPS.
- WordPress:
WordPress AddressandSite Addressin Settings, General, orWP_HOMEandWP_SITEURLinwp-config.php. If they sayhttp://while Cloudflare is Flexible, or the reverse, you loop. Behind a proxy you may also need:
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
- Laravel, Django, Rails and others: configure trusted proxies so the framework reads the forwarded scheme instead of the connection scheme. Typical settings are
TrustProxiesmiddleware in Laravel,SECURE_PROXY_SSL_HEADERin Django, andconfig.force_sslplus proxy settings in Rails. - Magento, PrestaShop and others: base URL settings in admin or the database need
https://and the canonical host.
Cause 4: A loop at the origin only
If the origin loops even when tested directly with --resolve, Cloudflare is not at fault. Look for:
- An
.htaccessthat redirects HTTPS to HTTPS because the rule tests%{HTTPS}but the web server sits behind another proxy (a load balancer or hosting reverse proxy) that terminates TLS. - Conflicting plugins, for example a security plugin and a caching plugin both enforcing SSL.
- A hosting panel "Force HTTPS" toggle combined with a manual rewrite rule.
Remove all but one mechanism. The right place is usually a single redirect at the outermost layer.
Cause 5: Cached redirects
Browsers cache 301 responses aggressively, and Cloudflare may cache a redirect if a cache rule applies to it. After fixing the cause:
- Test in a private window or with
curl, which keeps no cache. - Purge the affected URL in Cloudflare. See Cloudflare cache rules and purge.
- Clear the browser's cache for the site if your own browser still loops while
curlis clean.
Cookies can also trigger a loop with some apps. If a private window works but your normal window does not, clear cookies for the domain.
Quick decision table
What curl shows | Likely cause | Fix |
|---|---|---|
| Origin on port 80 returns 301 to HTTPS, Cloudflare mode is Flexible | Flexible plus origin redirect | Switch to Full (strict) |
example.com to www, www back to example.com | Two canonical hosts | Pick one, align edge, origin, CMS |
| Loop only on one path or subfolder | Page Rule, Redirect Rule or app route | Review rules matching that path |
| Origin loops without Cloudflare | App or server config | Fix origin rewrite, trust forwarded proto |
curl is clean, browser loops | Cached 301 or cookie | Clear cache and cookies, purge edge |
Verify the fix
curl -sIL http://example.com/ | grep -iE "^(HTTP/|location)"
You want exactly one redirect, from HTTP to the final HTTPS URL, then a 200. Anything longer is worth tidying, since every extra hop costs time. Confirm the final URL's certificate with the SSL Checker and the status with the HTTP Status Checker.
Next steps
- Trace your own chain with the Redirect Checker.
- Review SSL modes in Cloudflare setup: DNS and SSL modes.
- Learn redirect types in HTTP redirects: 301 vs 302.
- Watch the homepage and a keyword on it with the Uptime Monitor so a returning loop is flagged quickly.
FAQ
Why does the loop only happen after I enable Cloudflare?
Cloudflare changes the connection between the visitor and your origin. In Flexible mode the origin sees plain HTTP and redirects to HTTPS, which starts the loop. Moving to Full or Full (strict) usually ends it.
Does Full SSL always fix too many redirects?
It fixes the Flexible-plus-origin-redirect case. If the loop comes from conflicting www rules or the application's URL settings, you must fix those instead.
Why does the site load in incognito but not normally?
Your browser likely cached a 301 or holds a cookie that sends the app into a redirect. Clear site data for the domain, then retest.
Can a page rule cause a redirect loop?
Yes. A forwarding rule whose destination matches its own pattern redirects to itself. Check the pattern and target for each rule on the zone.
Get notified when this guide updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.