Scraping'de HTTP Hata Kodları: 403, 407, 429 ve 503

Yayın tarihi:

13 dk okuma

Acar Diveroli
Yazar: Acar Diveroli
Bir istek zarfından kilit, anahtar ve saat simgeli üç hata kodu sütununa uzanan çizim

Bir scraper'ın günlüğünde en sık görülen satırlar başarılı 200 yanıtları değil, arada bir beliren 403, 429 ve 503 kodlarıdır. Bu kodların her biri farklı bir sorunu anlatır ve her biri farklı bir tepki gerektirir. Hepsine aynı şekilde "üç kez yeniden dene" diye yaklaşan bir betik, kalıcı bir engeli zorlayıp durumu kötüleştirir ya da birkaç saniye bekleyince düzelecek geçici bir sorunda veriyi boşuna kaybeder.

Bu yazıda HTTP durum kodlarının nasıl okunacağını, scraping'de en çok karşılaşılan 403, 407, 429 ve 503 kodlarının ne anlama geldiğini ve arkalarındaki olası nedenleri anlatıyoruz. Ardından 502, 504 ve bağlantı hatalarını, Retry-After başlığının kullanımını ve hangi kodda yeniden denenip hangisinde durulması gerektiğini tek bir tabloda topluyoruz. Sonunda bu kararları uygulayan, denenmiş bir Python örneği var.

HTTP durum kodları nasıl okunur?

Her HTTP yanıtı üç haneli bir durum koduyla başlar. İlk hane, yanıtın sınıfını belirler. Kodların tanımları RFC 9110'un 15. bölümünde yer alır; MDN'deki durum kodları listesi de her kod için kısa açıklamalar ve örnekler verir.

SınıfAnlamıScraping'deki karşılığı
1xxBilgi, istek sürüyorPratikte görmezsiniz
2xxBaşarılıSayfa geldi, ama içeriğini yine de kontrol edin
3xxYönlendirmeAdres değişti veya giriş sayfasına yönlendirildiniz
4xxİstemci tarafı sorunİsteğinizde, kimliğinizde veya hızınızda bir sorun var
5xxSunucu tarafı sorunSunucu, ağ geçidi veya proxy isteği tamamlayamadı

Scraping açısından en önemli ayrım şudur: 4xx kodlarının çoğu, aynı isteği aynen tekrar gönderdiğinizde yine aynı sonucu verir. İsteğinizde bir şeyi değiştirmeniz gerekir. 5xx kodlarının çoğu ise geçicidir ve bir süre bekledikten sonra aynı istek başarılı olabilir. 429 bu kuralın istisnasıdır: bir 4xx kodudur ama beklemeyle düzelir.

Bir de koddan bağımsız bir uyarı: 200 görmek, istediğiniz veriyi aldığınız anlamına gelmez. Bot koruma sistemleri doğrulama sayfasını çoğu zaman 200 koduyla döndürür. Yanıtı başarılı saymadan önce sayfada beklediğiniz bir öğenin (ürün başlığı, fiyat alanı) bulunduğunu kontrol edin.

403 Forbidden ne anlama gelir?

403, sunucunun isteğinizi anladığını ama yerine getirmeyi reddettiğini söyler. RFC 9110'a göre sunucu, bu kararın nedenini açıklamak zorunda değildir. Kimlik doğrulaması eksik olduğunda kullanılan 401 Unauthorized'dan farkı, 403'te kimlik bilgisi eklemenin genellikle sonucu değiştirmemesidir.

Scraping'de 403 almanın olası nedenleri:

  • IP itibarı veya IP türü. Veri merkezi adreslerinden gelen trafiği kısıtlayan siteler, bu adreslere doğrudan 403 döner.
  • Coğrafi kısıtlama. Site yalnızca belirli ülkelerden erişime izin veriyordur.
  • Eksik veya tutarsız header. Kütüphanenin varsayılan User-Agent değeri veya bir tarayıcıda hiç görülmeyen header kombinasyonu.
  • Web uygulama güvenlik duvarı (WAF) kuralı. İstek, bir güvenlik kuralına takılmıştır.
  • Önceki trafiğiniz nedeniyle engelleme. Hız sınırını uzun süre aşan bir IP adresi, bir süre sonra 429 yerine 403 almaya başlayabilir.
  • Gerçekten yetki gerektiren sayfa. Giriş yapılmadan erişilemeyen bir yol.

