ProxynetProxynet

Max Retries Exceeded With URL: o que é e como resolver

Publicado:

16 min de leitura

Acar Diveroli
Autor: Acar Diveroli
O traço chega à caixa azul do proxy, mas o túnel até o destino apagado se rompe em um 403 vermelho; embaixo se lê RETRIES 0.

O seu script de monitoramento de preços rodou a noite inteira sem problemas. Hoje de manhã você colou nele o endereço de proxy do seu novo plano, e agora o terminal imprime uma única linha comprida: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url. O script não tem nenhuma configuração de novas tentativas, e o host na mensagem é a loja da qual você coleta os preços, então os seus olhos vão direto para a loja. No finalzinho da linha, entre parênteses, está escrito Tunnel connection failed: 403 Forbidden, e essa resposta veio do proxy, não da loja.

Este guia desmonta a mensagem: por que ela fala em "max retries" se você não configurou nenhuma nova tentativa, uma tabela de leitura montada com mensagens de erro que nós mesmos produzimos, as variantes com proxy, os timeouts e o mesmo erro no pip. No final há um script Python testado que diz qual é a causa.

O que significa "Max retries exceeded with url"?

A mensagem é gerada pelo urllib3, a biblioteca que abre as conexões para o Requests. Quando o urllib3 desiste de uma requisição, ele lança MaxRetryError. O Requests captura essa exceção e lança a sua própria, escolhida de acordo com a causa interna: ConnectTimeout, ProxyError, SSLError, RetryError quando se esgotam as novas tentativas por código de status, ou um simples ConnectionError para todo o resto. Veja uma mensagem da nossa execução de teste, dividida em suas quatro partes:

text
requests.exceptions.ProxyError                        <- 1. a exceção do Requests
HTTPSConnectionPool(host='example.com', port=443):    <- 2. o pool: host e porta de destino
Max retries exceeded with url: /                      <- 3. o texto que envolve o erro e o caminho
(Caused by ProxyError('Unable to connect to proxy',   <- 4. a causa real, da camada externa para a interna
    OSError('Tunnel connection failed: 403 Forbidden')))

A parte 2 é onde as pessoas se enganam. Para uma URL https://, a linha do pool mostra o destino, mesmo quando a requisição passa por um proxy; o endereço do proxy aparece só dentro da parte 4, quando aparece. Para uma URL http:// simples enviada por um proxy, é o contrário: a linha do pool mostra o proxy, e a parte 3 traz a URL de destino completa, como em HTTPConnectionPool(host='127.0.0.1', port=8083): Max retries exceeded with url: http://example.com/.

Por que aparece "max retries" se você nunca configurou novas tentativas?

Por padrão, o Requests não repete conexões que falharam. No código-fonte de requests/adapters.py, DEFAULT_RETRIES = 0, e o adaptador transforma isso em Retry(0, read=False). A documentação do urllib3 para a classe Retry diz que os erros são envolvidos em MaxRetryError, a menos que as novas tentativas sejam desativadas com retries=False. Zero novas tentativas não conta como desativado, então uma única tentativa que falhou já sai como "Max retries exceeded".

Aumentar o número de novas tentativas não corrige a causa. Um nome de proxy digitado errado, uma porta errada ou um túnel recusado falham do mesmo jeito todas as vezes. No nosso teste, um endereço inalcançável com timeout de conexão de 2 segundos falhou depois de 2 segundos na configuração padrão e depois de 7 segundos com duas novas tentativas e um backoff curto. Novas tentativas só ajudam em quedas curtas de rede.

Como ler a mensagem de erro, passo a passo?

Leia a mensagem de fora para dentro:

  1. Encontre a exceção do Requests. ProxyError significa que a falha aconteceu no caminho até o proxy ou no próprio proxy.
  2. Leia a linha do pool. Para destinos https://, host e port são o destino. Porta 443 por um proxy HTTP significa que a requisição passa por um túnel CONNECT.
  3. Leia a primeira classe depois de Caused by. É o diagnóstico do urllib3: NameResolutionError, NewConnectionError, ConnectTimeoutError, SSLError ou ProxyError.
  4. Leia o texto mais interno. Failed to resolve 'name', [Errno 111] Connection refused no Linux, [WinError 10061] no Windows, CERTIFICATE_VERIFY_FAILED ou Tunnel connection failed: 403 Forbidden. Um host= nesse ponto pode ser o proxy.
  5. Anote quanto tempo a chamada levou. Uma falha exatamente no seu timeout de conexão (ou em um múltiplo dele) é um timeout; uma mais rápida é uma recusa ou um túnel rejeitado. No Windows, uma conexão recusada levou cerca de dois segundos por endereço nos nossos testes, e localhost levou quatro (IPv6, depois IPv4).

