Python
requests library
URL errors
HTTP requests
error handling

Max retries exceeded with URL in requests

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The Max retries exceeded with url message in Python requests usually means the client could not establish or complete a successful HTTP connection. The root cause is often not "too many retries" in the everyday sense. It can be a bad URL, DNS failure, SSL problem, timeout, proxy issue, or a server that keeps returning retryable errors.

Start by Inspecting the Real Exception

requests wraps lower-level urllib3 errors, so the useful clue is often in the nested message. For example, a refused connection, name resolution failure, or certificate problem can all surface under the same top-level wording.

A minimal request should always include a timeout:

python
1import requests
2
3try:
4    response = requests.get("https://httpbin.org/status/200", timeout=5)
5    response.raise_for_status()
6    print(response.text)
7except requests.exceptions.RequestException as exc:
8    print(f"Request failed: {exc}")

If that fails, read the full exception text carefully. Messages such as NameResolutionError, ConnectTimeoutError, or SSLError point to very different fixes.

Common Causes

One common cause is an invalid URL. Forgetting the scheme is enough to break the request:

python
requests.get("example.com")          # wrong
requests.get("https://example.com")  # correct

Another common cause is a server that is slow or temporarily unavailable. In that case, explicit retry handling can help. The requests library uses urllib3 under the hood, and the supported way to configure retries is through an HTTPAdapter.

python
1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4
5session = requests.Session()
6
7retry = Retry(
8    total=5,
9    backoff_factor=1.0,
10    status_forcelist=[429, 500, 502, 503, 504],
11    allowed_methods=["GET", "HEAD", "OPTIONS"],
12)
13
14adapter = HTTPAdapter(max_retries=retry)
15session.mount("http://", adapter)
16session.mount("https://", adapter)
17
18response = session.get("https://httpbin.org/status/503", timeout=5)
19print(response.status_code)

That setup retries transient failures with backoff, which is appropriate for idempotent reads. It is usually a bad idea to retry non-idempotent writes blindly.

Diagnose Before You Retry Harder

Retries are useful only when the failure is temporary. If the problem is a typo, bad certificate chain, corporate proxy, or blocked port, more retries just waste time.

Check these basics:

  • confirm the URL includes the correct scheme and host
  • test DNS resolution and network reachability outside Python
  • verify proxy settings in the environment
  • inspect TLS or certificate-related messages
  • confirm the remote service is actually listening on the target port

For debugging, log the final URL and avoid silent error handling:

python
1try:
2    response = session.get("https://api.example.com/data", timeout=(3, 10))
3    response.raise_for_status()
4except requests.exceptions.RequestException as exc:
5    print(type(exc).__name__)
6    print(exc)

Using a tuple timeout is helpful because connect timeout and read timeout often need different values.

SSL and Certificate Issues

An SSL failure is often reported through the same request exception path. The correct fix is usually to trust the right certificate authority, update the environment, or fix the server certificate. Disabling verification can be useful for temporary local debugging, but it should not be the standard solution.

python
response = requests.get("https://localhost:8443", timeout=5, verify=False)

Only use that when you understand the security trade-off and the environment is controlled.

Common Pitfalls

The biggest mistake is assuming the phrase Max retries exceeded always means your retry count is too low. Often the real problem is that the request could never have succeeded in the first place.

Another mistake is leaving out timeouts. Without them, a request can hang for far too long and make debugging much harder.

Developers also sometimes retry every HTTP method. That is risky for POST, PATCH, or other operations that can create duplicate side effects if the server partially processed the request.

Finally, do not suppress exception details. The wrapped error message is usually the fastest way to tell whether the issue is DNS, TLS, connection refusal, or an upstream outage.

Summary

  • 'Max retries exceeded with url is a wrapper around a lower-level connection or HTTP failure.'
  • Start by reading the underlying exception text, not just the headline.
  • Use explicit timeouts on every request.
  • Add retries through HTTPAdapter and Retry only for failures that are likely to be temporary.
  • Check URL format, DNS, proxies, TLS, and server availability before increasing retry counts.

Course illustration
Course illustration

All Rights Reserved.