Las líneas más frecuentes en el registro de un scraper no son las respuestas 200 correctas, sino los códigos 403, 429 y 503 que aparecen entre ellas. Cada uno de estos códigos describe un problema distinto y requiere una reacción distinta. Un script que los trata todos igual, «reintentar tres veces», o bien insiste contra un bloqueo permanente y empeora las cosas, o bien pierde datos por un problema temporal que se habría resuelto en unos segundos.
En este artículo explicamos cómo leer los códigos de estado HTTP, qué significan los códigos con los que más te encuentras en el scraping (403, 407, 429 y 503) y las causas probables que hay detrás. Después vemos 502, 504 y los errores de conexión, cómo usar la cabecera Retry-After, y reunimos en una sola tabla qué códigos reintentar y ante cuáles parar. Al final hay un ejemplo en Python probado que aplica estas decisiones.
¿Cómo se leen los códigos de estado HTTP?
Toda respuesta HTTP empieza con un código de estado de tres dígitos. El primer dígito fija la clase de la respuesta. Los códigos están definidos en la sección 15 de RFC 9110; la lista de códigos de estado de MDN también da explicaciones breves y ejemplos de cada uno.
| Clase | Significado | En términos de scraping |
|---|---|---|
1xx | Informativo, petición en curso | En la práctica no los verás |
2xx | Éxito | La página llegó, pero revisa igualmente su contenido |
3xx | Redirección | La dirección cambió o te enviaron a una página de inicio de sesión |
4xx | Problema del lado del cliente | Algo falla en tu petición, tu identidad o tu velocidad |
5xx | Problema del lado del servidor | El servidor, la pasarela o el proxy no pudieron completar la petición |
La distinción más importante para el scraping es esta: la mayoría de los códigos 4xx dan el mismo resultado cuando envías exactamente la misma petición otra vez. Tienes que cambiar algo de la petición. La mayoría de los códigos 5xx son temporales, y la misma petición puede funcionar tras esperar un rato. 429 es la excepción: es un código 4xx, pero se resuelve esperando.
Una advertencia más que vale para cualquier código: ver 200 no significa que hayas obtenido los datos que querías. Los sistemas de protección de bots a menudo devuelven una página de verificación con código 200. Antes de dar una respuesta por correcta, comprueba que la página contiene un elemento que esperas (un título de producto, un campo de precio).
¿Qué significa 403 Forbidden?
403 indica que el servidor entendió tu petición pero se niega a atenderla. Según RFC 9110, el servidor no está obligado a explicar por qué. La diferencia con 401 Unauthorized, que se usa cuando falta autenticación, es que con 403 añadir credenciales normalmente no cambia el resultado.
Causas probables de un 403 en el scraping:
- Reputación o tipo de IP. Los sitios que restringen el tráfico de direcciones de centros de datos devuelven
403directamente a esas direcciones. - Restricción geográfica. El sitio solo permite el acceso desde ciertos países.
- Cabeceras ausentes o incoherentes. El valor
User-Agentpredeterminado de la librería o una combinación de cabeceras que nunca envía un navegador. - Una regla de firewall de aplicaciones web (WAF). La petición coincidió con una regla de seguridad.
- Bloqueo por tu tráfico anterior. Una dirección IP que supera el límite de velocidad durante mucho tiempo puede empezar a recibir
403en lugar de429al cabo de un tiempo. - Una página que de verdad requiere autorización. Una ruta a la que no se puede llegar sin iniciar sesión.
Qué hacer: no vuelvas a enviar la misma petición enseguida. Prueba a abrir la dirección en un navegador real con la misma IP. Si se abre en el navegador, el problema está en tu propia petición (cabeceras, velocidad); si no, el problema es la IP o la ubicación. Explicamos en detalle las causas de los bloqueos y las soluciones legítimas en Cómo hacer web scraping sin que te bloqueen.
¿Qué significa 407 Proxy Authentication Required?
407 no viene del sitio de destino, sino del servidor proxy. Significa que el proxy quiere que demuestres tu identidad antes de reenviar la petición al destino. Así que, cuando ves un 407, tienes que revisar tu conexión con el proxy, no las reglas del sitio de destino.
Causas probables:
- El usuario o la contraseña son incorrectos.
- La contraseña contiene caracteres especiales como
@,:o/que no están codificados dentro de la dirección del proxy (@→%40). - Se usa el método de lista blanca de IP, pero la dirección IP de la que viene la conexión no está en la lista.
- La librería no envía al proxy las credenciales incluidas en la dirección.
- Se ha agotado el saldo o la cuota de tráfico de la cuenta.
Las librerías muestran el 407 de formas distintas. En las peticiones HTTPS no se puede establecer el túnel del proxy, así que a menudo recibes una excepción en lugar de un objeto de respuesta: Python Requests lanza ProxyError, y HTTPX también lanza ProxyError; en Node.js, Axios devuelve un error con código de estado 407. Mostramos las diferencias entre librerías con ejemplos probados en Cómo usar un proxy en Node.js.
Qué hacer: no reintentes; corrige la configuración. Comprueba en la salida de curl -v si se envía la cabecera Proxy-Authorization; el comando está en Cómo usar un proxy con cURL. Recorremos paso a paso los dos métodos de autenticación y el diagnóstico del 407 en Autenticación de proxy: user:pass o lista blanca de IP.
¿Qué significa 429 Too Many Requests?
429 indica que enviaste demasiadas peticiones en un periodo determinado. El código está definido en la sección 4 de RFC 6585, que establece que el servidor puede enviar con la respuesta una cabecera Retry-After para indicar cuánto debes esperar.
Sobre qué se cuenta el límite de velocidad varía según el sitio:
- Por dirección IP: se suman las peticiones desde la misma dirección.
- Por sesión o cookie: se suman las peticiones de la misma sesión; cambiar de IP no reinicia el contador.
- Por clave de API: en las API oficiales, el límite suele ir ligado a la clave.
- Por endpoint: en endpoints pesados como las páginas de búsqueda, el límite es menor que en las páginas de producto.
Algunas API informan de tu cuota restante con cabeceras como X-RateLimit-Remaining y X-RateLimit-Reset. Estos nombres de cabecera no son estándar y cambian de un servicio a otro; consulta la documentación de la API que uses.
Qué hacer: si hay Retry-After, espera ese tiempo. Si no, aplica backoff exponencial: 1 segundo en el primer intento y después 2, 4 y 8 segundos, añadiendo un componente aleatorio a cada espera. Baja la concurrencia al mismo tiempo; si esperas y sigues a la misma velocidad, pronto volverás a recibir 429.
¿Qué significa 503 Service Unavailable?
503 indica que el servidor no puede atender la petición en este momento, pero que la situación es temporal. El mantenimiento, la sobrecarga o un servidor de aplicación caído detrás son causas típicas. Según RFC 9110, el servidor puede indicar con Retry-After cuándo volver a intentarlo.
En el scraping, 503 tiene dos caras distintas:
- Carga real o mantenimiento. El sitio devuelve
503a todo el mundo. No queda más que esperar. - Un bloqueo temporal de la protección de bots. Algunos sistemas de protección devuelven
503con una página de verificación al tráfico que consideran sospechoso. Si el cuerpo contiene una pantalla de verificación, el problema no es la carga del servidor sino tu propio tráfico.
Qué hacer: distingue los dos casos mirando el cuerpo. Si es carga real, espera con Retry-After o backoff exponencial. Si ves una página de verificación, revisa tu velocidad y tu identidad de cliente en lugar de reintentar.
502, 504 y errores de conexión
Un scraper que usa un proxy se topa con errores del propio proxy además de con las respuestas del sitio de destino. Estos códigos sirven para averiguar en qué eslabón de la cadena está el problema.
500 Internal Server Error: se produjo un error en la aplicación de destino. A veces es específico de una página. Puede reintentarse una o dos veces; si se repite, omite esa dirección.502 Bad Gateway: una pasarela intermedia (proxy, CDN o reverse proxy) no pudo obtener una respuesta válida del servidor que tiene detrás. En el contexto de un proxy, puede significar que el proxy no pudo llegar al destino. Reintenta tras una breve espera.504 Gateway Timeout: la pasarela no recibió a tiempo la respuesta del servidor de detrás. Aparece cuando el destino es lento o el punto de salida del proxy está lejos. Reintenta.408 Request Timeout: el servidor agotó el tiempo esperando a que se completara la petición. Reintenta.- Errores de conexión: no hay código; el cliente lanza una excepción. Conexión rechazada (
ECONNREFUSED), conexión restablecida (ECONNRESET), timeout, host no encontrado (ENOTFOUND), etc. Si la dirección o el puerto son incorrectos, ningún reintento lo arreglará; en situaciones temporales, como una caída de red, reintentar ayuda. - Códigos propios de CDN: algunas CDN usan códigos no estándar en el rango
520-526. Suelen describir problemas de conexión entre la CDN y el servidor propio del sitio.
404 Not Found y 410 Gone indican que la página no existe. En lugar de reintentar, quita la dirección de tu lista; si de repente ves muchos 404, puede que haya cambiado la estructura de URL del sitio.
¿Cómo se usa Retry-After?
La cabecera Retry-After puede llegar de dos formas:
- Un número de segundos:
Retry-After: 120→ espera 120 segundos. - Una fecha HTTP:
Retry-After: Wed, 16 Sep 2026 07:28:00 GMT→ inténtalo después de esa fecha.
Cuatro reglas para usarla bien:
- Si la cabecera está, no adivines; síguela. El tiempo que da el servidor es más preciso que cualquier backoff que calcules.
- Fija un límite superior. Si la cabecera indica algo largo, como varias horas, deja la dirección para una ejecución posterior en lugar de dejar tu script colgado todo ese tiempo.
- Aplica la espera al sitio, no solo a esa petición. Si retienes la petición que recibió el
429pero sigues enviando en paralelo otras peticiones al mismo sitio, el límite se sigue superando. - Interpreta también la forma de fecha. Un código que solo espera un número ignora una cabecera que llega como fecha. Compartimos una función de Python que gestiona ambas formas en Cómo hacer web scraping sin que te bloqueen.
¿Qué códigos se reintentan y ante cuáles se para?
| Código | Significado | Causa probable en el scraping | Qué hacer |
|---|---|---|---|
200 | Éxito | La página llegó, pero puede ser una página de verificación | Comprueba que el contenido tiene un elemento esperado |
301 / 302 | Redirección | La dirección cambió o te enviaron a una página de inicio de sesión | Sigue la redirección; si es una página de inicio de sesión, revisa la sesión |
400 | Petición incorrecta | Parámetro o cuerpo defectuoso | Para y corrige la petición |
401 | Se requiere autenticación | Falta el inicio de sesión o la clave de API | Para y añade credenciales |
403 | Rechazada | Tipo de IP, ubicación, cabeceras, regla WAF | Para y diagnostica |
404 / 410 | Página no encontrada | Producto eliminado, estructura de URL cambiada | Quítala de la lista |
407 | Se requiere autenticación del proxy | Contraseña incorrecta, carácter sin codificar, lista blanca | Para y corrige la configuración del proxy |
408 | Timeout de la petición | Conexión lenta | Reintenta |
429 | Demasiadas peticiones | Límite de velocidad superado | Espera lo que indique Retry-After, ve más despacio |
500 | Error del servidor | Error en la aplicación de destino | Prueba unas pocas veces y luego omite |
502 | Pasarela incorrecta | El proxy o la CDN no pudieron llegar al destino | Reintenta tras una breve espera |
503 | Servicio no disponible | Carga, mantenimiento o página de protección | Revisa el cuerpo; espera con Retry-After |
504 | Timeout de pasarela | Destino lento, punto de salida lejano | Reintenta; usa una ubicación más cercana si hace falta |
| Error de conexión | Sin respuesta | Caída de red, dirección o puerto incorrectos | Reintenta si es temporal; corrige la configuración si es permanente |
Ejemplo: reintentos que deciden según el código de estado
El ejemplo siguiente usa el cliente asíncrono de HTTPX. Con los códigos 408, 429 y 5xx respeta la cabecera Retry-After; si no hay cabecera, aplica backoff exponencial con un componente aleatorio. Con los códigos en los que reintentar no cambia el resultado, como 403, 404 y 407, se detiene lanzando una excepción aparte. Los errores de autenticación del proxy (que en las peticiones HTTPS llegan como ProxyError) también entran en este grupo.
import asyncio
import random
import httpx
RETRY_STATUS = {408, 429, 500, 502, 503, 504}
STOP_STATUS = {400, 401, 403, 404, 407, 410}
class StopScraping(Exception):
"""Casos en los que reintentar no cambia el resultado."""
def backoff(response, attempt, base=1.0, cap=60.0):
retry_after = response.headers.get("Retry-After") if response is not None else None
if retry_after and retry_after.isdigit():
return min(int(retry_after), cap)
return min(cap, base * 2**attempt) * random.uniform(0.5, 1.0)
async def fetch(client, url, attempts=5):
for attempt in range(attempts):
response = None
try:
response = await client.get(url)
except httpx.ProxyError as exc:
raise StopScraping(f"Error de proxy (revisa tus credenciales): {exc}") from exc
except httpx.TransportError:
pass # conexión caída, timeout: se puede reintentar
else:
status = response.status_code
if status < 400:
return response
if status in STOP_STATUS:
raise StopScraping(f"{url}: HTTP {status}, no se reintentará")
if status not in RETRY_STATUS:
return response
await asyncio.sleep(backoff(response, attempt))
raise RuntimeError(f"{url}: sin resultado tras {attempts} intentos")
async def main():
proxy = "http://user:pass@pr.proxynet.io:8000"
async with httpx.AsyncClient(proxy=proxy, timeout=20, follow_redirects=True) as client:
urls = ["https://example.com/product/1", "https://example.com/product/2"]
results = await asyncio.gather(*(fetch(client, u) for u in urls), return_exceptions=True)
for url, result in zip(urls, results):
print(url, result if isinstance(result, Exception) else result.status_code)
asyncio.run(main())Amplía el ejemplo en dos puntos para tu propio trabajo. Primero, asyncio.gather inicia todas las direcciones a la vez; en un trabajo real, limita con asyncio.Semaphore el número de peticiones simultáneas al mismo sitio. Segundo, Retry-After también puede llegar como fecha HTTP; si necesitas interpretar esa forma, usa la función enlazada más arriba.
Registrar y vigilar los errores
Usa los códigos de estado no solo para decidir en el momento, sino también para vigilar la salud del trabajo. Registrar estas cifras en cada ejecución te ayuda a detectar problemas pronto:
- Respuestas por código: si sube la tasa de
429, vas demasiado rápido; si sube la de403, algo ha cambiado en el lado de la IP o de las cabeceras. - Distribución por sitio y endpoint: ¿el problema está en un sitio o en todos? Los errores que suben a la vez en todos los sitios suelen apuntar al proxy o a la red.
- Número de reintentos y tiempo total de espera: si los reintentos ocupan buena parte del tiempo del trabajo, el ajuste de concurrencia es incorrecto.
- Respuestas
200sin el elemento esperado: la única señal de una pérdida de datos silenciosa.
Casos de uso
- Seguimiento diario de precios: los productos que devuelven
404se quitan de la lista, y en la siguiente ejecución se baja la concurrencia en los sitios que devolvieron429. La configuración general está en nuestra página de solución de extracción de datos. - Recogida de catálogos de muchos sitios: una tasa de
403creciente en un sitio necesita un diagnóstico aparte para ese sitio; para repartir la carga se usa un Proxies rotativos. - Tu propio panel que necesita sesión: una redirección
302a la página de inicio de sesión puede indicar que la IP cambió en mitad de la sesión; para mantener la misma IP durante la sesión se prefiere un Proxies de sesión fija. - Una configuración de proxy nueva: si las primeras peticiones devuelven
407oProxyError, el problema no es el destino sino las credenciales.
Errores comunes
- Reintentar el mismo número de veces ante cualquier error. Repetir
403y407no cambia el resultado; solo genera tráfico innecesario. - No leer la cabecera
Retry-After. Volver antes de tiempo por tu cuenta cuando el servidor te dijo cuánto esperar. - No añadir un componente aleatorio al backoff. Cientos de peticiones que fallaron en el mismo momento se reintentan en el mismo momento y crean una nueva acumulación.
- Aceptar una respuesta
200sin mirar el contenido. Las páginas de verificación producen datos vacíos en silencio. - Tratar el
407como un error del sitio de destino. Tienes que revisar la configuración de tu proxy, no el destino. - No poner límite a los reintentos. Un bucle que sigue para siempre ante un problema permanente desgasta tanto tus recursos como el sitio de destino.
Guía de decisión
| Lo que ves | Lo primero que hay que hacer |
|---|---|
429 | Espera lo que indique Retry-After, baja la concurrencia |
503 con una página de error normal | Espera y reintenta |
503 con una página de verificación | Para, revisa la velocidad y la identidad de cliente |
403 | Prueba con la misma IP en un navegador y diagnostica la causa |
407 o ProxyError | Revisa el usuario, la contraseña y la lista blanca del proxy |
502 / 504 | Reintenta tras una breve espera; si continúa, cambia la ubicación de salida |
404 / 410 | Quita la dirección de la lista |
200 pero sin datos | Comprueba si es una página de verificación o una carga dinámica |
Preguntas frecuentes
¿Qué diferencia hay entre 403 y 401?
401 Unauthorized indica que la petición requiere autenticación y que no enviaste credenciales válidas. 403 Forbidden indica que el servidor entendió la petición pero la rechaza con independencia de las credenciales. Con 401, añadir credenciales puede ser la solución; con 403, normalmente no.
¿Por qué el error 407 viene del proxy y no del sitio de destino?
Porque la petición nunca llegó al destino. El proxy te autentica antes de reenviar la conexión y, si la autenticación falla, responde él mismo. Por eso el 407 no tiene nada que ver con las reglas del sitio de destino.
¿Cambiar de IP tras un 429 es una solución?
Si el límite de velocidad se cuenta por IP, puede ayudar temporalmente, pero no cambia la velocidad que causó el problema, y no ayuda en absoluto si el límite es por sesión o por cuenta. La reacción correcta es esperar e ir más despacio; la rotación debe planificarse desde el principio para repartir la carga.
¿Cuánto debo esperar si no hay cabecera Retry-After?
Aplica backoff exponencial: empieza con unos segundos, duplica en cada intento, fija un límite superior y añade un componente aleatorio a cada espera. Si sigue fallando tras unos pocos intentos, deja la dirección para una ejecución posterior.
¿Un error 503 significa que el sitio está caído?
No siempre. También puede ser mantenimiento, carga temporal o un bloqueo de la protección de bots. Mira el cuerpo de la respuesta: ¿es un mensaje de mantenimiento, una página de error genérica o una pantalla de verificación?
Recibo errores 502 al usar un proxy. ¿Dónde está el problema?
502 indica que la pasarela intermedia no pudo obtener una respuesta válida del servidor de detrás. En el contexto de un proxy, puede significar que el proxy no pudo llegar al destino o que el destino cortó la conexión. Prueba la misma dirección sin proxy: si funciona sin proxy, el problema está en el punto de salida del proxy; si tampoco funciona sin proxy, el problema está en el sitio de destino.
En resumen
Los códigos de estado HTTP le dicen a tu scraper qué hacer: 429 y 503 piden esperar, 403 pide un diagnóstico, 407 pide corregir la configuración del proxy y 404 pide quitar la dirección. Si hay una cabecera Retry-After, síguela; si no, usa backoff exponencial con un componente aleatorio y pon límite a todo bucle de reintentos. No olvides revisar también el contenido de las respuestas 200. Encontrarás tipos de proxy adecuados para tu trabajo de recogida de datos en nuestros servicios de proxy.