Erros de HTTPSConnectionPool: o que a parte Caused by diz

Produzimos todas as mensagens abaixo no Python 3.13 com Requests 2.34.2 e urllib3 2.8.0, por meio de um proxy de teste local. Trechos longos foram encurtados com ...; o texto de erro do Windows também depende do idioma do sistema.

Caused by (parte mais interna)Exceção do RequestsO que aconteceuConfira primeiro
NameResolutionError(... Failed to resolve 'no-such-host.invalid' ...)ConnectionErrorO nome do destino não foi resolvidoGrafia da URL, DNS, VPN
NewConnectionError(... [Errno 111] or [WinError 10061] ...)ConnectionErrorNada escuta nessa portaServiço rodando, porta certa
ConnectTimeoutError(... 'Connection to 10.255.255.1 timed out. (connect timeout=2)')ConnectTimeoutNenhuma conexão TCP dentro do timeoutEndereço, firewall, valor do timeout
SSLError(SSLCertVerificationError(... CERTIFICATE_VERIFY_FAILED ...))SSLErrorO certificado não é confiávelcertifi, certificado raiz da empresa
ProxyError('Unable to connect to proxy', NewConnectionError(...))ProxyErrorA porta do proxy recusou a conexãoHost e porta do proxy, firewall local
ProxyError('Unable to connect to proxy', NameResolutionError(... 'pr.proxynet.invalid' ...))ProxyErrorO nome do proxy não foi resolvidoErro de digitação no host do proxy
ProxyError('Unable to connect to proxy', ConnectTimeoutError(...))ProxyErrorO proxy não respondeu a tempoEndereço do proxy, regras de saída para essa porta
ProxyError(..., OSError('Tunnel connection failed: 403 Forbidden'))ProxyErrorO proxy recusou o túnel CONNECTPorta de destino, tipo e porta do proxy, regras de permissão
ProxyError(..., OSError('Tunnel connection failed: 407 Proxy Authentication Required'))ProxyErrorO proxy quer credenciais válidasVeja Autenticação de proxy
ProxyError(..., OSError('Tunnel connection failed: 502 Bad Gateway'))ProxyErrorO proxy não conseguiu alcançar o destinoHost e porta de destino
ProxyError('... Your proxy appears to only use HTTP and not HTTPS ...', SSLError(... WRONG_VERSION_NUMBER ...))ProxyErrorA URL do proxy começa com https://Escreva http://

Três detalhes ficam fora da tabela. Um proxy que não responde dentro do timeout lança ProxyError, então except ConnectTimeout nunca o vê. Um timeout de leitura não é envolvido: ele chega como ReadTimeout com o texto Read timed out. (read timeout=3). E uma URL http:// simples por um proxy com senha errada não lança nada; você recebe uma resposta com status 407.

O que significa "ProxyError: Cannot connect to proxy"?

Cannot connect to proxy. (urllib3 1.26) e Unable to connect to proxy (urllib3 2.x) são o mesmo erro. Os dois podem aparecer na mesma máquina: o pip 25.x traz embutido o urllib3 1.26.20, enquanto uma instalação nova do Requests puxa o urllib3 2.8.0. Leia o segundo argumento, não a redação:

  • NewConnectionError: nada escuta nessa porta do proxy, ou um firewall local a bloqueia. Copie de novo o host e a porta do painel.
  • NameResolutionError: o nome do host do proxy está digitado errado ou o seu DNS não consegue resolvê-lo.
  • ConnectionResetError (Errno 104 no Linux, WinError 10054 no Windows): o proxy ou um dispositivo no caminho fechou a conexão.
  • OSError('Tunnel connection failed: ...'): o proxy respondeu, mas não abriu o túnel; o código de status é a resposta dele.

Para a versão do navegador, "The proxy server is not responding", veja Servidor proxy não está respondendo.

Tunnel connection failed: 403 Forbidden: por que o proxy recusa o CONNECT?