Yapılacak: Aynı isteği hemen tekrar göndermeyin. Adresi aynı IP ile gerçek bir tarayıcıda açmayı deneyin. Tarayıcıda açılıyorsa sorun isteğinizin kendisindedir (header, hız); açılmıyorsa IP veya konumdadır. Engellenmenin nedenlerini ve meşru çözümlerini Web Scraping'de Engellenmeden Veri Toplama Yöntemleri yazımızda ayrıntılı anlattık.

407 Proxy Authentication Required ne anlama gelir?

407, hedef siteden değil proxy sunucusundan gelir. Proxy, isteği hedefe iletmeden önce kimliğinizi kanıtlamanızı istiyor demektir. Bu yüzden 407 gördüğünüzde hedef sitenin kurallarıyla değil, proxy bağlantınızla ilgilenmeniz gerekir.

Olası nedenler:

  • Kullanıcı adı veya şifre yanlış.
  • Şifrede @, : veya / gibi özel karakterler var ve proxy adresinin içinde kodlanmamış (@%40).
  • IP whitelist yöntemi kullanılıyor ama bağlantının çıktığı IP adresi listede değil.
  • Kütüphane, adresteki kimlik bilgisini proxy'ye göndermiyor.
  • Hesaptaki bakiye veya trafik hakkı bitmiş.

Kütüphaneler 407'yi farklı biçimlerde gösterir. HTTPS isteklerinde proxy tüneli kurulamadığı için çoğu zaman bir yanıt nesnesi değil, bir istisna alırsınız: Python Requests ProxyError, HTTPX ProxyError fırlatır; Node.js'te Axios ise 407 durum kodlu bir hata döndürür. Kütüphane farklarını Node.js'te Proxy Kullanımı yazımızda denenmiş örneklerle gösterdik.

Yapılacak: Yeniden denemeyin, yapılandırmayı düzeltin. curl -v çıktısında Proxy-Authorization başlığının gönderilip gönderilmediğine bakın; komutun kendisi cURL ile Proxy Nasıl Kullanılır? yazımızda. İki kimlik doğrulama yöntemini ve 407'nin teşhisini Proxy Kimlik Doğrulama: User:Pass ve IP Whitelist yazımızda adım adım anlattık.

429 Too Many Requests ne anlama gelir?

429, belirli bir süre içinde çok fazla istek gönderdiğinizi söyler. Kod RFC 6585'in 4. bölümünde tanımlanır ve sunucunun yanıtla birlikte bir Retry-After başlığı göndererek ne kadar beklemeniz gerektiğini bildirebileceğini belirtir.

Hız sınırının neye göre sayıldığı siteden siteye değişir:

  • IP adresine göre: Aynı adresten gelen istekler toplanır.
  • Oturuma veya çereze göre: Aynı oturumdaki istekler toplanır; IP değiştirmek sayacı sıfırlamaz.
  • API anahtarına göre: Resmi API'lerde sınır genellikle anahtara bağlıdır.
  • Uç noktaya göre: Arama sayfası gibi ağır uç noktalarda sınır, ürün sayfalarından daha düşüktür.

Bazı API'ler kalan hakkınızı X-RateLimit-Remaining ve X-RateLimit-Reset gibi başlıklarla bildirir. Bu başlıkların adları standart değildir ve servisten servise değişir; kullandığınız API'nin belgesine bakın.

Yapılacak: Retry-After varsa o süre kadar bekleyin. Yoksa üstel geri çekilme uygulayın: ilk denemede 1 saniye, sonra 2, 4, 8 saniye, her birine rastgele bir bileşen ekleyerek. Aynı zamanda eşzamanlılığı düşürün; bekleyip aynı hızla devam ederseniz kısa süre sonra yine 429 alırsınız.

