Artikel

HTTP-Statuscodes: vollständige Referenz und die häufigsten Verwechslungen

Eine vollständige Referenzliste der HTTP-Statuscodes – plus die wirklich schwierigen Entscheidungen: 301 vs. 308, 401 vs. 403, 422 vs. 400, 502 vs. 503, inklusive der Frage, wie Next.js sie im Hintergrund handhabt.

Furkan Özay27. Juni 2024 · 13 Min. Lesezeit
czCZAY.DEV // EDITORIALDE
MODERN WEB & REACT

#Web Temelleri · 13 MIN LESEZEIT

FURKAN ÖZAYVOL. 2024 // #CC0E

Eine Liste von Statuscodes auswendig zu lernen ist leicht; den richtigen auszuwählen ist der schwierige Teil. Der Unterschied zwischen „diesen Datensatz habe ich nicht gefunden“ und „du darfst diesen Datensatz nicht sehen“ in einer API, ob aus einem POST bei einer Weiterleitung ein GET wird, ob Google eine Adresse wegen einer Fehlerseite aus dem Index nimmt – alles hängt an der Wahl der richtigen dreistelligen Zahl.

Dieser Beitrag hat zwei Teile: zuerst eine vollständige Liste (zum Nachschlagen), dann die Codes, die in der Praxis am häufigsten falsch gewählt werden, und wie sie in Next.js in Erscheinung treten.

Fünf Klassen

KlasseBedeutungKurz gesagt
1xxInformationalAnfrage empfangen, Verarbeitung läuft weiter
2xxSuccessfulAnfrage erfolgreich verarbeitet
3xxRedirectionWeitere Schritte nötig, um abzuschließen
4xxClient ErrorDer Fehler liegt beim Client
5xxServer ErrorDer Fehler liegt beim Server

Die Unterscheidung wirkt einfach, hat aber Grenzfälle: Der Client hat eine gültige Anfrage geschickt, der Server arbeitet korrekt, aber eine Geschäftsregel verbietet es – ist das 4xx oder 5xx? (Antwort: 4xx. Details weiter unten.)

1xx — Informational

CodeNameBedeutung
100ContinueDer Client kann den Request-Body weiter senden
101Switching ProtocolsDer Server wechselt auf das Protokoll aus dem Upgrade-Header (WebSocket-Handshake)
102ProcessingAnfrage empfangen, noch kein Ergebnis (WebDAV)
103Early HintsHinweis zum Vorladen von Ressourcen per Link-Header, bevor die endgültige Antwort fertig ist

In der Praxis ist 103 Early Hints der einzige moderne 1xx-Code, der wirklich nützlich ist: Während der Server die Hauptantwort vorbereitet, kann er dem Browser sagen: „Fang schon mal an, dieses CSS und diese Schrift zu laden.“

2xx — Successful

CodeNameBedeutung
200OKAnfrage erfolgreich; die Bedeutung hängt von der HTTP-Methode ab
201CreatedNeue Ressource erstellt (meist POST/PUT)
202AcceptedEmpfangen, aber noch nicht verarbeitet – für asynchrone Jobs
203Non-Authoritative InformationMetadaten stammen nicht vom Ursprungsserver (selten; besser 200)
204No ContentErfolgreich, kein Body – Header können trotzdem relevant sein
205Reset ContentDer Client soll die Dokumentansicht zurücksetzen
206Partial ContentTeilantwort auf eine Range-Anfrage (Video-Streaming, fortgesetzte Downloads)
207Multi-StatusSeparater Status für mehrere Ressourcen (WebDAV)
208Already ReportedVermeidet erneutes Auflisten von Mitgliedern (WebDAV)
226IM UsedAntwort per Delta-Encoding geliefert

Tipp: Nutze 201 und 204

Die meisten APIs geben für alles 200 zurück. Wenn aber ein Endpoint zum Erstellen 201 Created + einen Location-Header zurückgibt und ein Endpoint zum Löschen 204 No Content, weiß der Client sofort, was passiert ist, ohne einen Body parsen zu müssen.

3xx — Redirection

CodeNameMethode bleibt erhalten?Dauerhaft?
300Multiple Choices——
301Moved PermanentlyNein (Browser machen aus POST ein GET)Dauerhaft
302FoundNein (POST → GET)Temporär
303See OtherNein – wird immer zu GETTemporär
304Not Modified— (Antwort aus dem Cache)—
305Use Proxy⚠️ Veraltet—
306(unused)⚠️ Reserviert—
307Temporary RedirectJaTemporär
308Permanent RedirectJaDauerhaft