Uma requisição https:// por um proxy HTTP começa com CONNECT example.com:443. O proxy abre uma conexão TCP com o destino e repassa bytes criptografados; ele nunca vê a página. Pela RFC 9110, seção 9.3.6, qualquer resposta que não seja 2xx significa que o túnel não foi formado. O módulo http.client do Python lê essa resposta e escreve Tunnel connection failed.

O 403 é uma decisão do proxy; o destino nunca viu a sua requisição. A RFC diz que os proxies devem limitar o CONNECT a portas conhecidas ou a uma lista de destinos seguros, porque um túnel para a porta 25 poderia repassar spam. Motivos comuns:

  • A porta de destino não é permitida. https://example.com:8443/ pode falhar enquanto https://example.com/ funciona.
  • Uma lista de permissões. Proxies corporativos e algumas plataformas de hospedagem só permitem domínios aprovados. Pergunte à equipe de TI ou leia a documentação da plataforma; não contorne a política.
  • O tipo ou a porta de proxy errados, por exemplo uma porta destinada a outro protocolo.
  • Regras do provedor. Um provedor pode recusar túneis para alguns destinos; a documentação dele diz quais códigos de status usa.

Um 403 do site de destino chega como uma resposta normal, com página; esse caso está em Códigos de status HTTP no web scraping. Um 407 no túnel significa que o proxy quer credenciais.

A URL do proxy deve começar com http:// ou https://?

No dicionário proxies, a chave é o esquema do destino, e o valor é como chegar ao proxy. O próprio exemplo da documentação do Requests associa 'https' a 'http://10.10.1.10:1080'. A maioria dos proxies fala HTTP simples e abre um túnel CONNECT para sites criptografados (veja a nossa página de proxy HTTPS), então as duas chaves recebem um valor http://:

python
proxies = {
    "http": "http://user:pass@pr.proxynet.io:8000",
    "https": "http://user:pass@pr.proxynet.io:8000",  # http:// aqui também
}

Com https:// no valor, o urllib3 2.x abre TLS com o próprio proxy, um proxy HTTP simples responde com bytes que não são TLS, e você recebe WRONG_VERSION_NUMBER com a dica Your proxy appears to only use HTTP and not HTTPS. A página do urllib3 sobre esse erro dá a mesma correção, também para uma variável HTTPS_PROXY errada.

Dois pontos relacionados:

O que acontece sem timeout? ConnectTimeout e ReadTimeout

O Requests não tem timeout padrão: sem timeout=, uma chamada pode ficar travada por minutos sem deixar nenhum erro para você ler. Passe uma tupla como timeout=(3.05, 20): timeout de conexão e depois timeout de leitura, em segundos. A documentação sugere um timeout de conexão um pouco acima de um múltiplo de 3, a janela padrão de retransmissão do TCP.

Os dois timeouts falham de formas diferentes:

  • ConnectTimeout: nenhuma conexão TCP a tempo. Ele chega envolvido em "Max retries exceeded", e a referência da API diz que é seguro tentar de novo.
  • ReadTimeout: a conexão foi feita, mas nenhum dado chegou dentro do timeout de leitura. Ele não é envolvido, e o servidor pode já ter processado a requisição, então repetir um POST pode fazer o trabalho duas vezes.

O timeout de conexão vale para cada endereço IP, então um nome com endereços IPv4 e IPv6 pode dobrar a espera. O timeout de leitura é o intervalo entre bytes, não um limite para o download inteiro. Os padrões de outras bibliotecas estão em Comparativo entre HTTPX, Requests e AIOHTTP.

O mesmo erro no pip: "Retrying ... after connection broken by"

O pip traz embutidas as suas próprias cópias do Requests e do urllib3, então pip install falha pelos mesmos motivos. A documentação do pip lista os padrões: --retries 5 e --timeout 15 segundos. Rodamos o pip 26.2.1 com --retries 2 por um proxy local que recusa todo CONNECT com 403:

text
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'OSError('Tunnel connection failed: 403 Forbidden')': /simple/six/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'OSError('Tunnel connection failed: 403 Forbidden')': /simple/six/
ERROR: Could not find a version that satisfies the requirement six (from versions: none)
ERROR: No matching distribution found for six

O pacote existe; o pip nunca chegou ao índice. A causa está nas linhas WARNING. O pip 25.2 imprimiu o mesmo aviso com a redação do urllib3 1.26, ProxyError('Cannot connect to proxy.', ...).