503 Service Unavailable ne anlama gelir?

503, sunucunun şu an isteği karşılayamadığını, ancak durumun geçici olduğunu söyler. Bakım çalışması, aşırı yük veya arkadaki uygulama sunucusunun çökmesi tipik nedenlerdir. RFC 9110'a göre sunucu, ne zaman tekrar deneneceğini Retry-After ile bildirebilir.

Scraping'de 503'ün iki farklı yüzü vardır:

  • Gerçek bir yoğunluk veya bakım. Site herkese 503 dönüyordur. Beklemek dışında yapılacak bir şey yoktur.
  • Bot korumasının geçici engeli. Bazı koruma sistemleri, şüpheli buldukları trafiğe bir doğrulama sayfasıyla birlikte 503 döner. Sayfa gövdesinde bir doğrulama ekranı varsa sorun sunucu yükü değil, trafiğinizin kendisidir.

Yapılacak: Gövdeye bakarak iki durumu ayırın. Gerçek yoğunlukta Retry-After veya üstel geri çekilmeyle bekleyin. Doğrulama sayfası görüyorsanız, yeniden denemek yerine hızınızı ve istemci kimliğinizi gözden geçirin. Tarayıcı otomasyonunda bu ekranların neden çıktığını Puppeteer ve CAPTCHA yazımızda anlattık.

502, 504 ve bağlantı hataları

Proxy kullanan bir scraper, hedef siteden gelen yanıtların yanında proxy'nin kendisinden gelen hatalarla da karşılaşır. Bu kodlar, sorunun zincirin hangi halkasında olduğunu anlamak için önemlidir.

  • 500 Internal Server Error: Hedef uygulamada bir hata oluştu. Bazen belirli bir sayfaya özgüdür. Bir iki kez yeniden denenebilir; sürekli tekrarlanıyorsa o adresi atlayın.
  • 502 Bad Gateway: Aradaki bir ağ geçidi (proxy, CDN veya reverse proxy) arkadaki sunucudan geçerli bir yanıt alamadı. Proxy bağlamında, proxy'nin hedefe ulaşamadığı anlamına gelebilir. Kısa bir beklemeyle yeniden denenir.
  • 504 Gateway Timeout: Ağ geçidi, arkadaki sunucudan zamanında yanıt alamadı. Hedef yavaşsa veya proxy'nin çıkış noktası uzaksa görülür. Yeniden denenir.
  • 408 Request Timeout: Sunucu, isteğin tamamlanmasını beklerken zaman aşımına uğradı. Yeniden denenir.
  • Bağlantı hataları: Kod yoktur, istemci bir istisna fırlatır. Bağlantı reddedildi (ECONNREFUSED), bağlantı sıfırlandı (ECONNRESET), zaman aşımı, alan adı çözülemedi (ENOTFOUND) gibi. Adres veya port yanlışsa hiçbir deneme düzeltmez; ağ kopması gibi geçici durumlarda yeniden deneme işe yarar.
  • CDN'e özgü kodlar: Bazı CDN'ler 520-526 aralığında standart dışı kodlar kullanır. Bunlar genellikle CDN ile sitenin kendi sunucusu arasındaki bağlantı sorunlarını anlatır.

404 Not Found ve 410 Gone ise sayfanın olmadığını söyler. Yeniden denemek yerine adresi listenizden çıkarın; aniden çok sayıda 404 görüyorsanız sitenin adres yapısı değişmiş olabilir.

Retry-After nasıl kullanılır?

Retry-After başlığı iki biçimde gelebilir:

  • Saniye cinsinden sayı: Retry-After: 120 → 120 saniye bekleyin.
  • HTTP tarihi: Retry-After: Wed, 16 Sep 2026 07:28:00 GMT → bu tarihten sonra deneyin.

