HTTP durum kodları: tam referans ve pratikte en çok karıştırılanlar

HTTP durum kodları: tam referans ve pratikte en çok karıştırılanlar

Bütün HTTP durum kodlarının Türkçe açıklamalı listesi — ve asıl mesele: 301 mi 308 mi, 401 mi 403 mü, 422 mi 400 mü, 502 mi 503 mü? Next.js'te hangi kodun ne zaman döndüğü de dahil.

Furkan Özay·27 Haziran 2024·11 dk okuma·2 Eyl 2026'de güncellendi

Durum kodlarının listesini ezberlemek kolay; doğru olanı seçmek zor. Bir API'de "kaydı bulamadım" ile "bu kaydı görmeye yetkin yok" arasındaki fark, bir yönlendirmede POST'un GET'e dönüp dönmemesi, bir hata sayfasında Google'ın adresi indeksten silip silmemesi — hepsi bu üç haneli sayının seçimine bağlı.

Bu yazı iki bölüm: önce tam liste (referans olarak kullan), sonra pratikte en çok yanlış seçilen kodlar ve Next.js'te bunların nasıl karşımıza çıktığı.

Beş sınıf

SınıfAnlamıKısaca
1xxBilgiİstek alındı, işlem sürüyor
2xxBaşarıİstek başarıyla işlendi
3xxYönlendirmeTamamlamak için ek adım gerekiyor
4xxİstemci hatasıHata isteği gönderende
5xxSunucu hatasıHata sunucuda

Ayrım basit görünüyor ama sınırda kalan durumlar var: istemci geçerli bir istek gönderdi, sunucu da doğru çalışıyor, ama iş kuralı izin vermiyor — bu 4xx mi 5xx mi? (Cevap: 4xx. Aşağıda.)

1xx — Bilgi

KodAdAnlamı
100Continueİstemci gövdeyi göndermeye devam edebilir
101Switching ProtocolsSunucu Upgrade başlığındaki protokole geçiyor (WebSocket el sıkışması)
102Processingİstek alındı, henüz sonuç yok (WebDAV)
103Early HintsYanıt hazır olmadan Link başlığıyla kaynak ön yükleme ipucu

103 Early Hints pratikte işe yarayan tek modern 1xx: sunucu asıl yanıtı hazırlarken tarayıcıya "şu CSS ve fontu şimdiden çekmeye başla" diyebiliyor.

2xx — Başarı

KodAdAnlamı
200OKİstek başarılı; anlamı HTTP metoduna göre değişir
201CreatedYeni kaynak oluşturuldu (genelde POST/PUT)
202AcceptedAlındı ama henüz işlenmedi — asenkron işler için
203Non-Authoritative InformationÜstveri kaynak sunucudan gelmiyor (nadiren; 200 tercih edilir)
204No ContentBaşarılı, gövde yok — başlıklar anlamlı olabilir
205Reset Contentİstemci belgeyi sıfırlasın
206Partial ContentRange isteğine kısmi yanıt (video akışı, indirme devam ettirme)
207Multi-StatusBirden çok kaynak için ayrı ayrı durum (WebDAV)
208Already ReportedAynı üyeleri tekrar saymamak için (WebDAV)
226IM UsedDelta kodlamayla dönen yanıt
💡201 ve 204'ü kullan

Çoğu API her şeye 200 döndürüyor. Oysa kayıt oluşturan bir uç nokta 201 Created + Location başlığı, silen bir uç nokta 204 No Content döndürdüğünde istemci hiçbir gövdeyi ayrıştırmadan ne olduğunu anlıyor.

3xx — Yönlendirme

KodAdMetot korunur mu?Kalıcı mı?
300Multiple Choices
301Moved PermanentlyHayır (tarayıcılar POST'u GET'e çevirir)Kalıcı
302FoundHayır (POST → GET)Geçici
303See OtherHayır — her zaman GET'e çevirirGeçici
304Not Modified— (önbellek yanıtı)
305Use Proxy⚠️ Kullanımdan kaldırıldı
306(kullanılmıyor)⚠️ Ayrılmış
307Temporary RedirectEvetGeçici
308Permanent RedirectEvetKalıcı

Bu tablonun tamamı tek bir ayrımdan ibaret: yönlendirme sonrası metot korunuyor mu?

  • 301 / 302 eski kodlar. Tarayıcılar bunlarda POST'u GET'e çeviriyor — standart öyle demese de fiilî durum bu.
  • 307 / 308 bu belirsizliği ortadan kaldırmak için geldi: metot ne ise o kalıyor. POST'a yönlendiriyorsan POST olarak gidiyor.
  • 303 ise tam tersini kasten yapıyor: neyle geldiğine bakmadan GET'e çeviriyor.
💬303 ne işe yarar?