Para CERTIFICATE_VERIFY_FAILED atrás de um proxy corporativo que inspeciona TLS, passe o certificado raiz da empresa com --cert; --trusted-host desliga a verificação e é o último recurso. A configuração de proxy do pip está em Configurar proxy no Linux.

Um script Python que diz qual é a causa

O script transforma uma exceção em uma linha: o que falhou e o que conferir. Ele:

  • repete só as conexões que falharam, duas vezes;
  • mantém read=False: no nosso teste, read=0 transformou um ReadTimeout em um ConnectionError envolvido;
  • define other=0: sem isso, um túnel recusado com 403 ou 407 foi tentado três vezes;
  • passa proxies= e timeout=(3.05, 20) em toda requisição;
  • captura ProxyError, SSLError e ConnectTimeout antes de ConnectionError, a classe-mãe delas.

As novas tentativas por código de status são uma camada separada (Códigos de status HTTP no web scraping), e a rotação também (Como rotacionar proxies em Python).

python
"""Encontra a causa real por trás de "Max retries exceeded with url" e diz o que conferir."""
import re
import ssl
import time

import requests
from requests.adapters import HTTPAdapter
from urllib3.exceptions import (
    ConnectTimeoutError,
    NameResolutionError,
    NewConnectionError,
    ProxyError as Urllib3ProxyError,
)
from urllib3.util import Retry

PROXY = "http://user:pass@pr.proxynet.io:8000"  # http:// mesmo para destinos https://
TIMEOUT = (3.05, 20)  # segundos: (connect, read)


def make_session():
    """Uma sessão que repete só as conexões que falharam, duas vezes, e nada mais."""
    retry = Retry(
        total=2,
        connect=2,      # falhas de DNS, conexões recusadas e conexões com timeout
        read=False,     # ReadTimeout continua ReadTimeout: o servidor pode ter a requisição
        other=0,        # um proxy que recusou o túnel vai recusar de novo
        status=0,       # novas tentativas por código de status são de outra camada
        backoff_factor=0.5,
    )
    adapter = HTTPAdapter(max_retries=retry)
    session = requests.Session()
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    return session


def causes(exc):
    """A exceção e cada erro envolvido nela, do mais externo para o mais interno."""
    chain = []
    while exc is not None and all(exc is not seen for seen in chain):
        chain.append(exc)
        inner = None
        for candidate in (getattr(exc, "reason", None), getattr(exc, "original_error", None),
                          exc.__cause__, exc.__context__, *exc.args[:2]):
            if isinstance(candidate, BaseException):
                inner = candidate
                break
        exc = inner
    return chain


def explain(exc):
    """Uma linha: o que falhou, de que lado e o que conferir primeiro."""
    chain = causes(exc)
    text = " | ".join(str(e) for e in chain)
    side = "proxy" if any(isinstance(e, Urllib3ProxyError) for e in chain) else "target"

    tunnel = re.search(r"Tunnel connection failed: (\d{3})", text)
    if tunnel:
        code = tunnel.group(1)
        if code == "407":
            return "proxy asked for credentials (407): check user:pass or the IP whitelist"
        if code == "403":
            return "proxy refused the CONNECT tunnel (403): check the target port and the proxy's allow rules"
        return f"proxy was reached but could not reach the target ({code}): check the target host and port"
    if "appears to only use HTTP" in text:
        return "proxy URL starts with https:// but the proxy speaks plain HTTP: write http://"
    if any(isinstance(e, NameResolutionError) for e in chain):
        host = re.search(r"Failed to resolve '([^']+)'", text)
        return f"{side} name {host.group(1) if host else ''} does not resolve: check spelling, DNS and VPN"
    if any(isinstance(e, ssl.SSLCertVerificationError) for e in chain):
        return "certificate not trusted: update certifi or set REQUESTS_CA_BUNDLE to your company root CA"
    if isinstance(exc, requests.exceptions.ReadTimeout):
        return "connected, but no answer within the read timeout: the server may have the request"
    if any(isinstance(e, NewConnectionError) for e in chain):
        return f"{side} refused the connection: wrong port, service down, or a firewall rejects it"
    if any(isinstance(e, ConnectTimeoutError) for e in chain):
        return f"no TCP connection to the {side} within the connect timeout: check address, port, firewall"
    return f"unrecognised, read the innermost error: {chain[-1]!r}"