Diese ganze Tabelle läuft auf eine einzige Unterscheidung hinaus: Bleibt die HTTP-Methode nach der Weiterleitung erhalten?

  • 301 / 302 sind Legacy-Codes. Browser wandeln dabei POST-Anfragen in GET um – auch wenn die Spezifikation das nicht ausdrücklich vorsah, ist das der De-facto-Standard.
  • 307 / 308 wurden eingeführt, um diese Mehrdeutigkeit zu beseitigen: Die verwendete Methode bleibt unverändert. Wenn du einen POST weiterleitest, geht er als POST weiter.
  • 303 macht genau das Gegenteil mit Absicht: Es erzwingt die Methode GET, egal was hereinkam.

Erklärung: Wofür ist 303 da?

Wenn ein Nutzer ein Formular abschickt, willst du ihn auf eine Ergebnisseite weiterleiten. Mit 307 landet er auch dort mit einer POST-Anfrage; lädt er die Seite neu, fragt der Browser „Möchtest du das Formular erneut senden?“, und du bekommst womöglich doppelte Datensätze. 303 verhindert diese Falle, indem es die Anfrage auf GET zwingt. Dieses Muster heißt POST/Redirect/GET und ist in Abläufen wie Payment-Callbacks entscheidend.

Warnung: Auswirkung auf SEO

Verwende 301/308 für dauerhafte Umzüge; Suchmaschinen nehmen die alte URL aus ihrem Index und übertragen die Link-Power auf die neue. Bei 302/307 bleibt die alte URL im Index. Die falsche Wahl bei Website-Migrationen ist eine der häufigsten Ursachen für Traffic-Verluste.

4xx — Client Error

CodeNameBedeutung
400Bad RequestAnfrage ist fehlerhaft: ungültige Syntax, Body nicht parsbar
401UnauthorizedBedeutet eigentlich „nicht authentifiziert“ – Login erforderlich
402Payment RequiredZahlung erforderlich; keine Standardverwendung
403ForbiddenDer Server weiß, wer du bist, aber du hast keine Berechtigung
404Not FoundRessource fehlt – oder ihre Existenz soll verborgen bleiben
405Method Not AllowedMethode wird erkannt, aber für diese Ressource nicht unterstützt
406Not AcceptableDie Content Negotiation ergab kein akzeptables Format
407Proxy Authentication RequiredWie 401, aber für einen Proxy-Server
408Request TimeoutInaktive Verbindung vom Server geschlossen
409ConflictAnfrage steht im Konflikt mit dem aktuellen Zustand der Ressource
410GoneDauerhaft gelöscht, die Adresse existiert nicht mehr
411Length RequiredContent-Length-Header erforderlich
412Precondition FailedVorbedingung einer bedingten Anfrage nicht erfüllt
413Content Too LargeRequest-Body überschreitet die Server-Limits
414URI Too LongZiel-URL ist zu lang
415Unsupported Media TypeFormat des Request-Payloads wird nicht unterstützt
416Range Not SatisfiableAngeforderter Bereich kann nicht geliefert werden
417Expectation FailedErwartung aus dem Expect-Header konnte nicht erfüllt werden
418I'm a teapotScherz-Code (RFC 2324) – Teekannen können keinen Kaffee kochen
421Misdirected RequestAnfrage an den falschen Server geschickt
422Unprocessable ContentSyntax ist korrekt, aber der semantische Inhalt ist ungültig
423LockedRessource ist gesperrt (WebDAV)
424Failed DependencyVorherige Anfrage ist fehlgeschlagen (WebDAV)
425Too EarlyVerweigert die Verarbeitung einer Anfrage, die wiederholt werden könnte (TLS-1.3-Early-Data)
426Upgrade RequiredDer Client muss das Protokoll wechseln
428Precondition RequiredBedingte Anfrage erforderlich – verhindert das „Lost Update“-Problem
429Too Many RequestsRate Limit überschritten
431Request Header Fields Too LargeHeader sind zu groß
451Unavailable For Legal ReasonsZugriff aus rechtlichen Gründen gesperrt

401 oder 403?

