Códigos de estado HTTP When to Return 404 vs 410 vs 301 (and Stop Guessing)
Backend developers get HTTP status codes wrong all the time. Here’s a practical guide to the codes that actually matter in REST APIs — 404 vs 410, 301 vs 302, 429 rate limiting, and the 200-with-an-error-body anti-pattern.
You returned 200 with {"error": "user not found"} in the body. Your 301s are actually 302s. Your deleted resources keep returning 404 forever. Let’s go through the status codes developers get wrong most often, and what to return instead.
4xx vs 5xx: Not the Same Bucket
The most fundamental split in HTTP status codes: 4xx is the client’s fault, 5xx is yours. Simple in theory, violated constantly in practice.
The most common offender: returning 500 for a validation error. A user sent malformed JSON to your API. That’s a 400 Bad Request — their payload was wrong. A 500 tells the client “we crashed,” which triggers alerts, gets logged as a server error, and causes automated systems to retry (making your bad day worse). If the client sent garbage, say so with a 4xx.
404 vs 410: The Deleted Resource Problem
404 Not Found means: “I don’t have that right now, but maybe try again later.” Crawlers — Googlebot included — treat 404 as temporary. They’ll keep rechecking indefinitely.
410 Gone means: “That resource is permanently deleted. Stop asking.” Googlebot removes 410 URLs from the index faster than 404s, and it stops crawling them sooner. This matters for SEO and for crawl budget on large sites.
The practical rule: if your API hard-deletes a record and it’s never coming back, return 410 on subsequent requests. The only reason to prefer 404 for a deleted resource is if it might be restored — soft-delete with a recovery window, a published post that could be republished, that kind of thing. Otherwise, 410 is more honest and search engines will thank you for it.
301 vs 302 (and Why 307/308 Exist)
301 Moved Permanently: This URL is gone forever, use the new one. Browsers cache 301s aggressively. Search engines transfer link equity to the destination. If you’re consolidating domains or permanently moving a site, 301 is what you want.
302 Found: Go to this other URL for now, but come back to the original later. No caching. No link equity transfer. Use it for login redirects, temporary maintenance pages, or A/B tests.
The failure mode: using 302 for permanent moves. You think “same thing, just different,” but search engines don’t pass link equity through 302s. Years of SEO work stays attached to the old URL while the new one ranks for nothing. If you moved something permanently, use 301.
Then there’s 307 Temporary Redirect y 308 Permanent Redirect. These are method-safe variants: where a browser might downgrade a POST to a GET when following a 301/302, 307/308 preserve the original HTTP method. If you’re redirecting API endpoints that accept POST bodies, 307 (temporary) or 308 (permanent) keeps the method intact.
| Código | Tipo | Caches? | Preserves method? | Use for |
|---|---|---|---|---|
| 301 | Permanent | Sí | No (may downgrade to GET) | Permanent site moves, URL consolidation |
| 302 | Temporary | No | No (may downgrade to GET) | Login redirects, temporary unavailability |
| 307 | Temporary | No | Sí | Temporary redirect for API POST endpoints |
| 308 | Permanent | Sí | Sí | Permanent redirect for API POST endpoints |
401 vs 403: Authentication vs Authorization
The naming is confusing. 401 Unauthorized actually means unauthenticated — you’re not logged in, or your credentials are missing or invalid. 403 Forbidden means you’re authenticated, but you don’t have permission to access this resource.
The practical difference: a 401 should prompt a login screen or a token refresh. A 403 should show an access-denied message. Return the wrong one and your client doesn’t know whether to ask for credentials or give up.
There’s a security dimension too. Some APIs return 404 instead of 403 for resources the caller can’t access, to avoid leaking that the resource exists. If you return 403 on a resource from another tenant, you’ve confirmed it exists. Returning 404 is more information-secure, though it makes debugging harder for legitimate users. Pick whichever tradeoff fits your threat model and apply it consistently.
429: Rate Limiting, With the Header That Actually Helps
A bare 429 Too Many Requests is annoying. A 429 with a Retry-After header is actually useful.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1746374400
Retry-After can be a number of seconds or an HTTP date. Well-behaved clients will back off automatically. Without it, you’re returning an error code and hoping the client figures out when to retry — most will just hammer your endpoint again immediately, which defeats the purpose of rate limiting.
Don’t return 503 for rate limiting. 503 is “service unavailable” — infrastructure down, deployment in progress, circuit breaker open. Rate limiting is a policy decision, not a service failure. 429 exists exactly for this.
The “200 With an Error Body” Anti-Pattern
This one keeps appearing in production APIs and it needs to stop:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "error", "message": "user not found"}
This breaks everything that depends on HTTP semantics. Monitoring tools report the request as successful. Load balancers pass it through. Client libraries don’t throw. Logs look clean while users see errors. The fix is a one-liner: return the right status code. 200 means it worked. If it didn’t work, don’t return 200.
The same logic applies to 201 vs 200 for resource creation. If a POST to /users creates a new user, return 201 Created con un Location header pointing to the new resource. Return 200 and you’ve thrown away information your clients could use to avoid an extra round-trip.
API Scenario → Correct Status Code
Here’s a reference table for the scenarios that come up most in REST API development:
| Guión | Status code | Notas |
|---|---|---|
| Request body is malformed JSON | 400 Bad Request | Include a message pointing to the parse error |
| Missing or invalid field in request | 422 Unprocessable Entity | 422 is more precise than 400 for semantic validation failures |
| Auth token missing or expired | 401 Unauthorized | Include WWW-Authenticate header |
| Authenticated but no permission | 403 Forbidden | Or 404 if hiding resource existence is a requirement |
| Resource not found, might return | 404 Not Found | For temporary absence or unknown resources |
| Resource permanently deleted | 410 Gone | Crawlers will stop rechecking sooner |
| Created a new resource | 201 Created | Añadir Location: /resources/new-id header |
| DELETE succeeded, no body | 204 No Content | Don’t return an empty JSON object with 200 |
| Permanent URL change | 301 Moved Permanently | Search engines transfer link equity |
| Temporary redirect | 302 Found | No caching, no equity transfer |
| Rate limit exceeded | 429 Too Many Requests | Always include Retry-After |
| Unexpected server exception | 500 Internal Server Error | Don’t leak stack traces in the body |
| Upstream dependency is down | 503 Service Unavailable | Añadir Retry-After if downtime is bounded |
| POST redirect, preserve method | 307 or 308 | 307 temporary, 308 permanent |
When you’re mid-PR and need to verify what a status code actually means, the HTTP Status Codes Lookup tool gives you the spec definition, typical use cases, and which RFC defines it.
Checking Your Redirect Chains
After a site migration or URL restructure, it’s worth verifying the full redirect chain — especially if you’ve got 301s that were later updated to point somewhere else, creating multi-hop chains that bleed link equity. The Verificador de redirecciones traces the chain and shows each status code in sequence, so you can confirm everything resolves in one hop.
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta was added on May 15, 2026
