Cybersecurity / Networking

How to Fix "net::ERR_TOO_MANY_REDIRECTS" in HTTPS Configuration

4 min read by DebuggedIt

Quick answer

The HTTP browser error net::ERR_TOO_MANY_REDIRECTS occurs when a web client enters an infinite HTTP redirection loop (returning status codes 301 Moved...

The HTTP browser error net::ERR_TOO_MANY_REDIRECTS occurs when a web client enters an infinite HTTP redirection loop (returning status codes 301 Moved Permanently or 302 Found). In modern web deployments involving CDN reverse proxies (such as Cloudflare, AWS CloudFront, or Nginx), this infinite loop is most frequently caused by SSL termination misconfigurations where the proxy communicates with the origin server over HTTP while enforcing HTTPS externally.

The Problem

When sending requests or configuring components in your development environment, the application or HTTP client fails with the following exact error trace:

# Example 1: Google Chrome Browser Screen Error
This page isn't working
example.com redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS

# Example 2: Firefox Web Error
The page isn't redirecting properly.
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

# Example 3: cURL output showing 301 loop trace
curl -IL https://example.com
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
curl: (47) Maximum (%d) redirects followed

This error halts script execution, prevents API communication, or results in immediate client-side connection drops.

Browser https://example.com 1. HTTPS Request Cloudflare / Proxy SSL Mode: Flexible (HTTP) 2. Request over HTTP Origin 3. 301 Redirect to HTTPS (Infinite Loop!)

Why It Happens

This failure occurs due to misconfigurations at the networking, cryptographic, or application protocol layer. The primary causes include:

  • Cloudflare "Flexible" SSL Misconfiguration: Cloudflare communicates with the origin server over HTTP port 80, but the origin web server redirects all HTTP requests to HTTPS, triggering an infinite loop back to Cloudflare.
  • Missing X-Forwarded-Proto Header: Reverse proxies like Nginx or AWS Application Load Balancers terminate SSL and proxy traffic to application servers (Express, WordPress) without forwarding X-Forwarded-Proto: https, causing the backend framework to perceive requests as insecure.
  • Conflicting Web Server Redirect Rules: Both the reverse proxy layer and the application layer (e.g., .htaccess or Nginx config) enforce separate HTTP-to-HTTPS redirect rules with mismatched matching parameters.
  • Application Hardcoded Scheme: CMS frameworks like WordPress or Laravel are configured with FORCE_SSL or WP_HOME=https://... while receiving plain HTTP traffic from an unconfigured SSL-terminating load balancer.

The Fix

Follow these step-by-step solutions to resolve the error in your environment.

Solution 1: Fix Cloudflare SSL/TLS Encryption Mode

If using Cloudflare or similar CDNs, navigate to SSL/TLS Settings in the dashboard and change the encryption mode from Flexible to Full or Full (strict).

Flexible mode forces Cloudflare to connect to your server via HTTP, causing origin servers configured with HTTPS redirects to return 301 Moved Permanently endlessly.

Solution 2: Configure Nginx X-Forwarded-Proto and Reverse Proxy Headers

Ensure Nginx or your reverse proxy explicitly sets the X-Forwarded-Proto header when passing requests to upstream backend application pools:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Solution 3: Configure Express / Node.js Trust Proxy Settings

In Node.js applications running behind load balancers or reverse proxies, enable trust proxy so Express evaluates X-Forwarded-Proto headers correctly:

const express = require('express');
const app = express();

// Trust reverse proxy headers (e.g. AWS ALB, Nginx, Cloudflare)
app.set('trust proxy', true);

app.use((req, res, next) => {
  if (req.secure) {
    next();
  } else {
    // Redirect only if request is truly HTTP
    res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
});

Still Not Working?

Browser HSTS Cache and Cookie Redirection Loops

HTTP Strict Transport Security (HSTS) headers cached by the browser can force connections to HTTPS even after backend configurations are updated. Additionally, session cookies set without Secure flags or with conflicting domain parameters can trigger authentication-based redirect loops. Test the application endpoint using cURL to bypass browser caching completely:

curl -I -L --max-redirs 5 http://example.com

Inspect the Location: headers in the output trace to identify exactly which hop responds with a 301 or 302 redirect code.