HTTP-Statuscodes erklärt: Wann 401 vs 403 vs 422?
Die wichtigsten HTTP-Statuscodes verständlich erklärt – inklusive klarer Faustregeln für 401, 403 und 422.
HTTP-Statuscodes sind die kürzeste Form von API-Dokumentation – wenn man sie richtig nutzt. In der Praxis sieht man trotzdem oft 200 für Fehler, 500 für Validierung und 403für nicht eingeloggte User. Hier kommt die saubere Variante.
2xx – Erfolg
- 200 OK – Standard-Erfolgsantwort, üblicherweise mit Body.
- 201 Created – Eine neue Ressource wurde erzeugt. Der
Location-Header sollte auf sie zeigen. - 204 No Content – Erfolg, aber bewusst kein Body. Ideal für
DELETEoderPUT, wenn der Client den neuen Zustand schon kennt.
3xx – Redirects
Der Unterschied zwischen 301 und 302 ist eine der häufigsten SEO-Stolperfallen.
- 301 Moved Permanently – Permanent. Browser und Suchmaschinen cachen den Redirect aggressiv.
- 302 Found – Temporär. Methode darf laut Spec geändert werden (POST → GET), Browser tun das auch.
- 307 Temporary Redirect – Temporär, aber Methode bleibt erhalten. Sicherer als 302 für POST.
- 308 Permanent Redirect – Wie 301, aber Methode bleibt erhalten. Modernere Wahl.
4xx – Client-Fehler
Hier liegen die meisten Verwechslungen. 400 ist generisch (Request fehlerhaft, z.B. kaputtes JSON), 404heißt "Ressource existiert nicht oder Du darfst sie nicht sehen". Spannender wird es bei 401, 403 und 422:
| Code | Bedeutung | Wann nutzen | Beispiel |
|---|---|---|---|
| 401 | Unauthorized – nicht authentifiziert | Kein Token, abgelaufenes Token, falsche Credentials | API-Aufruf ohne Authorization-Header |
| 403 | Forbidden – authentifiziert, aber keine Berechtigung | User ist eingeloggt, darf aber diese Aktion nicht | Normaler User versucht Admin-Endpoint |
| 422 | Unprocessable Entity – Validierung fehlgeschlagen | Request-Format ok, aber Inhalt logisch falsch | E-Mail ist syntaktisch ok, aber bereits vergeben |
Weitere wichtige 4xx:
- 409 Conflict – Zustandskonflikt, z.B. concurrent edit oder doppelter Username.
- 429 Too Many Requests – Rate Limit erreicht. Sende einen
Retry-After-Header mit.
5xx – Server-Fehler
- 500 Internal Server Error – Der Sammeleimer für unerwartete Server-Fehler. Logge alles, was hier landet.
- 502 Bad Gateway – Reverse Proxy (nginx, Cloudflare) bekam vom Backend kaputte oder gar keine Antwort.
- 503 Service Unavailable – Server ist absichtlich offline (Wartung, Überlast). Mit
Retry-Afterkombinieren. - 504 Gateway Timeout – Backend antwortet zu langsam.
Faustregeln für die Praxis
- Niemals 200 für Fehler – auch nicht mit
{ "error": "..." }im Body. Clients und Monitoring verlassen sich auf den Statuscode. - 401 vs 403:Die Frage ist nicht "darfst Du das?" sondern "wer bist Du?". Kennen wir Dich nicht (oder kein gültiges Token)? → 401. Wissen wir wer Du bist, aber Du darfst nicht? → 403.
- 404 statt 403 für privaten Content – damit verrätst Du nicht mal die Existenz der Ressource. GitHub macht das z.B. für private Repos.
- 422 statt 400, wenn Du semantische Validierungsfehler zurückgibst (Pflichtfeld leer, falsches Format). 400 nimmst Du für strukturell kaputte Requests (kein gültiges JSON).
- 201 mit
Location-Header, wenn Du etwas erstellst. Das ist REST-Standard, hilft Clients und Tooling. - 204 nutzen, wenn der Body leer ist – das ist semantisch klarer als 200 mit leerem Body.
Konsistenz schlägt Perfektion: Wenn Dein Team sich auf eine klare Regel einigt und alle sich daran halten, ist das wertvoller als die theoretisch "perfekte" Wahl in jedem Einzelfall.