---
title: "Gestión de solicitudes fallidas en Python"
slug: retry-failed-requests-python
date: 2026-02-16T07:46:48+00:00
modified: 2026-02-16T07:46:49+00:00
permalink: https://brightdata.es/blog/datos-web/retry-failed-requests-python
type: blog
---

[ Blog ](https://brightdata.es/blog "Blog") / [Datos web](https://brightdata.es/blog/datos-web)







 [Datos web](https://brightdata.es/blog/datos-web)

# Gestión de solicitudes fallidas en Python

Aprenda a gestionar las solicitudes HTTP fallidas en Python con estrategias de reintento eficaces y lógica personalizada.

 9 min de lectura





 [ ![Jacob Nulty](https://media.brightdata.es/2024/12/Jacob-Nulty-50x50.jpg) ](https://brightdata.com/blog/authors/jake-nulty)

 [Jake Nulty

Technical Writer

 ](https://brightdata.com/blog/authors/jake-nulty)





 ![Managing Failed Requests in Python blog image](https://media.brightdata.es/2025/02/Managing-Failed-Requests-in-Python-blog-image.svg)





Cuando se trabaja con HTTP, las solicitudes fallidas son una realidad inevitable que hay que afrontar. En el desarrollo web, un estado 200 indica una *buena respuesta*. Sin embargo, no siempre obtenemos un 200, y esta guía le ayudará a comprender cómo manejar estos códigos de estado distintos de 200.

Según [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), los códigos de estado se pueden dividir en las siguientes categorías:

- **100-199**: Respuestas informativas
- **200-299**: Respuestas correctas
- **300-399**: Mensajes de redireccionamiento
- **400-499**: Mensajes de error del cliente
- **500-599**: Mensajes de error del servidor

## <a></a>¿Qué son los códigos de estado?

[Los códigos de error](/blog/proxy-101/proxy-error-codes) son importantes. Al crear programas del lado del cliente, como los Scrapers web, debemos centrarnos principalmente en los códigos de estado del rango 400+ y 500+. Los códigos del rango 400 suelen abarcar errores del lado del cliente, como problemas de autenticación, limitación de velocidad, tiempos de espera y el famoso error 404: Archivo no encontrado. En el rango 500, generalmente nos encontramos con problemas del servidor.

Durante décadas, Mozilla ha documentado los estándares de desarrollo web del [W3C](https://www.w3.org/) y [el IETF](https://www.ietf.org/). A continuación se muestra una lista de códigos de error comunes con los que te puedes encontrar. Esta lista no es exhaustiva. Estos errores provienen de [la documentación oficial](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) de Mozilla. Dependiendo del sitio de destino, los códigos pueden variar ligeramente, pero la lógica debe seguir siendo la misma.

**Código de estado****Significado****Descripción**400Solicitud incorrectaCompruebe el formato de su solicitud401No autorizadoCompruebe su clave API403ProhibidoNo puede acceder a estos datos404No encontradoEl sitio/punto final no existe408Tiempo de espera de la solicitud agotadoSe ha agotado el tiempo de espera de la solicitud, inténtelo de nuevo429Demasiadas solicitudesReduzca la velocidad de sus solicitudes500Error interno del servidorError genérico del servidor, reintente la solicitud501No implementadoEl servidor aún no admite esta función.502Puerta de enlace incorrectaRespuesta fallida de un servidor ascendente.503Servicio no disponibleEl servidor está temporalmente inactivo, inténtelo más tarde.504Tiempo de espera de la puerta de enlace agotadoSe ha agotado el tiempo de espera del servidor ascendente## <a></a>Estrategias de reintento

Al implementar un mecanismo de reintento, puede utilizar bibliotecas precompiladas como HTTPAdapter y Tenacity. Dependiendo de su caso, es posible que incluso desee escribir su propia lógica de reintento.

Normalmente, queremos un límite de reintentos y una estrategia para retroceder. Necesitamos un límite para no quedarnos atrapados en un bucle infinito de reintentos. Necesitamos retroceder poco a poco para respetar el servidor host. Cuando las solicitudes llegan demasiado rápido, te bloquean o sobrecargan el servidor.

- **Límites de reintentos**: Debe establecer un límite. Después de X reintentos, su Scraper se dará por vencido.
- **Algoritmo de retroceso**: este es relativamente sencillo. Debes empezar con un pequeño retroceso y aumentarlo con cada reintento. Queremos empezar con 0,3, luego aumentar a 0,6, 1,2 y así sucesivamente.

**Queremos reintentar nuestras solicitudes hasta un límite determinado. Después de cada solicitud fallida, queremos esperar un poco más de tiempo.**

## <a></a>HTTPAdapter

Con HTTPAdapter, necesitamos configurar tres cosas: `total`, `backoff_factor` y `status_forcelist`. `allowed_methods` no es realmente un requisito, pero hace que nuestro código sea más seguro al ayudar a definir nuestras condiciones de reintento. En el código siguiente, utilizamos [httpbin](https://httpbin.org/) para forzar automáticamente un error y activar nuestra lógica de reintento.

```none
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

#crear una sesión
session = requests.Session()

#configurar los ajustes de reintento
retry = Retry(
    total=3,                  #máximo de reintentos
    backoff_factor=0.3,       #tiempo entre reintentos (retroceso exponencial)
    status_forcelist=(429, 500, 502, 503, 504), #códigos de estado para activar un reintento
    allowed_methods={"GET", "POST"}
)

#montar el adaptador con nuestra configuración personalizada
adaptador = HTTPAdapter(máximo_reintentos=reintento)
sesión.montar("http://", adaptador)
sesión.montar("https://", adaptador)

#realizar una solicitud con nuestra lógica de reintento
intentar:
    imprimir("Realizando una solicitud con lógica de reintento...")
    response = session.get("https://httpbin.org/status/500")
    response.raise_for_status()
    print("✅ Solicitud correcta:", response.status_code)
except requests.exceptions.RequestException as e:
    print("❌ Solicitud fallida tras los reintentos:", e)

```

Una vez que hayamos creado un objeto `Session`, hacemos lo siguiente:

- Creamos un objeto `Retry` y definimos lo siguiente:
    - `total`: El límite máximo para reintentar una solicitud.
    - `backoff_factor`: Tiempo de espera entre reintentos. Se ajusta exponencialmente a medida que aumentan nuestros reintentos.
    - `status_forcelist`: Una lista de códigos de estado incorrectos. Cualquier código de esta lista activará automáticamente un reintento.
- Cree un objeto `HTTPAdapter` con nuestra variable `de reintento`: `adapter = HTTPAdapter(max_retries=retry)`.
- Una vez creado el `adaptador`, lo montamos en los métodos HTTP y HTTPS utilizando `session.mount()`.

Al ejecutar este código, se ejecutarán nuestros tres reintentos (`total=3`) y obtendrá el siguiente resultado.

```none
Realizando una solicitud con lógica de reintento...
❌ Solicitud fallida tras los reintentos: HTTPSConnectionPool(host='httpbin.org', port=443): Se ha superado el número máximo de reintentos con la URL: /status/500 (Causado por ResponseError('demasiadas respuestas de error 500'))
```

## <a></a>Tenacity

También puede utilizar [Tenacity](https://tenacity.readthedocs.io/en/latest/), una popular biblioteca de código abierto para reintentos en Python. No se limita a HTTP, pero nos ofrece una forma expresiva y comprensible de implementar reintentos.

En primer lugar, debe instalarla.

```none
pip install tenacity

```

Una vez instalada, creamos un *decorador* y lo utilizamos para envolver una función de solicitudes. Con nuestro decorador `@retry`, añadimos los argumentos `stop`, `wait` y `retry`.

```none
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type, RetryError

#definir una estrategia de reintento
@retry(
    stop=stop_after_attempt(3),  #reintentar hasta 3 veces
    wait=wait_exponential(multiplier=0.3),  #retroceso exponencial
    retry=retry_if_exception_type(requests.exceptions.RequestException),  #reintentar en caso de fallos en la solicitud)

def make_request():
    print("Realizando una solicitud con lógica de reintento...")
    response = requests.get("https://httpbin.org/status/500")
    respuesta.raise_for_status()
    imprimir("✅ Solicitud exitosa:", respuesta.status_code)
    devolver respuesta

# Intentar realizar la solicitud
intentar:
    realizar_solicitud()
excepto RetryError como e:
    imprimir("❌ Solicitud fallida después de todos los reintentos:", e)

```

La lógica y la configuración aquí son muy similares a nuestro primer ejemplo con HTTPAdapter.

- `stop=stop_after_attempt(3)`: Esto le indica a `tenacity` que se dé por vencido después de 3 intentos fallidos.
- `wait=wait_exponential(multiplier=0.3)` utiliza la misma espera que utilizamos antes. También retrocede exponencialmente, igual que antes.
- `retry=retry_if_exception_type(requests.exceptions.RequestException)` le indica a `tenacity` que utilice esta lógica cada vez que se produzca una `RequestException`.
- `make_request()` realiza una solicitud a nuestro punto final de error. Recibe todos los rasgos del decorador que hemos creado anteriormente.

Al ejecutar este código, se obtiene un resultado similar.

```none
Realizando una solicitud con lógica de reintento...
Realizando una solicitud con lógica de reintento...
Realizando una solicitud con lógica de reintento...
❌ La solicitud falló después de todos los reintentos: RetryError[<Future at 0x75e762970760 state=finished raised HTTPError>]
```

## <a></a>Cree su propio mecanismo de reintento

También puede crear su propio mecanismo de reintento. Cuando se trata de código personalizado, a menudo esta puede ser la mejor opción. Con una cantidad relativamente pequeña de código, podemos lograr el mismo efecto que obtenemos de estas bibliotecas.

En el código siguiente, necesitamos importar `sleep` para nuestro retroceso exponencial. Una vez más, establecemos nuestra configuración: `total`, `backoff_factor` y `bad_codes`. A continuación, utilizamos un bucle `while` para mantener nuestra lógica de reintento. `Mientras` aún tengamos intentos y no hayamos tenido éxito, intentamos la solicitud.

```none
import requests
from time import sleep

#crear una sesión
session = requests.Session()

#definir nuestra configuración de reintentos
total = 3
backoff_factor = 0.3
bad_codes = [429, 500, 502, 503, 504]

#contador de intentos y booleano de éxito
current_tries = 0
success = False

#intentar hasta que tengamos éxito o se agoten los intentos
while current_tries < total and not success:
    try:
        print("Realizando una solicitud con lógica de reintento...")
        response = session.get("https://httpbin.org/status/500")
        if response.status_code in bad_codes:
            raise requests.exceptions.HTTPError(f"Recibido {response.status_code}, activando reintento")
        print("✅ Solicitud exitosa:", response.status_code)
        success = True
    except requests.exceptions.RequestException as e:
        print(f"❌ Solicitud fallida: {e}, reintentos restantes: {total-current_tries}")
        sleep(backoff_factor)
        backoff_factor = backoff_factor * 2
        current_tries+=1
```

La lógica real aquí se maneja mediante un simple bucle `while`.

- Si `response.status_code` está en nuestra lista de `bad_codes`, lanzamos una excepción.
- Si una solicitud falla, hacemos lo siguiente:
    - Imprimimos un mensaje de error en la consola.
    - `sleep(backoff_factor)` espera antes de enviar la siguiente solicitud.
    - `backoff_factor = backoff_factor * 2` duplica nuestro `backoff_factor` para el siguiente intento.
    - Incrementamos `current_tries` para no permanecer en el bucle indefinidamente.

Este es el resultado de nuestra lógica de reintento personalizada.

```none
Realizando una solicitud con lógica de reintento...
❌ Solicitud fallida: se recibió 500, se activa el reintento, reintentos restantes: 3
Realizando una solicitud con lógica de reintento...
❌ Solicitud fallida: se recibió 500, se activa el reintento, reintentos restantes: 2
Realizando una solicitud con lógica de reintento...
❌ Solicitud fallida: se recibió 500, se activa el reintento, reintentos restantes: 1
```

## <a></a>Superar los bloqueos

En la práctica, algunos sitios te bloquearán. Lo mejor es [utilizar](/blog/proxy-101/proxy-with-python-requests) siempre [un Proxy con las solicitudes de Python](/blog/proxy-101/proxy-with-python-requests). Con un Proxy, tu solicitud se enruta a través de una máquina diferente. Esto protegerá tu identidad y evitará que tu dirección IP sea bloqueada por el sitio de destino. Incluso tenemos una [guía detallada](/blog/proxy-101/how-to-bypass-an-ip-ban) sobre cómo superar los bloqueos de IP. Nuestros [Proxies residenciales](/proxy-types/residential-proxies) están diseñados para ayudarte a superar estos retos.

## <a></a>Conclusión

Ahora ya sabe cómo gestionar las solicitudes HTTP fallidas en Python. Tanto si está escribiendo un Scraper, un cliente API o herramientas de automatización, ya sabe cómo gestionar estos problemas. Para evitar todo tipo de solicitudes fallidas, hemos desarrollado productos como la [API Web Unlocker](/products/web-unlocker) y [el Navegador de scraping](/products/scraping-browser). Estas herramientas gestionan automáticamente las medidas antibots, [los retos CAPTCHA](/blog/web-data/what-is-a-captcha) y los bloqueos de IP, lo que garantiza un Scraping web fluido y eficiente incluso en los sitios web más difíciles.

Regístrese ahora y comience su prueba gratuita hoy mismo.



Contactar ventasPrueba gratuita![google social icon](/wp-content/themes/brightdata/assets/images/ic_google.svg)









 Tabla de Contenidos













 [ ](https://news.ycombinator.com/submitlink?t=Gesti%C3%B3n+de+solicitudes+fallidas+en+Python&u=https://brightdata.es/blog/datos-web/retry-failed-requests-python) [ ](https://www.linkedin.com/shareArticle?mini=true&title=Gesti%C3%B3n+de+solicitudes+fallidas+en+Python&url=https://brightdata.es/blog/datos-web/retry-failed-requests-python) [ ](http://www.reddit.com/submit?title=Gesti%C3%B3n+de+solicitudes+fallidas+en+Python&url=https://brightdata.es/blog/datos-web/retry-failed-requests-python)







##  Usted también puede estar interesado en

 [ ![OpenHuman with Bright Data](https://media.brightdata.es/2026/09/OpenHuman-with-Bright-Data.png) ](https://brightdata.es/blog/ai/openhuman-with-bright-data "Acceso Web Listo para Producción en OpenHuman a Través de la CLI de Bright Data")

 [AI



 ![Antonello Zanini](https://media.brightdata.es/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Acceso Web Listo para Producción en OpenHuman a Través de la CLI de Bright Data

Integra la CLI de Bright Data con OpenHuman para habilitar acceso web listo para producción y recopilación de datos para agentes de IA.



 09-Sep-2026

 14 min de lectura

 ](https://brightdata.es/blog/ai/openhuman-with-bright-data)

 [ ![Multimodal Web Scraping with MiniMax](https://media.brightdata.es/2026/09/Multimodal-Web-Scraping-with-MiniMax.png) ](https://brightdata.es/blog/datos-web/multimodal-web-scraping-with-minimax "Scraping Web Multimodal con MiniMax")

 [Datos web



 ![Antonello Zanini](https://media.brightdata.es/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Scraping Web Multimodal con MiniMax

Combina Bright Data Web Unlocker con la visión de MiniMax M3 para extraer datos estructurados de imágenes y capturas de pantalla de páginas web.



 09-Sep-2026

 5 min de lectura

 ](https://brightdata.es/blog/datos-web/multimodal-web-scraping-with-minimax)

 [ ![The 10 Best CLI Tools for Codex in 2026](https://media.brightdata.es/2026/08/The-10-Best-CLI-Tools-for-Codex-in-2026.png) ](https://brightdata.es/blog/ai/best-cli-tools-for-codex "Las 10 mejores herramientas CLI para Codex en 2026 – Probadas y clasificadas")

 [AI



 ![Daniel Shashko](https://media.brightdata.es/2022/04/Daniel-Shashko-2-50x50.png)

Daniel Shashko

Web Data &amp; AI Expert





### Las 10 mejores herramientas CLI para Codex en 2026 – Probadas y clasificadas

Las 10 herramientas CLI que hacen a Codex más rápido y capaz, comenzando con la Bright Data CLI para acceso web real desde dentro del sandbox.



 06-Sep-2026

 24 min de lectura

 ](https://brightdata.es/blog/ai/best-cli-tools-for-codex)
