Notes
ERR_TOO_MANY_REDIRECTS:find the two rules redirecting to each other (Cloudflare, nginx, proxies, WordPress)
You open your site and the browser refuses to show it. Chrome says the address "redirected you too many times" and names the error:
ERR_TOO_MANY_REDIRECTSFirefox says "The page isn't redirecting properly", and adds that the server is redirecting the request "in a way that will never complete". Both mean the same thing: every response the browser got was another redirect, none of them led to a page, and the browser stopped following them. The Fetch standard, which browsers implement, draws that line at 20: when a request's redirect count reaches 20, the fetch ends in a network error.
A loop almost always has exactly two parts. One layer sends the request somewhere (to HTTPS, to www, to a trailing slash) and another layer sends it back. Each rule looks correct on its own, which is why the loop survives review. The job is to find the pair and remove one side of it, not to add a third rule on top. Cloudflare's page for this error names the same first suspects: the SSL/TLS encryption mode, edge settings such as Always Use HTTPS, and redirect rules. Below is how to read the loop, then the causes, starting with the two behind the most viewed questions about this error.
Read the loop before you change anything
You do not have to guess which pair it is. curl follows redirects with -L, and with -I it prints only the headers of every response, so each hop shows its status and its Location. --max-redirs keeps a loop short:
Every hop, headers only
curl -sIL --max-redirs 5 https://example.com/
echo $? # 47 means curl gave up: "Too many redirects"
Illustrative output of a loop, shortened
HTTP/2 301
location: https://example.com/
HTTP/2 301
location: https://example.com/
HTTP/2 301
location: https://example.com/
Put each Location next to the URL that was requested and look at what changes. That tells you which pair you are dealing with:
- Nothing changes: the URL redirects to itself. From the outside, the first three causes below all look like this: Cloudflare on Flexible (01), an nginx block that redirects its own HTTPS traffic (02), and an app behind a proxy or load balancer that cannot see the visitor used HTTPS (03). In 01 and 03 the layer that redirects is looking at a plain HTTP hop the visitor never sees; in 02 it does not check the scheme at all. Either way it sends the visitor to the https address they already have.
- The scheme flips between https and http. One layer forces HTTPS and another sends HTTPS back to HTTP (06).
- The host flips between www and the bare domain. Two layers disagree on the canonical host (05).
- The path flips, with and without a trailing slash. One layer adds the slash and another strips it. Choose one convention and set it in one place.
Test with curl, not in the tab that looped. RFC 9110 makes 301 and 308 responses heuristically cacheable, so a browser can keep replaying a redirect it stored after the server has stopped sending it. And once a site has sent Strict-Transport-Security, the browser upgrades http:// to https:// by itself for that host. curl does neither: it only uses an HSTS cache when you pass --hsts, and it keeps no cookies between hops unless you turn its cookie engine on, for example with -b.
01
Cloudflare on Flexible, and an origin that forces HTTPS
The most viewed question about this error, from 2017 (about 94,000 views), is exactly this setup: nginx behind Cloudflare with the Flexible option, and a port 80 server block with return 301 https://$server_name$request_uri;. On the second most viewed one (about 77,000 views), the answer with the most votes (113 at the time of writing, against 32 for the accepted answer) is one line: "In my case it was Cloudflare. I had to change to Full SSL encryption".
Cloudflare documents the mechanism. On Flexible, "all connections between Cloudflare and your origin are made through HTTP", whatever the visitor used. So the origin sees plain HTTP on every request and redirects it to HTTPS, Cloudflare hands that redirect to the browser, and the browser asks Cloudflare for the same https address again. The Flexible page puts it plainly: "If your origin forces HTTPS by automatically redirecting HTTP requests to HTTPS, do not use Flexible mode."
Fix it in the order Cloudflare recommends:
- Give the origin a certificate and switch to Full (strict), on the SSL/TLS Overview page. The origin has to accept HTTPS on port 443 and present a certificate that is unexpired, issued by a publicly trusted CA or by Cloudflare's Origin CA, and valid for the hostname; otherwise visitors get error 526 instead of the loop. Your origin can keep its HTTP to HTTPS redirect. In Full and Full (strict), Cloudflare connects to the origin with the scheme the visitor used, so an https request now arrives over HTTPS and is served, and a visit over http:// is redirected once and then loads.
- If the origin really cannot do TLS, stay on Flexible, remove the HTTPS redirect from the origin, and let Cloudflare enforce HTTPS at the edge with Always Use HTTPS (SSL/TLS, Edge Certificates). Cloudflare meant Flexible for origins that cannot support SSL/TLS, and says to use Full or Full (strict) if the site handles personal data or logins, because the hop to your origin stays unencrypted.
The accepted 2017 answer took a third route: keep Flexible and redirect only when Cloudflare reports that the visitor used HTTP.
Accepted answer, 2017 (shortened): redirect on the visitor's scheme
server {
listen 80 default_server;
server_name mydomain.com www.mydomain.com;
if ($http_x_forwarded_proto = "http") {
return 301 https://$server_name$request_uri;
}
# ... root, locations
}
It works because Cloudflare sets X-Forwarded-Proto to the protocol the visitor used and overwrites any value the client sent. It also leaves the hop to your origin unencrypted, and a request that reaches the origin without Cloudflare has no such header and is never redirected. Use it as a bridge until the origin has a certificate.
The same loop in Kubernetes
The 2023 question (about 16,000 views) looks different at first: Argo CD behind ingress-nginx. The ingress log in it tells the story. Every line is GET / answered with 308, the client is 172.71.6.219, an address inside Cloudflare's published range 172.64.0.0/13, and the four upstream fields just before the request ID at the end of each line are dashes. In ingress-nginx's documented log format those four fields are the upstream server's address, response length, response time and status, so no upstream was contacted: the controller sent the 308 itself, before Argo CD saw anything. That fits what the asker reported: switching Argo CD's server.insecure between "true" and "false" did not help.
ingress-nginx documents where a 308 like that comes from: "By default the controller redirects (308) to HTTPS if TLS is enabled for that ingress", and the ingress in the question has a tls section. The annotation the asker set to "false" was force-ssl-redirect, a different switch from ssl-redirect. If Cloudflare reaches the ingress over plain HTTP, as it does on Flexible, this is the loop in the diagram with a Kubernetes controller as the origin, and the fixes are the same: let Cloudflare connect over HTTPS, or set nginx.ingress.kubernetes.io/ssl-redirect: "false" and enforce HTTPS at Cloudflare. Argo CD's ingress guide adds its own requirement when TLS ends at the ingress: run the API server with TLS disabled, through --insecure or server.insecure: "true".
One caveat for 2026: ingress-nginx is retired. The same Argo CD guide says it "was archived on March 24, 2026", and the Kubernetes announcement said that after March 2026 there would be "no further releases, no bugfixes, and no updates to resolve any security vulnerabilities", while existing deployments keep working. The annotations in this article apply to those existing installations. If you have moved to Gateway API or another controller, the loop is the same, but look for that controller's own HTTP to HTTPS redirect setting instead.
02
One nginx server block that redirects its own HTTPS traffic
The second most viewed question (2017, about 77,000 views) had a different bug in its config. One server block listened on port 80 and on 443, and had the redirect at server level:
From the question (shortened): the redirect runs for HTTPS too
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name mywebsite.me www.mywebsite.me;
return 301 https://$server_name$request_uri;
# ... certificates, root, locations
}
nginx executes the rewrite-module directives at server level in order, and return "stops processing and returns the specified code to a client". Nothing in that block asks which port the request came in on, so a request that is already HTTPS gets redirected to itself. The accepted answer splits the block in two, so only port 80 redirects:
Accepted answer (shortened): port 80 redirects, port 443 serves
server {
listen 80 default_server;
server_name mywebsite.me www.mywebsite.me;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
server_name mywebsite.me www.mywebsite.me;
ssl_certificate /etc/letsencrypt/live/mywebsite.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.me/privkey.pem;
# ... root, locations
}
Another answer, on the 2017 Cloudflare question, keeps one block and guards the redirect with if ($scheme = "http"). nginx documents $scheme as the request scheme, "http" or "https", and that is the scheme of the connection nginx itself received. The guard is right when nginx terminates TLS. Behind Cloudflare on Flexible or behind a load balancer, the hop nginx sees is always http, so the guard matches every request and loops exactly like the unguarded redirect.
03
TLS ends at a proxy or load balancer, and the app forces HTTPS anyway
This is the general form of 01. Something in front of the app (a load balancer, a reverse proxy, an ingress, a tunnel) accepts HTTPS from the visitor and forwards plain HTTP. The app has an HTTPS redirect, sees an HTTP request, and sends the visitor to the https address they already have. AWS describes this for its Classic Load Balancer: rewrite rules that ignore X-Forwarded-Proto "can create an infinite loop of redirection requests between your Classic Load Balancer and the instances behind your load balancer", which "results in the error ERR_TOO_MANY_REDIRECTS". The same page notes that Application Load Balancers support redirect actions that can redirect HTTP traffic to HTTPS, so on an ALB the redirect can live on the load balancer instead of the instances.
X-Forwarded-Proto is how the app learns what the visitor used. MDN describes it as a de-facto standard header "for identifying the protocol (HTTP or HTTPS) that a client used to connect to a proxy or load balancer". Redirect only when it says http, or tell your framework to read it:
nginx behind a load balancer (AWS's example)
server {
listen 80;
server_name _;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
# ... root, locations
}
WordPress: wp-config.php, above the require_once line
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS'] = 'on';
Django: settings.py
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = True
Express: trust one proxy hop, then redirect on req.secure
app.set('trust proxy', 1);
app.use((req, res, next) => {
if (req.secure) return next();
res.redirect(301, 'https://example.com' + req.originalUrl);
});
In Express, req.protocol takes the value of X-Forwarded-Proto only when trust proxy is set, and req.secure is the same as req.protocol === 'https'. The redirect target is a fixed host here on purpose, so the Host header of the request does not decide where visitors are sent.
Trust the header only from your own proxy. Django's documentation says to set SECURE_PROXY_SSL_HEADER only if you control the proxy or have another guarantee that it sets or strips the header, and Express warns that with trust proxy set to true, the last trusted proxy must remove or overwrite X-Forwarded-Proto, "otherwise it may be possible for the client to provide any value". A hop count such as the 1 above does not change that: req.protocol still reads the header, so your proxy still has to set it.
04
WordPress after the switch to HTTPS
The WordPress question (2015, about 66,000 views) began with an .htaccess rule that forced HTTPS by port: RewriteCond %{SERVER_PORT} !^443$. The accepted answer changed the condition to %{HTTPS} !=on. The two answers with the most votes went further. Both set WP_HOME and WP_SITEURL to https in wp-config.php and set $_SERVER['HTTPS'] to 'on', one only when X-Forwarded-Proto is https, the other always. That second step only matters when TLS ends in front of the web server, and that is the case where neither .htaccess test can help.
Apache sets its HTTPS variable to "on" only "if the connection is using SSL/TLS", and the connection Apache gets from Cloudflare on Flexible or from a load balancer is plain HTTP, on the plain HTTP port. So both conditions match every request, including the ones that are HTTPS for the visitor. Behind such a proxy, test the header it sets instead; mod_rewrite reads any request header as %{HTTP:header}, and = compares it as an exact string:
.htaccess behind a proxy that always sets X-Forwarded-Proto
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
WordPress has its own HTTPS logic on top of that. Its handbook says that when WordPress is "hosted behind a reverse proxy that provides SSL, but is hosted itself without SSL", its HTTPS options such as FORCE_SSL_ADMIN "will initially send any requests into an infinite redirect loop", and fixes it by reading HTTP_X_FORWARDED_PROTO in wp-config.php. The reason is is_ssl(), the function WordPress uses to decide whether a request is HTTPS: it checks $_SERVER['HTTPS'] and port 443, nothing else. The snippet in 03 is the version from the is_ssl() reference page. The handbook's version tests with strpos() instead, because "in some setups HTTP_X_FORWARDED_PROTO might contain a comma-separated list e.g. http,https". Setting $_SERVER['HTTPS'] = 'on' unconditionally also stops the loop, but only by telling WordPress that every request is HTTPS, whether it is or not.
Then make WordPress's own addresses agree with the rest of the stack. WP_HOME and WP_SITEURL in wp-config.php override the home and siteurl values from the database without changing them there; the documentation says each should include https:// and no trailing slash:
wp-config.php
define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );
The host you put there matters as much as the scheme, which is the next cause.
05
www and the bare domain, redirecting to each other
If the host changes on every hop, two layers have a different idea of the canonical host. WordPress is often one of the two. Its redirect_canonical() takes the host for the redirect from home_url(), and only switches between the www and the non-www form of the same name. So a WordPress site whose home is https://www.example.com, behind a server, ingress or Cloudflare rule that sends www to the bare domain, sends visitors back and forth until the browser gives up. ingress-nginx, on installations that still run it (see the caveat in 01), has a switch of the same kind: from-to-www-redirect redirects toward whichever form the Ingress host uses. Cloudflare's troubleshooting page lists conflicting redirect rules and Page Rules as a cause in their own right.
Fix: pick one host, then make every layer agree with it: Cloudflare redirect rules and Page Rules, the web server, ingress annotations, and the app's base URL (in WordPress, home and siteurl). Then delete the redirects that point the other way instead of adding one more.
06
Cloudflare forces HTTPS, and the origin sends it back to HTTP
This is the mirror image of 01, and in curl output the scheme flips on every hop. On Full or Full (strict), Cloudflare connects to the origin with the scheme the visitor used, so an https request reaches the origin over HTTPS; with Always Use HTTPS on, Cloudflare redirects every http request to https. If the origin redirects HTTPS requests back to HTTP, from an old rule or a hardcoded http:// base URL, each side undoes the other: the origin sends the https request to http, and Cloudflare sends the http request back to https. Cloudflare lists the same loop when HSTS is enabled and the origin redirects to HTTP, or when HSTS is on while the encryption mode is Off.
Fix: remove the origin's redirect to HTTP, and make sure the encryption mode is at least Flexible if you keep HSTS or Always Use HTTPS on. Cloudflare's Always Use HTTPS page goes further and recommends not performing redirects at the origin at all, because they can cause redirect loops.
Confirm the fix
Check all four ways a visitor can arrive, not only the one that failed:
Every entry point, status and Location only
for u in http://example.com/ http://www.example.com/ https://example.com/ https://www.example.com/; do
echo "== $u"
curl -sIL --max-redirs 10 "$u" | grep -iE '^(HTTP/|location:)'
done
- Fixed: every chain ends in a
200(or the status your page really returns). Ideally the addresses that are not canonical get there in one redirect, straight to the canonical one. - Still looping: the chain stops at your
--max-redirswith a 3xx. The loop above pipes curl into grep, so you will not see curl's exit code there; run that address alone with the first command in this article, andecho $?prints 47. Read the flipping part again, as in the first section. - Loops only after you sign in: plain curl is signed out, so it will not reproduce this. Copy your session cookie from the browser's developer tools and send it with
-b 'name=value', which curl puts in the Cookie header of every request. If the chain loops only with that cookie, look at your session and login redirects, not at HTTPS. If the sign-in itself never sticks (the server sets a cookie during the redirects and then asks for it again), run the chain with-b ""instead: that turns on curl's cookie engine without any cookies, so curl records the cookies it receives along the way and sends them on the next hops.
Then open the site in the browser again. If curl ends in a 200 and the old tab still loops, the tab is replaying a cached redirect.
Traps
- Switching to Full (strict) before the origin has a valid certificate. The loop goes away and error 526 takes its place.
- Staying on Flexible for good. Removing the origin's redirect ends the loop, but the hop from Cloudflare to your origin stays unencrypted, which Cloudflare advises against for any site with logins or personal data.
- A second nginx that rewrites X-Forwarded-Proto. The WordPress handbook's proxy example sets
proxy_set_header X-Forwarded-Proto $scheme;. That is right when this nginx is the first hop and terminates TLS. If it sits behind Cloudflare or a load balancer,$schemeis http there, and the line replaces the https the first proxy sent with http. The app then redirects again. In that setup pass the incoming value on withproxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;(nginx exposes any request header as$http_plus its name), and let only the front proxy reach this nginx. - Trusting X-Forwarded-Proto from anyone. A client can send the header too. Trust it only from a proxy that overwrites it, as the Django and Express documentation both insist.
- Clearing cookies as the fix. Scheme and host loops live in configuration, so clearing cookies does not touch them. A loop that starts only after you sign in points at the session, and clearing cookies may not help there either. In a 2017 question about an AWS load balancer (two instances, and the asker describes only a port 80 listener, no HTTPS), the loop began right after logging in and stayed after the asker cleared all browser cookies. A later answer there reports that turning on sticky sessions for the target group fixed a similar login loop. Test that kind of loop with your session cookie, as in Confirm the fix.
- Changing two layers at once. Change one, run curl, then the next. Otherwise you will not know which pair it was, and the removed rule may have been the one you needed.
Check your chain in the browser
Run the first command from Read the loop, one curl -sIL for the one address that loops, and paste its output into Redirect Loop Doctor, together with that URL, your Cloudflare SSL/TLS mode, whether your server and your app force HTTPS, whether your server trusts X-Forwarded-Proto, your www rule and your app's site URL. Do not paste the four-address output from Confirm the fix: the tool reads every Location line as one chain, so four chains that each end in a 200 look like a loop to it. It finds the step that repeats and, when the Location headers are absolute URLs, names what differs there (scheme, host or trailing slash); relative ones such as location: /blog/ are skipped, so compare those by hand. It also checks your settings for several of the pairs above: Flexible against an origin that forces HTTPS, an app that forces HTTPS without trusting the proxy header, a site URL that disagrees on scheme or www, and a Cloudflare rule that forwards to itself. It does not request your URL; it reads only what you paste, in your browser.
Questions
Why did ERR_TOO_MANY_REDIRECTS start right after I put my site behind Cloudflare?
Most often because the SSL/TLS encryption mode is Flexible and your origin redirects HTTP to HTTPS. On Flexible, Cloudflare connects to your origin over plain HTTP, so the origin redirects every request to the HTTPS address the visitor already asked for. Put a certificate on the origin and switch to Full (strict), or remove the origin's redirect and let Cloudflare enforce HTTPS with Always Use HTTPS.
Does clearing cookies fix ERR_TOO_MANY_REDIRECTS?
Only when the loop depends on a cookie, such as a login that never sticks. Scheme and host loops live in server configuration. Run curl -sIL against the URL: curl sends and keeps no cookies unless you give it some or turn its cookie engine on, for example with -b, so if curl loops too, cookies are not the cause.
I fixed the configuration. Why does my browser still show the error?
The browser may be replaying what it stored. RFC 9110 makes 301 and 308 responses heuristically cacheable, and after a site has sent Strict-Transport-Security the browser upgrades http:// to https:// on its own. curl starts fresh on every run and only uses an HSTS cache when you pass --hsts, so check with curl first. If curl ends in a 200, the fix worked.
Flexible, Full or Full (strict): which Cloudflare mode should I use?
Cloudflare recommends Full (strict) whenever possible. It needs an origin that accepts HTTPS on port 443 and presents an unexpired certificate from a publicly trusted CA or from Cloudflare's Origin CA, valid for the hostname; otherwise visitors get error 526. Flexible is meant for origins that cannot support SSL/TLS, and it loops whenever the origin redirects HTTP to HTTPS.
How many redirects does a browser follow before it shows the error?
20. The Fetch standard, which browsers implement, returns a network error when a request's redirect count reaches 20. curl follows up to 50 redirects by default with -L, and exits with code 47 when it reaches the limit set by --max-redirs.
Sources
- Cloudflare, "ERR_TOO_MANY_REDIRECTS" (the browser messages; Flexible with an origin that redirects HTTP to HTTPS; Full or Full (strict) with an origin that redirects HTTPS to HTTP; Always Use HTTPS; HSTS with an origin redirect to HTTP or encryption mode Off; conflicting redirect rules and Page Rules): developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/
- Cloudflare, "Flexible" encryption mode ("all connections between Cloudflare and your origin are made through HTTP"; use when the origin cannot support SSL/TLS; "do not use Flexible mode" when the origin forces HTTPS; Full or Full (strict) for sensitive information such as logins): developers.cloudflare.com/ssl/origin-configuration/ssl-modes/flexible/
- Cloudflare, "Full" encryption mode (Cloudflare "makes connections to the origin using the scheme requested by the visitor": http from the visitor means plaintext HTTP to the origin, and vice versa): developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/
- Cloudflare, "Full (strict)" encryption mode ("does everything in Full mode" with stricter certificate checks; recommended whenever possible; origin on port 443 with an unexpired certificate from a publicly trusted CA or Cloudflare Origin CA matching the hostname; error 526 otherwise): developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/
- Cloudflare, "Always Use HTTPS" (redirects all http requests to https; recommends not redirecting at the origin; set under Edge Certificates, not available with encryption mode Off): developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/
- Cloudflare, "Cloudflare HTTP headers" (
X-Forwarded-Protois the protocol the visitor used, and a client-sent value is overwritten): developers.cloudflare.com/fundamentals/reference/http-headers/; Cloudflare IPv4 ranges (includes172.64.0.0/13): cloudflare.com/ips-v4 - WHATWG Fetch Standard, "HTTP-redirect fetch" ("If request's redirect count is 20, then return a network error"): fetch.spec.whatwg.org/#http-redirect-fetch
- RFC 9110, HTTP Semantics, section 15.4 (a client should detect and intervene in cyclical redirections), 15.4.2 and 15.4.9 (301 and 308 responses are heuristically cacheable): rfc-editor.org/rfc/rfc9110#section-15.4
- MDN,
X-Forwarded-Proto(de-facto standard header for the protocol a client used to connect to a proxy or load balancer): developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto;Strict-Transport-Security(future http requests to the host are upgraded to https): developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security; "Redirections in HTTP", redirection loops: developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections#redirection_loops - nginx,
ngx_http_rewrite_module(server-level directives run in order;return"stops processing and returns the specified code to a client"): nginx.org/en/docs/http/ngx_http_rewrite_module.html#return;ngx_http_core_moduleembedded variables ($scheme,$http_name,$host): nginx.org/en/docs/http/ngx_http_core_module.html#variables - AWS re:Post Knowledge Center, "How do I redirect HTTP traffic to HTTPS on my Classic Load Balancer?" (the loop between the load balancer and the instances, the ERR_TOO_MANY_REDIRECTS error, the nginx example with
$http_x_forwarded_proto, and the note that Application Load Balancers support redirect actions): repost.aws/knowledge-center/redirect-http-https-elb - ingress-nginx, annotations, "Server-side HTTPS enforcement through redirect" (308 to HTTPS by default when TLS is enabled;
ssl-redirectandforce-ssl-redirect) and "Redirect from/to www": kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/; log format (the upstream fields): kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/log-format/ - Argo CD, "Ingress Configuration" (run the API server with TLS disabled,
--insecureorserver.insecure: "true", when TLS ends at the ingress; ingress-nginx "is retired, and was archived on March 24, 2026"): argo-cd.readthedocs.io/en/stable/operator-manual/ingress/ - Kubernetes blog, "Ingress NGINX Retirement: What You Need to Know" (November 11, 2025; after March 2026 no releases, bugfixes or security updates; existing deployments continue to function; Gateway API as the suggested replacement): kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/
- WordPress Advanced Administration Handbook, "HTTPS" (behind a reverse proxy that provides SSL the options "will initially send any requests into an infinite redirect loop"; the
HTTP_X_FORWARDED_PROTOsnippet; the nginx proxy example): developer.wordpress.org/advanced-administration/security/https/; "wp-config.php" (WP_SITEURL,WP_HOME): developer.wordpress.org/advanced-administration/wordpress/wp-config/ - WordPress Code Reference,
is_ssl()(checks HTTPS or port 443; the load balancer fix above the require_once call): developer.wordpress.org/reference/functions/is_ssl/;redirect_canonical()(the host comes fromhome_url(), only between www and non-www): developer.wordpress.org/reference/functions/redirect_canonical/ - Apache HTTP Server,
mod_rewrite, RewriteCond (HTTPSis "on" if the connection uses SSL/TLS;%{HTTP:header}; the=comparison): httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond - Django, settings,
SECURE_PROXY_SSL_HEADER(and its warning) andSECURE_SSL_REDIRECT: docs.djangoproject.com/en/stable/ref/settings/#secure-proxy-ssl-header - Express, "Express behind proxies" (
trust proxy, the warning about overwriting X-Forwarded-Proto when it is set totrue,req.protocol): expressjs.com/en/guide/behind-proxies.html; request API (req.protocolusesX-Forwarded-Protowhenevertrust proxydoes not evaluate to false;req.secure): expressjs.com/en/5x/api/request/ - curl, man page (
-L,-I,--max-redirswith a default of 50, exit code 47 "Too many redirects",-bwithNAME=VALUEcookies sent in every request, or with""to turn on the cookie engine, which records incoming cookies for use with--location,--hsts): curl.se/docs/manpage.html - Stack Overflow, "HTTP to HTTPS Nginx too many redirects" (2017, about 94,000 views; the Chrome and Firefox messages as the asker quotes them; Cloudflare Flexible with an nginx redirect; the accepted
$http_x_forwarded_protoanswer, the Full (strict) answer and the$schemeanswer): stackoverflow.com/questions/41583088 - Stack Overflow, "ERR_TOO_MANY_REDIRECTS with nginx" (2017, about 77,000 views; one server block for ports 80 and 443; the accepted split into two blocks; the 113-vote answer about Cloudflare Full SSL): stackoverflow.com/questions/46413494
- Stack Overflow, "Too many Redirects after switching WordPress to https" (2015, about 66,000 views; the SERVER_PORT rule and the answers with WP_HOME, WP_SITEURL and
$_SERVER['HTTPS']): stackoverflow.com/questions/29478863 - Stack Overflow, "AWS Load Balancer ERR_TOO_MANY_REDIRECTS" (2017, about 33,000 views; two instances behind a load balancer with a port 80 listener; the loop starts after logging in; cookies already cleared; the answer reporting that sticky sessions fixed a similar login loop): stackoverflow.com/questions/42715718
- Stack Overflow, "ArgoCD Ingress Kubernetes Too Many Redirects even With --insecure - Nginx" (2023, about 16,000 views; the ingress log with repeated 308 responses; "Nothing is working" after both server.insecure values): stackoverflow.com/questions/76624577