Errores
Todos los códigos de error de la API, qué los causa, cómo resolverlos y si se deben reintentar.
Todas las respuestas de error de Firecrawl usan la misma estructura JSON. Busca el valor de error (o el código de estado HTTP) en la tabla siguiente para identificar la causa, cómo corregirlo y si es seguro reintentar la solicitud.
Todas las respuestas que no son 2xx devuelven JSON con success: false en el nivel superior y un error de tipo cadena. Algunos endpoints incluyen campos adicionales (details, code) cuando hay más contexto disponible.
{
"success": false,
"error": "Unauthorized: Invalid token",
"details": "Optional structured details (only present on some errors)"
}| Campo | Tipo | Descripción |
|---|---|---|
success | boolean | Siempre false en caso de error. |
error | string | Mensaje de error comprensible para una persona. Úsalo para consultar la fila siguiente. |
details | any | Opcional. Errores de validación estructurados por campo, cuando corresponda. |
| HTTP | error (mensaje típico) | Causa | Solución | Reintentable |
|---|---|---|---|---|
| 400 | Bad Request / mensaje de validación | El cuerpo de la solicitud no pasó la validación del esquema (faltan campos o son inválidos). | Corrige la carga útil de la solicitud usando la referencia del endpoint. Revisa details para identificar los campos. | No |
| 400 | Invalid URL | Falta el campo url, está mal formado o usa un esquema no compatible. | Proporciona una URL absoluta http(s)://. | No |
| 401 | Unauthorized: Invalid token | Falta la API key, está mal formada o fue revocada. | Envía Authorization: Bearer fc-... con una clave válida desde el dashboard. | No |
| 402 | Payment Required: Insufficient credits | Los créditos del plan se agotaron o la facturación no está configurada. | Recarga créditos, habilita la recarga automática o actualiza tu plan. | No |
| 403 | Forbidden | La clave no tiene permisos para este endpoint o función. | Usa una clave con el alcance requerido o actualiza el plan que habilita esta función. | No |
| 404 | Not Found | El ID de trabajo, el recurso o la ruta del endpoint no existen. | Verifica el ID del recurso y la URL del endpoint. | No |
| 408 | Request Timeout | La página tardó más que el timeout de la solicitud en cargarse. | Aumenta timeout, simplifica las acciones o usa fastMode. | Sí, con backoff |
| 409 | Conflict | El recurso está en un estado que impide la operación (p. ej., ya fue eliminado). | Vuelve a consultar el estado y reconcílialo antes de reintentar. | No |
| 413 | Payload Too Large | El cuerpo de la solicitud superó el tamaño máximo permitido. | Reduce la carga útil (p. ej., un esquema más corto, menos URL por lote). | No |
| 422 | Unprocessable Entity / error de esquema de extracción | El esquema no es un JSON Schema válido o el modelo no pudo generar un resultado conforme. | Valida el esquema; flexibiliza los campos obligatorios; prueba con otro model. | A veces |
| 429 | Rate limit exceeded | Hay demasiadas solicitudes para el límite por minuto de tu plan. | Espera y reintenta después de los segundos indicados en Retry-After. Consulta Límites de tasa. | Sí, con backoff |
| 429 | Concurrency limit reached | Se alcanzó el límite de navegadores concurrentes de tu plan. | Espera a que terminen los trabajos en curso, reduce la concurrencia o actualiza tu plan. | Sí, con backoff |
| 500 | Internal Server Error | Error no controlado del lado del servidor. | Reintenta con backoff exponencial. Si persiste, contacta con soporte e indica el ID de la solicitud. | Sí, con backoff |
| 502 | Bad Gateway | El proxy upstream o el worker devolvió una respuesta no válida. | Reintenta con backoff. | Sí, con backoff |
| 503 | Service Unavailable | El servicio no puede procesar temporalmente la solicitud. | Reintenta con backoff. | Sí, con backoff |
| 504 | Gateway Timeout | La solicitud superó el timeout de la puerta de enlace (normalmente en crawls largos). | Usa los endpoints async de crawl/lote y consulta el estado en su lugar. | Sí, con backoff |
Para las respuestas 429, Firecrawl incluye una cabecera Retry-After (en segundos) cuando está disponible; espera al menos ese tiempo antes de reintentar.
Toma la columna Reintentable como referencia definitiva; no lo deduzcas solo a partir del estado HTTP. El patrón siguiente usa backoff exponencial con jitter y respeta Retry-After en respuestas 429.
import time
import random
import requests
RETRYABLE_STATUSES = {408, 429, 500, 502, 503, 504}
def request_with_retry(method, url, headers=None, json=None, max_attempts=5):
for attempt in range(max_attempts):
resp = requests.request(method, url, headers=headers, json=json)
if resp.status_code < 400 or resp.status_code not in RETRYABLE_STATUSES:
return resp
# Respeta Retry-After cuando esté presente; de lo contrario, usa backoff exponencial con jitter.
retry_after = resp.headers.get("Retry-After")
delay = float(retry_after) if retry_after else min(2 ** attempt, 30) + random.random()
time.sleep(delay)
return respLas respuestas 429 son el error reintentable más común. Los límites de tasa y de concurrencia por plan se documentan en Límites de tasa. Respeta siempre la cabecera Retry-After cuando esté presente, en lugar de reintentar de inmediato.