Das am häufigsten verwechselte Paar. Die Namen führen in die Irre, denn 401 bedeutet eigentlich „nicht authentifiziert“:

  • 401 – Ich weiß nicht, wer du bist. Melde dich an. (Keine Session oder ungültiges Token.)
  • 403 – Ich weiß, wer du bist, aber auf diese Ressource darfst du nicht zugreifen. (Ein Nutzer mit der Rolle user, der /admin aufrufen will.)

Tipp: Eine dritte Option: 404

Manchmal verrät schon 403 zu viel. „Diese Ressource existiert, aber du darfst sie nicht sehen“ gibt Informationen preis. Mit 404 die Existenz einer Ressource komplett zu verbergen – wie GitHub es bei privaten Repositories macht – ist ein legitimer Ansatz.

400 oder 422?

  • 400 – Ich konnte die Anfrage nicht parsen. Kaputtes JSON, fehlendes Pflichtfeld, falscher Datentyp.
  • 422 – Ich habe sie geparst und das Format ist gültig, aber die Bedeutung ist ungültig. „Das Enddatum darf nicht vor dem Startdatum liegen“, „diese E-Mail-Adresse ist bereits registriert“.

Anders gesagt: Syntaxfehler sind 400, Verstöße gegen Geschäftsregeln sind 422. In der Praxis geben viele APIs für beides 400 zurück, das ist in Ordnung – aber wenn du sie trennst, können Client-Anwendungen „Formular korrigieren“ und „Anfrageformat korrigieren“ ohne zusätzlichen Code unterscheiden.

409 und 410

  • 409 Conflict – Die Anfrage steht im Konflikt mit dem aktuellen Zustand der Ressource. Versionskonflikt bei gleichzeitiger Bearbeitung oder der Versuch, eine Ressource mit einem bereits vorhandenen Slug anzulegen.
  • 410 Gone – Die Ressource existierte, wurde dauerhaft gelöscht und kommt nicht wieder. Der Unterschied zu 404 ist die Gewissheit: Suchmaschinen entfernen eine 410 deutlich schneller aus dem Index. Wenn du dir nicht sicher bist, bleib bei 404.

429 und Retry-After

Wenn du Rate Limiting implementierst, ist allein 429 zurückzugeben nur die halbe Arbeit. Sende auch einen Retry-After-Header – damit der Client weiß, wie lange er warten muss, statt blind erneut zu versuchen.

Beispiel: Rate Limiting in einem Next.js Route Handler

TypeScript
export async function POST(req: Request) {
	const allowed = await rateLimit(req);
 
	if (!allowed) {
		return new Response(
			JSON.stringify({ error: "Çok fazla istek gönderdiniz." }),
			{
				status: 429,
				headers: {
					"Content-Type": "application/json",
					"Retry-After": "60", // seconds
				},
			}
		);
	}
 
	// ...
}

451

Wird verwendet, wenn Inhalte aus rechtlichen Gründen gesperrt sind. Benannt nach Ray Bradburys Roman Fahrenheit 451 – der Temperatur, bei der Papier brennt.

5xx — Server Error

CodeNameBedeutung
500Internal Server ErrorAllgemeiner Fehler; der Server ist auf einen unerwarteten Zustand gestoßen
501Not ImplementedDer Server unterstützt die Anfragemethode nicht
502Bad GatewayDer Proxy hat vom Upstream-Server eine ungültige Antwort erhalten
503Service UnavailableDer Server kann die Anfrage vorübergehend nicht bearbeiten (Wartung, Überlast)
504Gateway TimeoutDer Upstream-Server hat nicht rechtzeitig geantwortet
505HTTP Version Not SupportedHTTP-Version wird nicht unterstützt
506Variant Also NegotiatesFehler in der Serverkonfiguration (zirkuläre Negotiation)
507Insufficient StorageSpeicherplatz erschöpft (WebDAV)
508Loop DetectedEndlosschleife erkannt (WebDAV)
510Not ExtendedErforderliche HTTP-Erweiterung wird nicht unterstützt
511Network Authentication RequiredDer Client muss sich authentifizieren, um Netzwerkzugang zu erhalten (WLAN-Portal)

502, 503, 504 – welcher Fehler ist welcher?