def fetch(session, url, proxy=PROXY):
    """Faz GET em uma URL e imprime o status, ou o diagnóstico se a requisição falhar."""
    proxies = {"http": proxy, "https": proxy} if proxy else None  # por requisição: variáveis de ambiente não sobrescrevem
    start = time.monotonic()
    try:
        resp = session.get(url, proxies=proxies, timeout=TIMEOUT)
    except requests.exceptions.ProxyError as exc:      # antes de ConnectionError: é uma subclasse dela
        kind, error = "ProxyError", exc
    except requests.exceptions.SSLError as exc:        # também é um ConnectionError
        kind, error = "SSLError", exc
    except requests.exceptions.ConnectTimeout as exc:  # é um ConnectionError e um Timeout ao mesmo tempo
        kind, error = "ConnectTimeout", exc
    except requests.exceptions.ReadTimeout as exc:     # nunca vem envolvido em "Max retries exceeded"
        kind, error = "ReadTimeout", exc
    except requests.exceptions.ConnectionError as exc:
        kind, error = "ConnectionError", exc
    else:
        print(f"{'OK':<16}{time.monotonic() - start:6.2f}s  {url}  HTTP {resp.status_code}")
        return resp
    print(f"{kind:<16}{time.monotonic() - start:6.2f}s  {url}\n{'':<24}{explain(error)}")
    return None


if __name__ == "__main__":
    session = make_session()
    for url in ["https://httpbin.org/ip", "https://example.com/"]:
        fetch(session, url)

No urllib3 2.x, NameResolutionError é subclasse de NewConnectionError, que por sua vez é subclasse de ConnectTimeoutError, então explain() testa primeiro a classe mais específica. O script só precisa de pip install requests.

Como fica a saída

