Al llamar a una API, 401 Unauthorized, 403 Forbidden y 429 Too Many Requests son los tres tipos de errores más comunes.
Todos pertenecen a los errores de cliente 4xx, pero las soluciones son completamente diferentes:
- 401: fallo de autenticación——el servidor no puede confirmar “quién eres”
- 403: acceso denegado——el servidor entiende la solicitud, pero no permite ejecutarla
- 429: demasiadas solicitudes——la velocidad de llamadas o el uso supera los límites
Si se reintenta directamente sin distinguir el tipo de error, no solo no se resolverá el problema, sino que también podría provocar una tormenta de reintentos e incluso hacer que la interfaz sea restringida aún más.
Este artículo explicará, mediante una lista de comprobación de diagnóstico, comandos curl y código Node.js, cómo manejar estos tres tipos de errores cuando se presentan.
¶ Entender 401, 403 y 429 con una tabla
| Código de estado | Significado principal | Causas comunes | Si se debe reintentar inmediatamente |
|---|---|---|---|
401 Unauthorized |
Faltan credenciales de autenticación válidas | API Key incorrecta, Token expirado, formato incorrecto de cabecera de autenticación | No se debe reintentar sin cambios |
403 Forbidden |
El servidor rechaza procesar la solicitud | Permisos insuficientes, restricciones de IP o región, políticas de recursos, bloqueo de WAF | Normalmente no |
429 Too Many Requests |
Las solicitudes superan los límites de velocidad o cuota | Concurrencia demasiado alta, QPS excedido, cuota agotada | Reintentar después de esperar |
Cabe señalar que, aunque el nombre en inglés de 401 es Unauthorized, en el diagnóstico real de problemas es más adecuado entenderlo como “no autenticado”; 403 es el que normalmente se relaciona con la autorización o las políticas de acceso.
¶ I. 401 Unauthorized: primero compruebe las credenciales de autenticación

HTTP 401 Unauthorized indica que la solicitud carece de las credenciales de autenticación válidas requeridas para el recurso de destino. Una respuesta 401 estándar normalmente informa al cliente, mediante la cabecera de respuesta WWW-Authenticate, del esquema de autenticación que el servidor espera utilizar.
¶ Causas comunes
- No se envió la cabecera de solicitud
Authorization - La API Key o el Access Token son incorrectos
- El Token ha expirado o fue revocado
- El esquema de autenticación es incorrecto, por ejemplo, falta
Bearer - Las variables de entorno no se cargaron correctamente
- Se utilizó una clave del entorno equivocado
- La cabecera de autenticación se perdió cuando la solicitud fue reenviada por un proxy o una puerta de enlace
- La diferencia de tiempo entre el cliente y el servidor es demasiado grande, lo que provoca que la firma deje de ser válida
¶ Errores comunes
La interfaz requiere un Bearer Token:
Authorization: Bearer YOUR_ACCESS_TOKEN
Pero el cliente lo envía como:
Authorization: YOUR_ACCESS_TOKEN
O se escribe erróneamente como:
Authentication: Bearer YOUR_ACCESS_TOKEN
Ambas situaciones pueden devolver 401.
¶ Diagnóstico con curl
No mire únicamente el cuerpo de la respuesta al principio. Añada -i para comprobar al mismo tiempo el código de estado y las cabeceras de respuesta:
curl -i "https://api.example.com/v1/profile" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Accept: application/json"
Compruebe especialmente:
- Si realmente se envió
Authorization - Si el esquema de autenticación es correcto
- Si hay espacios o saltos de línea antes o después del Token
- Qué devuelve
WWW-Authenticate - Si hay información de error como
invalid_token,expired_tokenen el cuerpo de la respuesta
Si necesita ver un proceso de solicitud más detallado, puede utilizar:
curl -v "https://api.example.com/v1/profile" \
-H "Authorization: Bearer $API_TOKEN"
Nota: los registros de depuración pueden contener Tokens. No envíe los registros completos directamente a Issues públicos, chats grupales o tickets.
¶ ¿Se debe reintentar un 401?
No reintente repetidamente usando las mismas credenciales inválidas.
Flujo recomendado:
- Compruebe si la solicitud incluye información de autenticación
- Compruebe si el Token ha expirado, fue revocado o se copió incorrectamente
- Si se admite Refresh Token, actualice una vez el token de acceso
- Reintente una vez con el nuevo Token
- Si sigue devolviendo 401, deje de reintentar y registre el error
Si utiliza una API Key fija, debe comprobar el estado de la clave o sustituirla por una clave válida, en lugar de reintentar en bucle.
¶ II. 403 Forbidden: la autenticación puede haberse realizado correctamente, pero la solicitud sigue siendo rechazada