Doğru kullanım için dört kural:

  1. Başlık varsa tahmin etmeyin, uyun. Sunucunun verdiği süre, sizin hesaplayacağınız geri çekilmeden daha doğrudur.
  2. Üst sınır koyun. Başlık birkaç saat gibi uzun bir süre söylüyorsa, betiğinizin o süre boyunca asılı kalması yerine adresi daha sonraki bir çalıştırmaya bırakın.
  3. Beklemeyi yalnızca o isteğe değil, o siteye uygulayın. 429 alan bir isteği beklettiğiniz sırada aynı siteye paralel olarak başka istekler gönderiyorsanız sınır aşılmaya devam eder.
  4. Tarih biçimini de ayrıştırın. Yalnızca sayı bekleyen kod, tarih biçimiyle gelen başlığı yok sayar. İki biçimi de işleyen bir Python fonksiyonunu Web Scraping'de Engellenmeden Veri Toplama Yöntemleri yazımızda paylaştık.

Hangi kodda yeniden denenir, hangisinde durulur?

KodAnlamıScraping'deki olası nedenYapılacak
200BaşarılıSayfa geldi, ama doğrulama ekranı olabilirİçerikte beklenen öğeyi kontrol et
301 / 302YönlendirmeAdres değişti veya giriş sayfasına yönlendirmeYönlendirmeyi izle; giriş sayfasıysa oturumu kontrol et
400Hatalı istekBozuk parametre veya gövdeDurdur, isteği düzelt
401Kimlik gerekliGiriş veya API anahtarı eksikDurdur, kimlik bilgisini ekle
403ReddedildiIP türü, konum, header, WAF kuralıDurdur, teşhis et
404 / 410Sayfa yokSilinmiş ürün, değişen adres yapısıListeden çıkar
407Proxy kimliği gerekliYanlış şifre, kodlanmamış karakter, whitelistDurdur, proxy ayarını düzelt
408İstek zaman aşımıYavaş bağlantıYeniden dene
429Çok fazla istekHız sınırı aşıldıRetry-After kadar bekle, hızı düşür
500Sunucu hatasıHedef uygulamada hataBirkaç kez dene, sonra atla
502Hatalı ağ geçidiProxy veya CDN hedefe ulaşamadıKısa beklemeyle yeniden dene
503Hizmet yokYoğunluk, bakım veya koruma sayfasıGövdeye bak; Retry-After ile bekle
504Ağ geçidi zaman aşımıHedef yavaş, çıkış noktası uzakYeniden dene, gerekirse daha yakın konum
Bağlantı hatasıYanıt yokAğ kopması, yanlış adres veya portGeçiciyse dene; kalıcıysa yapılandırmayı düzelt

Örnek: koda göre karar veren yeniden deneme

Aşağıdaki örnek HTTPX'in asenkron istemcisiyle çalışır. 408, 429 ve 5xx kodlarında Retry-After başlığına uyar, başlık yoksa rastgele bileşenli üstel geri çekilme uygular. 403, 404 ve 407 gibi yeniden denemenin sonucu değiştirmeyeceği kodlarda ise ayrı bir istisna fırlatarak durur. Proxy kimlik doğrulama hatası (HTTPS isteklerinde ProxyError olarak gelir) de bu gruba girer.

python
import asyncio
import random

import httpx

RETRY_STATUS = {408, 429, 500, 502, 503, 504}
STOP_STATUS = {400, 401, 403, 404, 407, 410}


class StopScraping(Exception):
    """Yeniden denemenin sonucu değiştirmeyeceği durumlar."""


def backoff(response, attempt, base=1.0, cap=60.0):
    retry_after = response.headers.get("Retry-After") if response is not None else None
    if retry_after and retry_after.isdigit():
        return min(int(retry_after), cap)
    return min(cap, base * 2**attempt) * random.uniform(0.5, 1.0)


async def fetch(client, url, attempts=5):
    for attempt in range(attempts):
        response = None
        try:
            response = await client.get(url)
        except httpx.ProxyError as exc:
            raise StopScraping(f"Proxy hatası (kimlik bilgilerini kontrol edin): {exc}") from exc
        except httpx.TransportError:
            pass  # bağlantı kopması, zaman aşımı: yeniden denenebilir
        else:
            status = response.status_code
            if status < 400:
                return response
            if status in STOP_STATUS:
                raise StopScraping(f"{url}: HTTP {status}, yeniden denenmeyecek")
            if status not in RETRY_STATUS:
                return response
        await asyncio.sleep(backoff(response, attempt))
    raise RuntimeError(f"{url}: {attempts} denemede sonuç alınamadı")


