psf/requests · error · TooManyRedirects
Exceeded redirects.
Error message
Exceeded {self.max_redirects} redirects. What it means
Raised by Session.resolve_redirects() when the number of HTTP redirects in a chain reaches or exceeds session.max_redirects (default 30). This is a safety mechanism to prevent infinite redirect loops. The response object is attached so the caller can inspect the last redirect response.
Solutions
- Investigate the redirect chain with allow_redirects=False to inspect each Location header manually.
- If the redirect count is legitimately high, increase session.max_redirects to a safe ceiling.
- Fix the server-side redirect loop — exceeding 30 redirects almost always indicates a bug.
Example fix
# before
resp = session.get(url) # TooManyRedirects
# after — diagnose the chain
resp = session.get(url, allow_redirects=False)
print(resp.status_code, resp.headers.get('Location'))
# or increase the limit if legitimate
session.max_redirects = 50 Defensive patterns
Strategy: try-catch
Validate before calling
session.max_redirects = 10 # set a sensible limit for your use case
Try / catch
try:
resp = session.get(url)
except requests.TooManyRedirects as e:
logger.error(f'Redirect chain exceeded limit. Last URL: {e.response.url}')
# Debug with allow_redirects=False
resp = session.get(url, allow_redirects=False) Prevention
- Use allow_redirects=False to inspect redirect chains when debugging.
- Set session.max_redirects to a reasonable limit for your application.
- Check for redirect loops in server configuration (especially auth/login flows).
- Ensure cookie handling isn't causing repeated auth redirects.
When it happens
Trigger: A URL that redirects more than 30 times (default); a redirect loop where URL A → URL B → URL A indefinitely; a misconfigured server with circular Location headers; a login flow with many intermediary redirects.
Common situations: Server-side redirect loop after authentication changes; cookie handling causing repeated redirects to a login page; migrating URLs without updating redirect chains; CDN misconfiguration creating circular redirects between HTTP and HTTPS.
Related errors
- An error occurred when rewinding request body for redirect.
- {e}
- {err}
- No connection adapters were found for
- Unable to rewind request body for redirect.
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/86a3b690b49e5a2a.
Report an issue: GitHub.
Appendix: source
Thrown at src/requests/sessions.py:217
hist: list[Response] = [] # keep track of history
url = self.get_redirect_target(resp)
previous_fragment = urlparse(req.url).fragment
while url:
prepared_request = req.copy()
# Update history and keep track of redirects.
resp.history = hist[:]
hist.append(resp)
try:
resp.content # Consume socket so it can be released
except (ChunkedEncodingError, ContentDecodingError, RuntimeError):
resp.raw.read(decode_content=False)
if len(resp.history) >= self.max_redirects:
raise TooManyRedirects(
f"Exceeded {self.max_redirects} redirects.", response=resp
)
# Release the connection back into the pool.
resp.close()
# Handle redirection without scheme (see: RFC 1808 Section 4)
if url.startswith("//"):
parsed_rurl = urlparse(resp.url)
url = ":".join([to_native_string(parsed_rurl.scheme), url])
# Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2)
parsed = urlparse(url)
if parsed.fragment == "" and previous_fragment:
parsed = parsed._replace(fragment=previous_fragment)
elif parsed.fragment:
previous_fragment = parsed.fragment
url = parsed.geturl()View on GitHub (pinned to 8068356288)