403 Forbidden indica que el servidor ya ha entendido la solicitud, pero rechaza procesarla. Para errores de permisos típicos, incluso volver a autenticarse no resolverá el problema automáticamente; si no se modifica la solicitud o la configuración de permisos, las solicitudes repetidas normalmente seguirán fallando.
¶ Causas comunes
- La cuenta o clave actual carece de los permisos requeridos
- El Scope del Token es insuficiente
- Se accedió a un recurso que no pertenece al proyecto o inquilino actual
- La IP de origen no está en la lista blanca
- La región de origen de la solicitud está restringida
- WAF, firewall o sistema antiabuso bloquea la solicitud
- La cuenta, proyecto o recurso fue deshabilitado
- La interfaz solo está disponible para planes o roles específicos
- La firma es válida, pero el alcance del recurso en la firma no coincide
- En escenarios de navegador, está sujeto a restricciones de políticas de CSRF, Origin o Referer
¶ Diferencia entre 401 y 403
Se puede determinar rápidamente con dos frases:
- 401: el servidor no puede confirmar quién eres
- 403: el servidor conoce o entiende tu identidad y solicitud, pero no te permite hacerlo
Por ejemplo, un miembro normal utiliza un Token válido para llamar a la interfaz de “eliminar organización”:
curl -i -X DELETE \
"https://api.example.com/v1/organizations/org_123" \
-H "Authorization: Bearer $API_TOKEN"
Si el Token es válido, pero la cuenta no es administradora de la organización, el servidor puede devolver:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "insufficient_permissions",
"message": "Administrator role is required."
}
¶ Orden de diagnóstico para 403
¶ 1. Lea el cuerpo de la respuesta
Busque primero el código de error, el rol o permiso faltante, el Scope requerido, el ID del recurso rechazado y las indicaciones sobre IP, región o políticas de seguridad.
¶ 2. Compruebe el Scope del Token
Por ejemplo, leer datos puede requerir solo data:read, pero crear datos puede requerir data:write. Que el Token sea válido no significa que tenga todos los permisos.
¶ 3. Compruebe la pertenencia del recurso
Confirme que el ID de proyecto, ID de organización, ID de inquilino, ID de usuario, región o entorno pertenezcan a la misma cuenta o ámbito de autorización que las credenciales actuales.
¶ 4. Compruebe las políticas de red y seguridad
Si el código funciona correctamente localmente, pero devuelve 403 después del despliegue, se deben revisar especialmente la IP de salida del servidor, la lista blanca de IP, la configuración del proxy, CDN, WAF, la región de origen de la solicitud y los encabezados de solicitud relacionados.
¶ No saque conclusiones basándose solo en el código de estado
Las implementaciones de API en la realidad no necesariamente son completamente consistentes. Algunas plataformas pueden devolver 403 al activar la limitación de tasa, en lugar de 429. Por ejemplo, la API REST de GitHub puede devolver 403 o 429 al exceder el límite de velocidad, e indicar el estado de la limitación mediante encabezados de respuesta como x-ratelimit-remaining, x-ratelimit-reset o retry-after.
Por lo tanto, al encontrar un 403 también se debe verificar en conjunto:
- El código de error de negocio en el cuerpo de la respuesta
Retry-AfterX-RateLimit-RemainingX-RateLimit-Reset- La documentación oficial de la plataforma
¶ ¿Se debe reintentar un 403?
Para los 403 causados por permisos insuficientes, restricciones de IP o políticas de recursos, reintentar sin cambios no tiene sentido.
La forma correcta es modificar los permisos o Token Scope, usar la cuenta o proyecto correctos, ajustar la lista blanca y las políticas de seguridad, corregir el ID del recurso, y confirmar si el servicio o plan admite esta interfaz. Solo cuando la plataforma indique explícitamente que este 403 en realidad representa una limitación temporal de tasa, se debe esperar y reintentar según las reglas de limitación.
¶ III. 429 Too Many Requests: primero reduzca la velocidad, luego reintente