async def main():
    proxy = "http://kullanici:parola@pr.proxynet.io:8000"
    async with httpx.AsyncClient(proxy=proxy, timeout=20, follow_redirects=True) as client:
        urls = ["https://ornek.com/urun/1", "https://ornek.com/urun/2"]
        results = await asyncio.gather(*(fetch(client, u) for u in urls), return_exceptions=True)
        for url, result in zip(urls, results):
            print(url, result if isinstance(result, Exception) else result.status_code)


asyncio.run(main())

Örneği iki noktada kendi işinize göre genişletin. Birincisi, asyncio.gather bütün adresleri aynı anda başlatır; gerçek bir işte aynı siteye aynı anda giden istek sayısını asyncio.Semaphore ile sınırlayın. İkincisi, Retry-After HTTP tarihi olarak da gelebilir; bu biçimi de ayrıştırmanız gerekiyorsa yukarıda bağlantısını verdiğimiz fonksiyonu kullanın. HTTPX ve diğer Python kütüphanelerinin farkları HTTPX, Requests ve AIOHTTP yazımızda.

Hataları kaydetmek ve izlemek

Durum kodlarını yalnızca anlık karar için değil, işin sağlığını izlemek için de kullanın. Her çalıştırmada şu sayıları kaydetmek, sorunları erken fark etmenizi sağlar:

  • Koda göre yanıt sayısı: 429 oranı artıyorsa hızınız fazla; 403 oranı artıyorsa IP veya header tarafında bir değişiklik var.
  • Site ve uç noktaya göre dağılım: Sorun tek bir sitede mi, bütün sitelerde mi? Bütün sitelerde aynı anda artan hatalar genellikle proxy veya ağ tarafını gösterir.
  • Yeniden deneme sayısı ve toplam bekleme süresi: Yeniden denemeler işin süresinin önemli bir kısmını alıyorsa eşzamanlılık ayarı yanlıştır.
  • 200 ama beklenen öğesi olmayan yanıtlar: Sessiz veri kaybının tek göstergesi budur.

Kullanım senaryoları

  • Günlük fiyat takibi: 404 alan ürünler listeden çıkarılır, 429 alan siteler için ertesi çalıştırmada eşzamanlılık düşürülür. Genel kurgu veri kazıma çözümü sayfamızda.
  • Çok sayıda siteden katalog toplama: Tek bir sitede artan 403 oranı o site için ayrı teşhis gerektirir; yük dağıtımı için Rotating Proxy kullanılır.
  • Oturum gerektiren kendi paneliniz: 302 ile giriş sayfasına yönlendirme, oturum ortasında IP değiştiğini gösterebilir; oturum boyunca aynı IP için Sticky Proxy tercih edilir.
  • Yeni proxy kurulumu: İlk isteklerde 407 veya ProxyError görüyorsanız sorun hedefte değil, kimlik bilgilerindedir.

Sık yapılan hatalar

  • Her hatada aynı sayıda yeniden denemek. 403 ve 407'yi tekrar etmek sonucu değiştirmez, yalnızca gereksiz trafik üretir.
  • Retry-After başlığını okumamak. Sunucu size ne kadar beklemeniz gerektiğini söylemişken kendi tahmininizle erken dönmek.
  • Geri çekilmeye rastgele bileşen eklememek. Aynı anda başarısız olan yüzlerce istek, aynı anda yeniden denenir ve yeni bir yığılma oluşturur.
  • 200 yanıtını içeriğe bakmadan kabul etmek. Doğrulama sayfaları sessizce boş veri üretir.
  • 407'yi hedef sitenin hatası sanmak. Hedefi değil, proxy yapılandırmanızı kontrol etmeniz gerekir.
  • Yeniden denemeye üst sınır koymamak. Kalıcı bir sorunda sonsuza kadar dönen bir döngü, hem kaynaklarınızı hem hedef siteyi yorar.