Form gönderiminden sonra kullanıcıyı bir sonuç sayfasına göndermek istiyorsun. 307 kullanırsan sonuç sayfasına da POST ile gider; kullanıcı sayfayı yenilediğinde tarayıcı "formu yeniden göndermek istiyor musun?" diye sorar ve kayıt iki kez oluşabilir. 303, isteği GET'e çevirerek bu tuzağı kapatır. Buna POST/Redirect/GET deniyor ve ödeme dönüşü gibi akışlarda kritik.

⚠️SEO tarafı

Kalıcı taşımada 301/308 kullan; arama motorları eski adresi indeksten düşürüp sinyalleri yenisine taşır. 302/307 kullanırsan eski adres indekste kalmaya devam eder. Yanlış seçim, site göçlerinde trafik kaybının en yaygın sebeplerinden biri.

4xx — İstemci hatası

KodAdAnlamı
400Bad Requestİstek bozuk: sözdizimi geçersiz, gövde ayrıştırılamıyor
401UnauthorizedAslında "kimliği doğrulanmamış" — giriş gerekiyor
402Payment RequiredÖdeme gerekli; standart bir kullanımı yok
403ForbiddenKim olduğun biliniyor ama yetkin yok
404Not FoundKaynak yok — ya da varlığını gizlemek istiyorsun
405Method Not AllowedMetot tanınıyor ama bu kaynakta desteklenmiyor
406Not Acceptableİçerik pazarlığı sonucu uygun bir biçim bulunamadı
407Proxy Authentication Required401'in vekil sunucu hâli
408Request TimeoutBoşta bekleyen bağlantı kapatılıyor
409Conflictİstek, kaynağın mevcut durumuyla çelişiyor
410GoneKalıcı olarak silindi, adresi de yok
411Length RequiredContent-Length başlığı zorunlu
412Precondition FailedKoşullu isteğin ön koşulu sağlanmadı
413Content Too LargeGövde sunucu sınırından büyük
414URI Too LongAdres çok uzun
415Unsupported Media TypeGönderilen biçim desteklenmiyor
416Range Not Satisfiableİstenen aralık kaynağın dışında
417Expectation FailedExpect başlığındaki beklenti karşılanamıyor
418I'm a teapotŞaka kodu (RFC 2324) — demlikten kahve çıkmaz
421Misdirected Requestİstek yanlış sunucuya düştü
422Unprocessable ContentBiçimi doğru ama anlamı geçersiz
423LockedKaynak kilitli (WebDAV)
424Failed DependencyÖnceki istek başarısız olduğu için (WebDAV)
425Too EarlyTekrar oynatılabilecek isteği işlemeyi reddediyor (TLS 1.3 early data)
426Upgrade RequiredProtokolü yükseltmen gerekiyor
428Precondition RequiredKoşullu istek zorunlu — "kayıp güncelleme" sorununu önler
429Too Many RequestsHız sınırı aşıldı
431Request Header Fields Too LargeBaşlıklar çok büyük
451Unavailable For Legal ReasonsHukuki sebeple erişime kapalı

401 mi 403 mü?

En çok karıştırılan çift. Adları yanıltıcı, çünkü 401 aslında "kimliği doğrulanmamış" demek:

  • 401 — Sen kimsin bilmiyorum. Giriş yap. (Oturum yok ya da token geçersiz.)
  • 403 — Kim olduğunu biliyorum, ama bu kaynağa erişemezsin. (user rolündeki biri /admin'e girmeye çalışıyor.)
💡Üçüncü bir seçenek: 404

Bazen 403 bile fazla bilgi verir. "Bu kaynak var ama sen göremezsin" demek, kaynağın varlığını sızdırır. Özel depoları listelerken GitHub'ın yaptığı gibi 404 döndürmek, varlığı tamamen gizlemenin meşru yolu.

400 mü 422 mi?

  • 400 — İsteği ayrıştıramadım. Bozuk JSON, eksik zorunlu alan, yanlış tip.
  • 422 — Ayrıştırdım, biçim doğru; ama anlamı geçersiz. "Bitiş tarihi başlangıçtan önce olamaz", "bu e-posta zaten kayıtlı".

Yani sözdizimi hatası 400, iş kuralı ihlali 422. Pratikte pek çok API ikisine de 400 döndürüyor ve bu da kabul edilebilir — ama ayırırsan istemci tarafında "formu düzelt" ile "isteği düzelt" ayrımını kod yazmadan yapabiliyorsun.

409 ve 410

  • 409 Conflict — İstek kaynağın şu anki durumuyla çelişiyor. Eşzamanlı düzenlemede sürüm çakışması, aynı slug'ın ikinci kez oluşturulmaya çalışılması.
  • 410 Gone — Kaynak vardı, kalıcı olarak silindi ve geri gelmeyecek. 404'ten farkı kesinlik: arama motorları 410 gördüğünde adresi daha hızlı düşürüyor. Emin değilsen 404 kullan.

429 ve Retry-After

Hız sınırlaması uyguluyorsan yalnız 429 döndürmek yarım iş. Retry-After başlığını da gönder — istemci ne kadar bekleyeceğini bilsin, körlemesine tekrar denemesin.

🧪Next.js Route Handler'da hız sınırı
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", // saniye
				},
			}
		);
	}
 
	// ...
}