429 Too Many Requests indica que el cliente ha enviado demasiadas solicitudes durante un período de tiempo, es decir, ha activado la limitación de tasa. El servidor puede indicar al cliente mediante Retry-After cuánto tiempo debe esperar antes de reintentar.
¶ Causas comunes
- Demasiadas solicitudes en poco tiempo
- Cantidad demasiado alta de tareas concurrentes
- Varios servicios comparten la misma API Key
- El código de reintento no tiene mecanismo de espera
- Las tareas programadas se ejecutan de forma concentrada al mismo tiempo
- Las solicitudes no tienen caché y obtienen repetidamente los mismos datos
- La cuota de una sola cuenta, IP o proyecto se ha agotado
- Límites de uso o saldo del plan
¶ Primero revise los encabezados de respuesta
curl -i "https://api.example.com/v1/resources" \
-H "Authorization: Bearer $API_TOKEN"
Preste especial atención a:
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1710000000
Los nombres de los encabezados de respuesta pueden variar entre plataformas; se debe tomar como referencia la documentación de la plataforma.
¶ Manejar correctamente Retry-After
Los dos formatos comunes de Retry-After son segundos o fecha HTTP:
Retry-After: 30
Retry-After: Wed, 21 Oct 2026 07:28:00 GMT
Es mejor que el cliente sea compatible con ambos formatos.
¶ ¿Por qué no se puede reintentar inmediatamente?
Si se reintenta inmediatamente después de que una solicitud sea limitada por tasa, la nueva solicitud seguirá siendo limitada; varios clientes también podrían reintentar al mismo tiempo, formando una “estampida”. Un método más seguro es:
- Priorizar el cumplimiento de
Retry-After - Cuando no haya un tiempo de espera explícito, usar retroceso exponencial
- Añadir fluctuación aleatoria al tiempo de espera
- Establecer un número máximo de reintentos
- Devolver un error claro después de alcanzar el límite
¶ Node.js: manejar 429 de forma segura
El siguiente ejemplo utiliza el fetch integrado de Node.js, prioriza el análisis de Retry-After; si el servidor no proporciona este encabezado de respuesta, utiliza retroceso exponencial con fluctuación aleatoria.
const sleep = (ms) =>
new Promise((resolve) => setTimeout(resolve, ms));
function parseRetryAfter(value) {
if (!value) return null;
const seconds = Number(value);
if (Number.isFinite(seconds) && seconds >= 0) {
return seconds * 1000;
}
const timestamp = Date.parse(value);
if (!Number.isNaN(timestamp)) {
return Math.max(0, timestamp - Date.now());
}
return null;
}
async function fetchWithRetry(url, options = {}, config = {}) {
const {
maxRetries = 3,
baseDelayMs = 1000,
maxDelayMs = 30_000,
} = config;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
if (attempt === maxRetries) {
throw new Error(
`请求持续受到限流,已达到最大重试次数:${maxRetries}`
);
}
const retryAfterMs = parseRetryAfter(
response.headers.get("retry-after")
);
const backoffCap = Math.min(
maxDelayMs,
baseDelayMs * 2 ** attempt
);
const jitterMs = Math.floor(Math.random() * backoffCap);
const delayMs = retryAfterMs ?? jitterMs;
console.warn(
`收到 429,第 ${attempt + 1} 次等待 ${delayMs}ms 后重试`
);
await sleep(delayMs);
}
throw new Error("请求失败");
}
Ejemplo de llamada:
const response = await fetchWithRetry(
"https://api.example.com/v1/resources",
{
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
Accept: "application/json",
},
},
{
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 30_000,
}
);
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`API 请求失败:${response.status} ${errorBody}`);
}
const data = await response.json();
console.log(data);
¶ Al reintentar solicitudes POST, también se debe considerar la idempotencia
No todas las solicitudes son adecuadas para reintentos automáticos. Las solicitudes de lectura como GET y HEAD normalmente pueden reintentarse de forma segura con mayor facilidad. Para solicitudes POST como crear pedidos, realizar cargos o enviar mensajes, el cliente puede haber enviado correctamente la solicitud, pero no haber recibido respuesta debido a una interrupción de red. Reintentar directamente en este caso puede causar operaciones duplicadas.
Si la plataforma lo admite, se debe establecer una clave de idempotencia para las operaciones de escritura:
curl -i -X POST "https://api.example.com/v1/orders" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-20260331-0001" \
-d '{
"product_id": "prod_123",
"quantity": 1
}'
El nombre del encabezado y el período de validez de la clave de idempotencia son determinados por cada plataforma específica; se debe consultar la documentación de la API correspondiente.
¶ Lista de verificación para la resolución de problemas en entornos de producción
¶ Al recibir 401
- Si la solicitud incluye un encabezado de autenticación
- Si el esquema de autenticación como
Beareres correcto - Si el Token ha expirado, ha sido revocado o se copió incorrectamente
- Si se está utilizando la clave del entorno correcto
- Si el proxy o la puerta de enlace eliminó el encabezado de autenticación
- Si la hora del cliente es precisa
- Si es posible actualizar un Token de forma segura una vez
¶ Al recibir 403
- Si el token tiene el Scope requerido
- Si la cuenta actual tiene el rol requerido
- Si el recurso pertenece al proyecto o tenant actual
- Si la IP de salida está en la lista blanca
- Si está sujeto a restricciones de región, WAF o políticas de seguridad
- Si el cuerpo de la respuesta indica claramente permisos o limitación de tasa
- Si existen datos de limitación de tasa en los encabezados de respuesta
¶ Al recibir 429
- Si se ha leído
Retry-After - Si se han comprobado los encabezados de respuesta relacionados con la limitación de tasa
- Si se utiliza retroceso exponencial y fluctuación aleatoria
- Si se ha establecido el número máximo de reintentos
- Si se limita la concurrencia
- Si se almacenan en caché los resultados de consultas repetidas
- Si se pueden combinar o enviar solicitudes por lotes
- Si se ha alcanzado la cuota del plan o el límite de uso de la cuenta
¶ ¿Qué información de diagnóstico se recomienda registrar?
Se recomienda registrar en los logs la hora de la solicitud, el nombre de host y la ruta de la API, el método HTTP, el código de estado, el código de error de negocio, request-id o trace-id, Retry-After, la cuota restante de limitación de tasa y la hora de restablecimiento, el número de reintentos y el tiempo de espera real.
Pero no registre la API Key completa, el Access Token completo, el Refresh Token, las contraseñas de los usuarios ni la información personal sensible en el cuerpo de la solicitud.
¶ El último mantra de decisión
401: primero corrige las credenciales, no reintentes con el Token antiguo.
403: primero corrige los permisos o las políticas, no repitas la solicitud tal cual.
429: respeta el tiempo de espera, retrocede, reduce la velocidad y limita la concurrencia.
El código de estado solo es la entrada para la resolución de problemas, no es toda la respuesta. Una forma fiable de manejarlo es combinar el código de estado HTTP, el código de error de negocio en el cuerpo de la respuesta, los encabezados de respuesta relevantes, la documentación de la plataforma, el ID de solicitud y los logs del servidor, para convertir los “errores de interfaz” en un mecanismo de ingeniería observable, recuperable y mantenible.