Karar rehberi

Gördüğünüzİlk yapılacak
429Retry-After kadar bekleyin, eşzamanlılığı düşürün
503 ve normal hata sayfasıBekleyin ve yeniden deneyin
503 ve doğrulama sayfasıDurun, hızı ve istemci kimliğini gözden geçirin
403Aynı IP ile tarayıcıda deneyin, nedeni teşhis edin
407 veya ProxyErrorProxy kullanıcı adı, şifre ve whitelist'i kontrol edin
502 / 504Kısa beklemeyle yeniden deneyin; sürerse çıkış konumunu değiştirin
404 / 410Adresi listeden çıkarın
200 ama veri yokDoğrulama sayfası veya dinamik yükleme olup olmadığını kontrol edin

Sık sorulan sorular

403 ile 401 arasındaki fark nedir?

401 Unauthorized, isteğin kimlik doğrulaması gerektirdiğini ve geçerli bir kimlik bilgisi göndermediğinizi söyler. 403 Forbidden ise sunucunun isteği anladığını ama kimlik bilgisinden bağımsız olarak reddettiğini söyler. 401'de kimlik eklemek çözüm olabilir, 403'te genellikle olmaz.

407 hatası neden hedef siteden değil de proxy'den gelir?

Çünkü istek hedefe hiç ulaşmamıştır. Proxy, bağlantıyı iletmeden önce kimliğinizi doğrular ve doğrulama başarısız olursa yanıtı kendisi verir. Bu yüzden 407 hedef sitenin kurallarıyla ilgisizdir.

429 aldıktan sonra IP değiştirmek çözüm mü?

Hız sınırı IP'ye göre sayılıyorsa geçici olarak sonuç verebilir, ama sorunun kaynağı olan hızı değiştirmez ve sınır oturum veya hesap bazındaysa hiç işe yaramaz. Doğru tepki beklemek ve hızı düşürmektir; rotasyon, başından beri yükü dağıtmak için planlanmalıdır.

Retry-After başlığı yoksa ne kadar beklemeliyim?

Üstel geri çekilme uygulayın: birkaç saniyeyle başlayıp her denemede ikiye katlayın, bir üst sınır koyun ve her beklemeye rastgele bir bileşen ekleyin. Birkaç denemeden sonra hâlâ başarısızsa adresi sonraki bir çalıştırmaya bırakın.

503 hatası sitenin çöktüğü anlamına mı gelir?

Her zaman değil. Bakım, geçici yoğunluk veya bot korumasının verdiği bir engel de olabilir. Yanıt gövdesine bakın: bir bakım mesajı mı, genel bir hata sayfası mı, yoksa doğrulama ekranı mı?

Proxy kullanırken 502 hatası alıyorum. Sorun nerede?

502, aradaki ağ geçidinin arkadaki sunucudan geçerli yanıt alamadığını söyler. Proxy bağlamında, proxy'nin hedefe ulaşamadığını veya hedefin bağlantıyı kestiğini gösterebilir. Aynı adresi proxy olmadan deneyin: proxy'siz çalışıyorsa proxy'nin çıkış noktasında, proxy'siz de çalışmıyorsa hedef sitede bir sorun vardır.

Özetle

HTTP durum kodları scraper'ınıza ne yapması gerektiğini söyler: 429 ve 503 beklemeyi, 403 teşhisi, 407 proxy yapılandırmasını düzeltmeyi, 404 adresi listeden çıkarmayı ister. Retry-After başlığı varsa ona uyun, yoksa rastgele bileşenli üstel geri çekilme kullanın ve her yeniden denemeye bir üst sınır koyun. 200 yanıtlarında da içeriği kontrol etmeyi ihmal etmeyin. Veri toplama işleriniz için uygun proxy türlerini proxy hizmetlerimizde bulabilirsiniz.

ChatGPT'ye sorClaude'a sor