Para un diagnóstico pequeño de proxy con urllib3, usa ProxyManager con los reintentos desactivados. Así se informa del primer intento en vez de dedicar más tiempo a una entrada que ha dejado de funcionar. En un proyecto gestionado con uv:

uv add urllib3

Sustituye el punto de documentación por un proxy HTTP de tu servicio o de la lista de proxies HTTP y realiza la solicitud mediante ese gestor:

import urllib3

proxy = urllib3.ProxyManager(
    "http://203.0.113.10:8080",
    timeout=urllib3.Timeout(connect=5, read=10),
    retries=False,
)

try:
    response = proxy.request("GET", "https://example.com/")
    print(response.status)
    print(response.data.decode("utf-8", errors="replace")[:200])
finally:
    proxy.clear()

Lee primero response.status y después inspecciona response.data. Son campos de urllib3; status_code y text al estilo de Requests no los sustituyen. El rechazo de un sitio puede llegar por un proxy funcional. En cambio, una excepción antes de la respuesta indica que no se ha podido completar la solicitud.

retries=False es una elección de diagnóstico, no una política de reintentos de producción. Los ajustes de conexión de 5 segundos y lectura de 10 segundos limitan sus propias fases; no suman un plazo total garantizado de 15 segundos. El DNS y el progreso de la respuesta pueden afectar la espera total.

El ejemplo precarga el cuerpo y vacía los grupos de conexiones del gestor al final. Para solicitudes repetidas por el mismo punto, conserva ese gestor hasta terminar la carga de trabajo para reutilizar sus conexiones. Cambiar a preload_content=False modifica ese ciclo de vida: quien llama debe leer y liberar la respuesta en flujo.

Elige el gestor que corresponda al servicio que escucha. Un PoolManager normal no empieza a usar proxies porque se almacene una URL en otro lugar; SOCKS usa urllib3.contrib.socks.SOCKSProxyManager y sus dependencias opcionales. El código anterior sigue la vía HTTP de ProxyManager.

Artículos relacionados