Diese drei sind der schnellste Weg, Probleme bei Server-Deployments zu diagnostizieren:

  • 502 Bad Gateway – Nginx läuft, aber die App dahinter ist abgestürzt oder antwortet auf diesem Port nicht. Schau in die Logs deiner App.
  • 503 Service Unavailable – Der Server läuft, verweigert aber gerade den Traffic: Wartungsmodus, Systemüberlastung, keine Instanz im Pool verfügbar. Sollte mit Retry-After gesendet und darf nicht gecacht werden.
  • 504 Gateway Timeout – Die Upstream-App existiert, ist aber zu langsam; der Proxy hat das Warten aufgegeben. Such nach langsamen Queries oder langsamen Aufrufen externer APIs.

Achtung: Gib im Wartungsmodus nicht 200 zurück

Wenn du eine „Wir führen gerade Wartungsarbeiten durch“-Seite mit Status 200 auslieferst, glauben Suchmaschinen, das sei dein eigentlicher Inhalt. Wartungsseiten sollten 503 zurückgeben – Suchmaschinen strafen dein Ranking bei kurzen Ausfällen nicht ab.

Statuscodes in Next.js

Das Framework wählt einige Statuscodes für dich aus, und es hilft zu wissen, was es im Hintergrund nimmt.

Wichtig: Redirect-Funktionen

  • redirect() → 307 (temporär, Methode bleibt erhalten)
  • permanentRedirect() → 308 (dauerhaft, Methode bleibt erhalten)
  • redirect() innerhalb eines Server-Action-Formular-Submits → 303 (damit der Browser mit GET nachfragt; ist JS aktiv, übernimmt ohnehin die clientseitige Navigation)
  • NextResponse.redirect() → standardmäßig 307

Next.js nimmt 307/308 statt 302/301 wegen des oben erwähnten Problems mit der Methode: Ein Browser, der 302 erhält, wandelt POST in GET um, und aus einem POST an /users wird ein GET an /people.

Wenn du eine Adresse dauerhaft änderst, nimm permanentRedirect() statt redirect() – oder setze permanent: true in der redirects()-Konfiguration deiner next.config.ts. Sonst nehmen Suchmaschinen die alte Adresse nicht aus dem Index.

notFound() gibt 404 zurück und rendert deine Datei not-found.tsx.

Beispiel: Korrekte Statuscodes in einem Route Handler

TypeScript
import { NextResponse } from "next/server";
 
export async function POST(req: Request) {
	const body = await req.json().catch(() => null);
 
	if (!body) {
		return NextResponse.json({ error: "Geçersiz JSON" }, { status: 400 });
	}
 
	const parsed = schema.safeParse(body);
	if (!parsed.success) {
		// Valid format, invalid meaning
		return NextResponse.json(
			{ error: "Doğrulama hatası", issues: parsed.error.issues },
			{ status: 422 }
		);
	}
 
	const session = await auth();
	if (!session) {
		return NextResponse.json({ error: "Giriş gerekli" }, { status: 401 });
	}
	if (session.user.role !== "admin") {
		return NextResponse.json({ error: "Yetkiniz yok" }, { status: 403 });
	}
 
	const created = await db.post.create({ data: parsed.data });
 
	return NextResponse.json(created, {
		status: 201,
		headers: { Location: `/api/posts/${created.id}` },
	});
}

Schnelle Entscheidungshilfe

Zusammenfassung: Welchen Code soll ich zurückgeben?

  • Datensatz erstellt → 201 + Location
  • Gelöscht, nichts zurückzugeben → 204
  • URL dauerhaft geändert → 308 (301 ist für SEO ebenfalls in Ordnung)
  • Weiterleitung auf die Ergebnisseite nach Formular-Submit → 303
  • Nicht authentifiziert → 401
  • Authentifiziert, aber nicht berechtigt → 403
  • Existenz des Datensatzes verbergen → 404
  • Kaputtes JSON → 400
  • Gültiges JSON, Verstoß gegen Geschäftsregel → 422
  • Konflikt bei gleichzeitiger Bearbeitung → 409
  • Rate Limit erreicht → 429 + Retry-After
  • Wartungsarbeiten → 503 + Retry-After
  • Unerwarteter Fehler → 500 (den tatsächlichen Grund ins Log schreiben, nicht an den Nutzer)

Eine letzte Anmerkung: Gib in Fehlerantworten niemals Stacktraces an Nutzer heraus. Statuscodes sagen dem Client, was er tun soll; detaillierte Informationen gehören in die Server-Logs.

Hinweis: Quellen

Die Liste der Statuscodes basiert auf der Referenz MDN HTTP response status codes, das Verhalten von Next.js folgt der redirect-Dokumentation.

Interaktive Roadmap & Tool

Als Nächstes lesen