How to fix Error: Maximum number of redirects exceeded (circular redirects) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 230 views

This error occurs when an HTTP client follows too many redirect responses, exceeding the configured limit. It commonly happens with axios, node-fetch, or the follow-redirects package when a server creates a redirect loop or when legitimate redirects exceed the maxRedirects threshold (default 21).

Quick fix

Fixes ERR_FR_TOO_MANY_REDIRECTS

const axios = require('axios');

axios.interceptors.request.use(request => {
  console.log('Requesting:', request.url);
  return request;
});

axios.interceptors.response.use(response => {
  if (response.status >= 300 && response.status < 400) {
    console.log('Redirect from:', response.config.url);
    console.log('Redirect to:', response.headers.location);
  }
  return response;
});

try {
  await axios.get('https://example.com/api/endpoint');
} catch (err) {
  console.error('Failed after redirects:', err.message);
}
  1. Identify the redirect chain causing the error
  2. Fix circular redirect loops on the server
  3. Increase maxRedirects for legitimate multi-step redirects
  4. Disable automatic redirects and handle them manually
node.js โ€” error
const axios = require('axios');
axios.interceptors.request.use(request => {
console.log('Requesting:', request.url);
return request;
});
axios.interceptors.response.use(response => {
if (response.status >= 300 && response.status < 400) {
console.log('Redirect from:', response.config.url);
console.log('Redirect to:', response.headers.location);
}
return response;
});
try {
await axios.get('https://example.com/api/endpoint');
} catch (err) {
console.error('Failed after redirects:', err.message);
}
Error: Maximum number of redirects exceeded (circular redirects)

What this error means

The "Maximum number of redirects exceeded" error is thrown by HTTP clients when a request follows more redirect responses than the configured maximum allows. This safety mechanism prevents infinite redirect loops that could hang your application indefinitely. Most Node.js HTTP libraries use the follow-redirects package under the hood, which sets a default limit of 21 redirects. When this limit is exceeded, the ERR_FR_TOO_MANY_REDIRECTS error is emitted and the request fails. Circular redirects are the most common cause - when URL A redirects to URL B, which redirects back to URL A, creating an endless loop. However, the error can also occur with legitimate multi-step redirects that happen to exceed the threshold, particularly in complex authentication flows or CDN configurations.

Typical symptoms

  • axios requests fail with "ERR_FR_TOO_MANY_REDIRECTS" error code
  • HTTP client throws "Maximum number of redirects exceeded" message
  • fetch requests hang then fail after multiple redirect attempts
  • Request appears to work in browser but fails in Node.js
  • Error stack trace shows follow-redirects module at RedirectableRequest._processResponse
  • Same URL works with lower maxRedirects threshold but fails with higher values

Common causes

  1. Circular redirect loop where two URLs redirect to each other infinitely
  2. Misconfigured server that redirects a URL back to itself
  3. Authentication flow with too many intermediate redirect steps
  4. Proxy or load balancer creating unintended redirect chains
  5. HTTP to HTTPS redirects combined with www to non-www redirects exceeding limit
  6. CDN or edge server configuration causing excessive redirects
  7. Session handling logic that triggers redirects on every request
  8. maxRedirects set too low for legitimate multi-step redirect flows

How to fix "Error: Maximum number of redirects exceeded (circular redirects)"

1Identify the redirect chain causing the error

Add request logging to see the full redirect chain before it fails:

javascript
const axios = require('axios');

axios.interceptors.request.use(request => {
  console.log('Requesting:', request.url);
  return request;
});

axios.interceptors.response.use(response => {
  if (response.status >= 300 && response.status < 400) {
    console.log('Redirect from:', response.config.url);
    console.log('Redirect to:', response.headers.location);
  }
  return response;
});

try {
  await axios.get('https://example.com/api/endpoint');
} catch (err) {
  console.error('Failed after redirects:', err.message);
}

This reveals whether you have a circular loop (same URLs repeating) or just too many legitimate redirects.

2Fix circular redirect loops on the server

If you control the server, fix the redirect configuration to break the loop:

javascript
// BAD: Creates circular redirect
app.get('/api/login', (req, res) => {
  if (!req.session.user) {
    res.redirect('/auth'); // Redirects to auth
  }
});

app.get('/auth', (req, res) => {
  if (!req.query.token) {
    res.redirect('/api/login'); // Redirects back to login - LOOP!
  }
});

// GOOD: Properly handle authentication flow
app.get('/api/login', (req, res) => {
  if (!req.session.user) {
    res.redirect('/auth?returnUrl=/api/login');
  } else {
    res.json({ user: req.session.user });
  }
});

app.get('/auth', (req, res) => {
  // Show login form or handle OAuth without redirecting back
  res.render('login', { returnUrl: req.query.returnUrl });
});

Ensure each redirect moves forward in the flow rather than creating cycles.

3Increase maxRedirects for legitimate multi-step redirects

If the redirect chain is legitimate but exceeds the default limit, increase the threshold:

javascript
// With axios
const axios = require('axios');

const response = await axios.get('https://example.com/api', {
  maxRedirects: 30 // Default is 21
});

// With follow-redirects directly
const { https } = require('follow-redirects');