451

İçerik hukuki bir sebeple engellendiğinde. Ray Bradbury'nin Fahrenheit 451 romanına gönderme — kitapların yakıldığı sıcaklık. Türkiye'de erişim engelleri için de doğru koddur, ama uygulamada çoğu yerde kullanılmıyor.

5xx — Sunucu hatası

KodAdAnlamı
500Internal Server ErrorGenel hata; başka bir şey söylenemiyor
501Not ImplementedSunucu bu metodu desteklemiyor
502Bad GatewayAra sunucu, arkadaki sunucudan geçersiz yanıt aldı
503Service UnavailableSunucu geçici olarak hizmet veremiyor (bakım, aşırı yük)
504Gateway TimeoutArkadaki sunucu zamanında cevap vermedi
505HTTP Version Not SupportedHTTP sürümü desteklenmiyor
506Variant Also NegotiatesSunucu yapılandırma hatası (döngüsel pazarlık)
507Insufficient StorageDepolama yetersiz (WebDAV)
508Loop DetectedSonsuz döngü algılandı (WebDAV)
510Not Extendedİstenen HTTP uzantısı desteklenmiyor
511Network Authentication RequiredAğa erişim için kimlik doğrulama (otel/kafe wifi portalı)

502, 503, 504 — hangisi hangi arıza?

Bu üçü sunucu kurulumunda teşhis koymanın en hızlı yolu:

  • 502 Bad Gateway — Nginx ayakta, ama arkadaki uygulama çökmüş ya da o porta cevap vermiyor. Uygulama loglarına bak.
  • 503 Service Unavailable — Sunucu ayakta ama şu an hizmet vermek istemiyor: bakım modu, aşırı yük, havuzda örnek yok. Retry-After ile birlikte gönderilmeli ve önbelleğe alınmamalı.
  • 504 Gateway Timeout — Arkadaki uygulama var ama çok yavaş; ara sunucu beklemekten vazgeçti. Yavaş sorgu ya da dış API çağrısı ara.
🚨Bakım moduna 200 dönme

"Bakımdayız" sayfasını 200 ile sunmak, arama motorlarının o sayfayı sitenin gerçek içeriği sanmasına yol açar. Bakım sayfası 503 döndürmeli — kısa süreli bir kesintiden sonra sıralamana bir şey olmaz.

Next.js'te durum kodları

Framework bazı kodları senin yerine seçiyor ve hangisini seçtiğini bilmek işe yarıyor.

Yönlendirme fonksiyonları
  • redirect()307 (geçici, metot korunur)
  • permanentRedirect()308 (kalıcı, metot korunur)
  • Server Action form gönderiminde redirect()303 (tarayıcı GET ile takip etsin diye; JavaScript varsa zaten istemci tarafı gezinme yapılıyor)
  • NextResponse.redirect() → varsayılan 307

Next.js'in 302/301 yerine 307/308 seçmesinin sebebi yukarıdaki metot sorunu: 302 alan tarayıcı POST'u GET'e çeviriyor ve /users'a yaptığın POST, /people'a GET olarak varıyor.

Kalıcı bir adres değişikliği yapıyorsan redirect() değil permanentRedirect() kullan — ya da next.config.ts içindeki redirects() tanımında permanent: true ver. Aksi hâlde arama motoru eski adresi düşürmez.

notFound() çağrısı 404 döndürür ve not-found.tsx dosyanı gösterir.

🧪Route Handler'da doğru kod
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) {
		// Biçim doğru, anlam geçersiz
		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}` },
	});
}

Hızlı karar rehberi

📋Ne döndüreyim?
  • Kayıt oluşturdum → 201 + Location
  • Sildim, dönecek bir şey yok → 204
  • Adres kalıcı değişti → 308 (SEO için 301 de kabul)
  • Form sonrası sonuç sayfasına gönderiyorum → 303
  • Giriş yapılmamış → 401
  • Giriş yapılmış ama yetkisiz → 403
  • Kaydın varlığını gizlemem gerekiyor → 404
  • JSON bozuk → 400
  • JSON doğru, iş kuralı ihlal → 422
  • Eşzamanlı düzenleme çakışması → 409
  • Hız sınırı → 429 + Retry-After
  • Bakımdayım → 503 + Retry-After
  • Beklenmedik hata → 500 (ve loglara gerçek sebebi yaz, kullanıcıya değil)

Son bir not: hata gövdesinde kullanıcıya yığın izi (stack trace) gösterme. Durum kodu istemciye ne yapacağını söylemek için; ayrıntı loglara ait.

📝Kaynak

Kod listesi MDN HTTP response status codes referansına, Next.js davranışları redirect dokümantasyonuna dayanıyor.

Bu yazıyı faydalı bulduysan paylaşabilirsin.

Furkan Özay

Yazılım geliştirici ve eğitmen; Next.js, React ve altyapı üzerine yazıyor.

czay.dev

Bunu da oku

Yorumlar