Rodamos fetch() no Windows 11 uma vez por caso: um proxy de teste local (senha certa e errada, porta fechada, nome digitado errado, esquema https://), um segundo proxy que recusa todo CONNECT e hosts reais para os casos de certificado e timeout. O timeout de leitura foi de 5 segundos:

text
OK                0.77s  https://httpbin.org/ip  HTTP 200
ProxyError        0.02s  https://httpbin.org/ip
                        proxy asked for credentials (407): check user:pass or the IP whitelist
ProxyError        0.00s  https://example.com/
                        proxy refused the CONNECT tunnel (403): check the target port and the proxy's allow rules
ProxyError        0.02s  https://no-such-host.invalid/
                        proxy was reached but could not reach the target (502): check the target host and port
ProxyError        7.10s  https://httpbin.org/ip
                        proxy refused the connection: wrong port, service down, or a firewall rejects it
ProxyError        1.02s  https://httpbin.org/ip
                        proxy name pr.proxynet.invalid does not resolve: check spelling, DNS and VPN
ProxyError        0.21s  https://httpbin.org/ip
                        proxy URL starts with https:// but the proxy speaks plain HTTP: write http://
SSLError          0.63s  https://self-signed.badssl.com/
                        certificate not trusted: update certifi or set REQUESTS_CA_BUNDLE to your company root CA
ConnectTimeout   10.16s  http://10.255.255.1/
                        no TCP connection to the target within the connect timeout: check address, port, firewall
ReadTimeout       5.02s  http://127.0.0.1:8082/
                        connected, but no answer within the read timeout: the server may have the request
ConnectionError  13.12s  http://localhost:8083/
                        target refused the connection: wrong port, service down, or a firewall rejects it

Os túneis recusados falharam em milissegundos porque o other=0 os interrompeu. A porta fechada do proxy levou três tentativas de cerca de dois segundos mais um segundo de backoff; o timeout de conexão, três vezes 3,05 segundos mais o backoff; e localhost, 13 segundos, porque cada tentativa testou IPv6 e depois IPv4. O 502 veio do nosso proxy de teste, que não conseguiu resolver o destino.

Onde você encontra esse erro

  • Scraping com proxy: os erros de proxy aparecem aqui antes de qualquer código de status (extração de dados).
  • Builds de CI e Docker atrás de um proxy corporativo: os builds muitas vezes não herdam as configurações de proxy do host, e localhost é o próprio contêiner (Configurar proxy no Linux).
  • Integrações de API com IP de saída fixo: uma recusa de túnel parece uma queda da API (IP estático para API).
  • Teste de um proxy novo: rode uma requisição com timeout antes de um trabalho inteiro (Como testar um proxy).
  • Automação de navegador: a mesma falha de túnel aparece como ERR_TUNNEL_CONNECTION_FAILED (Playwright com proxy).
  • Redes corporativas: um firewall e um proxy filtram as conexões ao mesmo tempo (Proxy ou firewall).

Erros comuns

  • Aumentar o número de novas tentativas. Uma causa permanente continua permanente; você só espera mais.
  • Culpar o destino porque o nome dele está na linha do pool. Em URLs https://, o proxy só aparece entre parênteses.
  • Esquecer uma variável HTTPS_PROXY antiga. Ela pode substituir session.proxies sem avisar.
  • Deixar verify=False em produção. A documentação do Requests avisa que isso expõe você a ataques man-in-the-middle. Atualize o certifi ou defina REQUESTS_CA_BUNDLE; para um proxy local de depuração, veja Proxy MITM.
  • Capturar ConnectionError primeiro. Ele engole ProxyError, SSLError e ConnectTimeout.
  • Confundir 403 e 407 no túnel. Um é uma regra; o outro, credenciais.
  • Ler só a última linha do pip. A causa está nas linhas WARNING acima dela.

Guia de decisão

O que você vêO que fazer
NameResolutionError em Caused byCorrija o nome que falhou (host do proxy ou URL); sem novas tentativas
ProxyError com NewConnectionErrorCopie de novo o host e a porta do proxy; confira o firewall local
Tunnel connection failed: 403Confira a porta de destino, o tipo e a porta do proxy e as regras de permissão
Tunnel connection failed: 407Confira as credenciais ou a whitelist de IP
SSLError: CERTIFICATE_VERIFY_FAILEDAtualize o certifi ou defina REQUESTS_CA_BUNDLE (pip: --cert)
As chamadas travam ou dão timeout de vez em quandotimeout=(3.05, 20) mais um Retry só para conexões
O pip diz "No matching distribution found"Leia a linha WARNING: Retrying

Perguntas frequentes

Aumentar o número de novas tentativas resolve "Max retries exceeded"?

Só quando a rede cai por um instante. Para um nome que não resolve, uma porta fechada ou um túnel recusado, toda nova tentativa falha do mesmo jeito. Leia primeiro a parte Caused by.

Qual é o timeout padrão do Python Requests?

Não existe: sem timeout=, uma requisição pode esperar indefinidamente. Dê a cada chamada uma tupla (connect, read).

O timeout do Requests é em segundos ou milissegundos?

Segundos. Um float como 3.05 funciona; um número só define as duas fases, e uma tupla como (3.05, 20) define cada uma separadamente.

Posso usar verify=False para CERTIFICATE_VERIFY_FAILED?

Só para um teste local rápido, porque isso deixa qualquer um no caminho ler ou alterar o tráfego. A correção duradoura é um certifi atualizado ou, atrás de um proxy corporativo que inspeciona TLS, o certificado raiz desse proxy em REQUESTS_CA_BUNDLE.

Por que o pip diz "No matching distribution found" se o pacote existe?

O pip não conseguiu chegar ao índice de pacotes, então não encontrou nenhuma versão. As linhas WARNING: Retrying ... after connection broken by acima dizem a causa real, como Tunnel connection failed: 403 Forbidden.

Por que recebo esse erro ao chamar localhost:8000?

Nada escuta nessa porta: o servidor está parado, usa outra porta, ou o seu código roda no Docker, onde localhost é o contêiner. O erro mais interno é [Errno 111] ou [WinError 10061]. Para descobrir qual programa ocupa uma porta, veja o nosso artigo O que é a porta 8080?

Em resumo

"Max retries exceeded with url" é uma mensagem que envolve o erro real: a causa vem depois de Caused by, e a mensagem aparece depois de uma única tentativa porque o Requests não faz novas tentativas por padrão. Em erros de proxy, diferencie uma falha no caminho até o proxy de um túnel que o proxy recusou, e mantenha http:// na URL do proxy. Dê a toda requisição uma tupla de timeout e repita só as falhas de conexão. Teste uma configuração nova primeiro com uma única requisição (como testar um proxy) e compare as opções na nossa página de serviços de proxy.