https.get({
  host: 'example.com',
  path: '/api',
  maxRedirects: 30
}, (response) => {
  // Handle response
});

// With node-fetch (using follow-redirects wrapper)
const fetch = require('node-fetch');

const response = await fetch('https://example.com/api', {
  follow: 30 // Maximum redirects to follow
});

Only increase this value if you've verified the redirects are legitimate and not circular.

4Disable automatic redirects and handle them manually

For complex scenarios, disable automatic redirects and handle them yourself:

javascript
// With axios
const axios = require('axios');

async function fetchWithManualRedirects(url, maxRedirects = 5) {
  let redirectCount = 0;
  let currentUrl = url;

  while (redirectCount < maxRedirects) {
    const response = await axios.get(currentUrl, {
      maxRedirects: 0,
      validateStatus: (status) => status < 400 // Don't throw on 3xx
    });

    if (response.status >= 300 && response.status < 400) {
      const location = response.headers.location;

      if (location === currentUrl) {
        throw new Error('Circular redirect detected');
      }

      console.log(`Redirect ${redirectCount + 1}: ${currentUrl} -> ${location}`);
      currentUrl = new URL(location, currentUrl).href;
      redirectCount++;
    } else {
      return response;
    }
  }

  throw new Error('Maximum redirects exceeded');
}

const response = await fetchWithManualRedirects('https://example.com/api');

This gives you full control to detect circular redirects and log the redirect chain.

5Use beforeRedirect hook to detect and prevent circular redirects

Implement circular redirect detection using the beforeRedirect option:

javascript
const axios = require('axios');

const visitedUrls = new Set();

const response = await axios.get('https://example.com/api', {
  beforeRedirect: (options, responseDetails) => {
    const nextUrl = options.href || options.url;

    if (visitedUrls.has(nextUrl)) {
      throw new Error(`Circular redirect detected: ${nextUrl}`);
    }

    visitedUrls.add(nextUrl);
    console.log('Redirecting to:', nextUrl);
  }
});

This aborts the request immediately when a circular redirect is detected, providing a clearer error message.

Advanced notes

Understanding the follow-redirects Package

Most Node.js HTTP clients (axios, request, node-fetch wrappers) use the follow-redirects package internally. This package handles HTTP redirects by creating a new request for each redirect response. The default maxRedirects of 21 is based on the HTTP specification's recommendation.

Detecting Redirect Loops in Production

Implement monitoring to detect redirect issues before they cause errors:

javascript
const axios = require('axios');

axios.interceptors.response.use(
  response => response,
  error => {
    if (error.code === 'ERR_FR_TOO_MANY_REDIRECTS') {
      // Log to monitoring service
      console.error('Redirect loop detected', {
        url: error.config.url,
        method: error.config.method,
        timestamp: new Date().toISOString()
      });
    }
    throw error;
  }
);

Handling Authentication Redirects

OAuth and SSO flows often involve multiple redirects. Configure clients appropriately:

javascript
// For OAuth flows that may have many redirect steps
const authClient = axios.create({
  maxRedirects: 30,
  beforeRedirect: (options, responseDetails) => {
    // Log OAuth redirect chain for debugging
    console.log('OAuth redirect:', options.href);
  }
});

Testing for Redirect Loops

Create integration tests to catch redirect configuration issues:

javascript
const axios = require('axios');

describe('API Endpoints', () => {
  it('should not create redirect loops', async () => {
    const visitedUrls = new Set();

    await axios.get('https://api.example.com/endpoint', {
      maxRedirects: 10,
      beforeRedirect: (options) => {
        const url = options.href || options.url;
        expect(visitedUrls.has(url)).toBe(false);
        visitedUrls.add(url);
      }
    });
  });
});

Proxy and CDN Considerations

When using proxies or CDNs, redirect chains can become complex. Consider using the absolute URL form for redirects to avoid resolution issues:

javascript
// Server-side: Use absolute URLs in redirect responses
app.get('/api/old-endpoint', (req, res) => {
  res.redirect(301, 'https://api.example.com/api/new-endpoint');
});

Security Implications

Excessive redirects can be used in attacks to cause denial of service or confuse clients. Always validate redirect destinations and consider implementing rate limiting for endpoints that trigger redirects.

Frequently asked questions

What does "ERR_FR_TOO_MANY_REDIRECTS" mean?
The "Maximum number of redirects exceeded" error is thrown by HTTP clients when a request follows more redirect responses than the configured maximum allows. This safety mechanism prevents infinite redirect loops that could hang your application indefinitely. js HTTP libraries use the follow-redirects package under the hood, which sets a default limit of 21 redirects.
How do I fix "ERR_FR_TOO_MANY_REDIRECTS"?
This error occurs when an HTTP client follows too many redirect responses, exceeding the configured limit. It commonly happens with axios, node-fetch, or the follow-redirects package when a server creates a redirect loop or when legitimate redirects exceed the maxRedirects threshold (default 21).
What causes "ERR_FR_TOO_MANY_REDIRECTS"?
Circular redirect loop where two URLs redirect to each other infinitely Misconfigured server that redirects a URL back to itself Authentication flow with too many intermediate redirect steps
Is the "ERR_FR_TOO_MANY_REDIRECTS" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading