---
title: "Max Retries Exceeded With URL Hatası Nedir, Nasıl Çözülür?"
description: "Max Retries Exceeded With URL, Requests'te asıl bağlantı hatasını saran mesajdır. Nedeni parantezdeki Caused by kısmında yazar; okumayı ve çözümü anlatıyoruz."
url: https://proxynet.io/tr/blog/max-retries-exceeded-with-url
date: 2026-09-24
author: "Acar Diveroli"
category: "Nasıl Yapılır, Web Scraping"
lang: tr
---

# Max Retries Exceeded With URL Hatası Nedir, Nasıl Çözülür?

Fiyat takip betiğiniz bütün gece sorunsuz çalıştı. Bu sabah yeni paketinizin proxy adresini betiğe yapıştırdınız ve terminal artık tek bir uzun satır basıyor: `HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url`. Betikte yeniden deneme ayarı yok, mesajdaki host da veri topladığınız mağaza; bu yüzden gözünüz hemen mağazaya gidiyor. Oysa satırın en sonunda, parantez içinde `Tunnel connection failed: 403 Forbidden` yazıyor ve bu cevabı mağaza değil, proxy vermiş.

Bu yazıda mesajı parçalarına ayırıyor ve hiç ayarlamadığınız hâlde neden "max retries" dediğini anlatıyoruz. Ardından kendi ürettiğimiz hata dizgilerinden hazırladığımız okuma tablosu, proxy'ye özgü türevler, zaman aşımları ve aynı hatanın pip'teki hâli geliyor. Sonda nedeni adıyla söyleyen, denenmiş bir Python betiği var.

> **Not: Kısa cevap**
>
> "Max retries exceeded with url", urllib3'ün `MaxRetryError` hatasının metnidir ve tek başına bir neden söylemez. Requests varsayılan olarak yeniden deneme yapmadığı için bu mesajı tek bir başarısız denemeden sonra da görürsünüz. Asıl neden parantez içindeki `Caused by` kısmında yazar: `NameResolutionError` bir adın çözülemediğini, `NewConnectionError` bağlantının reddedildiğini, `ConnectTimeoutError` bağlantının süre içinde kurulamadığını, `SSLError` sertifikanın doğrulanamadığını, `ProxyError` ise sorunun sizinle proxy arasında olduğunu gösterir. `Tunnel connection failed: 403`, proxy'nin CONNECT isteğinizi (şifreli bağlantı için tünel açma isteğini) reddettiği anlamına gelir. Proxy URL'sinin `http://` ile başladığını ve portu kontrol edin, her isteğe de `timeout=(bağlantı, okuma)` verin.

## "Max retries exceeded with url" ne anlama gelir?

Mesajı urllib3 üretir; Requests bağlantıları bu kütüphane üzerinden açar. urllib3 bir istekten vazgeçtiğinde `MaxRetryError` fırlatır. Requests bu hatayı yakalar ve içteki nedene göre seçtiği kendi istisnasını (exception) fırlatır: `ConnectTimeout`, `ProxyError`, `SSLError`, durum koduna göre yeniden denemeler tükendiğinde `RetryError`, geri kalan her durumda düz `ConnectionError`. Test çalıştırmamızdan aldığımız bir dizgiyi dört parçasına ayırdık:

```text
requests.exceptions.ProxyError                        <- 1. Requests istisnası
HTTPSConnectionPool(host='example.com', port=443):    <- 2. havuz: hedef host ve port
Max retries exceeded with url: /                      <- 3. saran metin ve yol
(Caused by ProxyError('Unable to connect to proxy',   <- 4. asıl neden, dıştan içe
    OSError('Tunnel connection failed: 403 Forbidden')))
```

Çoğu kişi 2. parçada yanılır. Bir `https://` URL'sinde havuz satırı, istek proxy üzerinden gitse bile **hedefi** gösterir; proxy adresi yalnız 4. parçada geçer, o da her zaman değil. Proxy üzerinden gönderilen düz bir `http://` URL'de durum tersine döner: havuz satırı proxy'yi gösterir, hedefin tam URL'si de 3. parçada yer alır, örneğin `HTTPConnectionPool(host='127.0.0.1', port=8083): Max retries exceeded with url: http://example.com/`.

## Hiç yeniden deneme ayarlamadığınız hâlde neden "max retries" yazıyor?

Requests başarısız bağlantıları varsayılan olarak yeniden denemez. `requests/adapters.py` kaynak kodunda `DEFAULT_RETRIES = 0` tanımlıdır ve adaptör bunu `Retry(0, read=False)` nesnesine çevirir. urllib3 dokümantasyonu [Retry sınıfı](https://urllib3.readthedocs.io/en/stable/reference/urllib3.util.html) için, yeniden denemeler `retries=False` ile kapatılmadıkça hataların `MaxRetryError` içine sarıldığını söyler. Sıfır yeniden deneme "kapalı" sayılmaz; bu yüzden tek bir başarısız deneme bile "Max retries exceeded" diye çıkar.

Yeniden deneme sayısını artırmak nedeni ortadan kaldırmaz. Yanlış yazılmış bir proxy adı, yanlış port ya da reddedilen bir tünel her seferinde aynı şekilde düşer. Testimizde bağlantı zaman aşımı 2 saniye olan ulaşılamaz bir adres, varsayılan ayarla 2 saniyede, iki yeniden deneme ve kısa bir beklemeyle (backoff) 7 saniyede hata verdi. Yeniden deneme yalnız kısa ağ kopmalarında işe yarar.

## Hata mesajı adım adım nasıl okunur?

Mesajı dıştan içe doğru okuyun:

1. **Requests istisnasını bulun.** `ProxyError`, hatanın proxy'ye giden yolda ya da proxy'nin kendisinde oluştuğunu söyler.
2. **Havuz satırını okuyun.** `https://` hedeflerde `host` ve `port` hedefe aittir. HTTP proxy üzerinden 443 portu görüyorsanız istek bir CONNECT tünelinden geçiyordur.
3. **`Caused by` sonrasındaki ilk sınıfı okuyun.** Bu, urllib3'ün teşhisidir: `NameResolutionError`, `NewConnectionError`, `ConnectTimeoutError`, `SSLError` ya da `ProxyError`.
4. **En içteki metni okuyun.** `Failed to resolve 'name'`, Linux'ta `[Errno 111] Connection refused`, Windows'ta `[WinError 10061]`, `CERTIFICATE_VERIFY_FAILED` ya da `Tunnel connection failed: 403 Forbidden`. Burada geçen bir `host=` proxy'ye ait olabilir.
5. **Çağrının ne kadar sürdüğüne bakın.** Tam olarak bağlantı zaman aşımınız kadar (ya da onun katları kadar) süren bir hata zaman aşımıdır; daha çabuk düşen bir hata ise bağlantı reddi ya da reddedilen bir tüneldir. Testlerimizde Windows'ta reddedilen bir bağlantı adres başına yaklaşık iki saniye, `localhost` ise dört saniye sürdü (önce IPv6, sonra IPv4).

## HTTPSConnectionPool hataları: Caused by kısmı ne söyler?

Aşağıdaki dizgilerin hepsini Python 3.13, Requests 2.34.2 ve urllib3 2.8.0 ile, yerel bir test proxy'si üzerinden kendimiz ürettik. Uzun kısımlar `...` ile kısaltıldı; Windows hata metni ayrıca sistem diline göre değişir.

| Caused by (en içteki kısım) | Requests istisnası | Ne oldu | Önce kontrol edin |
|---|---|---|---|
| `NameResolutionError(... Failed to resolve 'no-such-host.invalid' ...)` | `ConnectionError` | Hedef adı çözülemedi | URL yazımı, DNS, VPN |
| `NewConnectionError(... [Errno 111] or [WinError 10061] ...)` | `ConnectionError` | O portu dinleyen bir şey yok | Servis çalışıyor mu, port doğru mu |
| `ConnectTimeoutError(... 'Connection to 10.255.255.1 timed out. (connect timeout=2)')` | `ConnectTimeout` | Süre içinde TCP bağlantısı kurulamadı | Adres, güvenlik duvarı, zaman aşımı değeri |
| `SSLError(SSLCertVerificationError(... CERTIFICATE_VERIFY_FAILED ...))` | `SSLError` | Sertifikaya güvenilmiyor | certifi, kurumsal kök sertifika |
| `ProxyError('Unable to connect to proxy', NewConnectionError(...))` | `ProxyError` | Proxy portu bağlantıyı reddetti | Proxy host ve portu, yerel güvenlik duvarı |
| `ProxyError('Unable to connect to proxy', NameResolutionError(... 'pr.proxynet.invalid' ...))` | `ProxyError` | Proxy adı çözülemedi | Proxy host'unda yazım hatası |
| `ProxyError('Unable to connect to proxy', ConnectTimeoutError(...))` | `ProxyError` | Proxy zamanında cevap vermedi | Proxy adresi, o port için giden bağlantı kuralları |
| `ProxyError(..., OSError('Tunnel connection failed: 403 Forbidden'))` | `ProxyError` | Proxy CONNECT tünelini reddetti | Hedef port, proxy türü ve portu, izin kuralları |
| `ProxyError(..., OSError('Tunnel connection failed: 407 Proxy Authentication Required'))` | `ProxyError` | Proxy geçerli kimlik bilgisi istiyor | Bkz. [Proxy Kimlik Doğrulama](/tr/blog/proxy-authentication-methods) |
| `ProxyError(..., OSError('Tunnel connection failed: 502 Bad Gateway'))` | `ProxyError` | Proxy hedefe ulaşamadı | Hedef host ve port |
| `ProxyError('... Your proxy appears to only use HTTP and not HTTPS ...', SSLError(... WRONG_VERSION_NUMBER ...))` | `ProxyError` | Proxy URL'si `https://` ile başlıyor | `http://` yazın |

Tabloya girmeyen üç ayrıntı var. Zaman aşımına uğrayan bir proxy `ProxyError` fırlatır; yani `except ConnectTimeout` onu hiç yakalamaz. Okuma zaman aşımı sarılmaz: `Read timed out. (read timeout=3)` metniyle `ReadTimeout` olarak gelir. Proxy üzerinden gönderilen düz bir `http://` URL'de şifre yanlışsa da hiçbir istisna oluşmaz; `407` durum kodlu bir yanıt alırsınız.

## "ProxyError: Cannot connect to proxy" ne anlama gelir?

`Cannot connect to proxy.` (urllib3 1.26) ile `Unable to connect to proxy` (urllib3 2.x) aynı hatadır. İkisi aynı makinede de görülebilir: pip 25.x kendi içinde urllib3 1.26.20 taşır, sıfırdan kurulan Requests ise urllib3 2.8.0'ı çeker. İfadeye değil, ikinci argümana bakın:

- **`NewConnectionError`**: o proxy portunu dinleyen bir şey yok ya da yerel bir güvenlik duvarı engelliyor. Host ve portu panelden yeniden kopyalayın.
- **`NameResolutionError`**: proxy host adı yanlış yazılmış ya da DNS'iniz bu adı çözemiyor.
- **`ConnectionResetError`** (Linux'ta `Errno 104`, Windows'ta `WinError 10054`): proxy ya da yoldaki bir cihaz bağlantıyı kapattı.
- **`OSError('Tunnel connection failed: ...')`**: proxy cevap verdi ama tüneli açmadı; durum kodu onun cevabıdır.

Tarayıcıdaki karşılığı olan "Proxy sunucusu yanıt vermiyor" hatası için [Proxy Hatası Nedir?](/tr/blog/proxy-server-not-responding) yazımıza bakın.

## Tunnel connection failed: 403 Forbidden: proxy CONNECT'i neden reddeder?

HTTP proxy üzerinden giden bir `https://` isteği `CONNECT example.com:443` ile başlar. Proxy hedefe bir TCP bağlantısı açar ve şifreli baytları iki yana aktarır; sayfanın içeriğini hiç görmez. [RFC 9110'un 9.3.6 bölümüne](https://www.rfc-editor.org/rfc/rfc9110.html#name-connect) göre 2xx dışındaki her cevap, tünelin kurulmadığı anlamına gelir. Python'un `http.client` modülü bu cevabı okur ve `Tunnel connection failed` yazar.

`403` proxy'nin kararıdır; hedef site isteğinizi hiç görmedi. RFC, proxy'lerin CONNECT'i bilinen portlarla ya da güvenli hedeflerden oluşan bir listeyle sınırlaması gerektiğini söyler, çünkü 25 portuna açılan bir tünel spam aktarmak için kullanılabilir. Sık görülen nedenler:

- **Hedef portuna izin yok.** `https://example.com:8443/` başarısız olurken `https://example.com/` çalışabilir.
- **İzin listesi.** Kurumsal proxy'ler ve bazı barındırma platformları yalnız onaylı alan adlarına izin verir. BT ekibine sorun ya da platformun dokümantasyonunu okuyun; politikayı aşmaya çalışmayın.
- **Yanlış proxy türü ya da port**, örneğin başka bir protokol için ayrılmış bir port.
- **Sağlayıcı kuralları.** Bir sağlayıcı bazı hedeflere tünel açmayı reddedebilir; hangi durum kodlarını kullandığı dokümantasyonunda yazar.

Hedef siteden gelen `403` ise sayfasıyla birlikte normal bir yanıt olarak gelir; bu durumu [Scraping'de HTTP Hata Kodları](/tr/blog/http-status-codes-web-scraping) yazısında anlattık. Tünelde `407` görürseniz proxy kimlik bilgisi istiyor demektir.

## Proxy URL'si http:// ile mi, https:// ile mi başlamalı?

`proxies` sözlüğünde anahtar **hedefin** şemasıdır, değer ise **proxy'ye** nasıl ulaşılacağıdır. Requests dokümantasyonunun kendi örneği `'https'` anahtarını `'http://10.10.1.10:1080'` değerine bağlar. Çoğu proxy düz HTTP konuşur ve şifreli siteler için bir CONNECT tüneli açar ([HTTPS proxy](/tr/https-proxy) sayfamıza bakın); bu yüzden iki anahtarın değeri de `http://` ile başlar:

```python
proxies = {
    "http": "http://user:pass@pr.proxynet.io:8000",
    "https": "http://user:pass@pr.proxynet.io:8000",  # burada da http://
}
```

Değerde `https://` varsa urllib3 2.x proxy'nin kendisiyle TLS bağlantısı kurmaya çalışır, düz bir HTTP proxy TLS olmayan baytlarla cevap verir ve `Your proxy appears to only use HTTP and not HTTPS` ipucuyla birlikte `WRONG_VERSION_NUMBER` hatası alırsınız. urllib3'ün [bu hatayı anlatan sayfası](https://urllib3.readthedocs.io/en/latest/advanced-usage.html#https-proxy-error-http-proxy) aynı çözümü verir; yanlış yazılmış bir `HTTPS_PROXY` değişkeni için de geçerlidir.

İlgili iki nokta:

- **SOCKS.** `requests[socks]` paketini kurun. `socks5://` ile adı sizin makineniz çözer, bu yüzden testimizde hatalı bir ad proxy'ye hiç ulaşmadan düştü; `socks5h://` ile adı proxy çözer ([SOCKS ve HTTP Proxy Farkı](/tr/blog/socks-vs-http-proxy), [SOCKS5 proxy](/tr/socks5-proxy)).
- **Ortam değişkenleri.** [Requests'in ileri kullanım sayfası](https://requests.readthedocs.io/en/latest/user/advanced/), ortamdaki proxy ayarlarının `session.proxies` değerini ezebileceği konusunda uyarır ve her istekte `proxies=` vermeyi önerir. Bu değişkenleri [wget ile Proxy Kullanımı](/tr/blog/wget-proxy) yazısında anlattık.

## Timeout vermezseniz ne olur? ConnectTimeout ve ReadTimeout farkı

Requests'in varsayılan bir zaman aşımı yoktur: `timeout=` vermezseniz bir çağrı dakikalarca asılı kalabilir ve size okuyacak bir hata bile bırakmaz. `timeout=(3.05, 20)` gibi bir tuple verin: önce bağlantı, sonra okuma zaman aşımı, saniye cinsinden. Dokümantasyon, bağlantı zaman aşımını 3'ün bir katının biraz üstüne koymayı önerir; 3 saniye, TCP'nin varsayılan yeniden iletim penceresidir.

İki zaman aşımı farklı şekilde düşer:

- **ConnectTimeout**: süre içinde TCP bağlantısı kurulamadı. "Max retries exceeded" içine sarılı gelir ve API referansı bu hatayı yeniden denemesi güvenli sayar.
- **ReadTimeout**: bağlantı kuruldu ama okuma zaman aşımı içinde veri gelmedi. Sarılmaz; sunucu isteği çoktan işlemiş olabilir, bu yüzden bir POST'u yeniden denemek aynı işi iki kez yaptırabilir.

Bağlantı zaman aşımı her IP adresi için ayrı işler; hem IPv4 hem IPv6 adresi olan bir adda bekleme iki katına çıkabilir. Okuma zaman aşımı iki bayt arasındaki boşluğa konan sınırdır, indirmenin tamamına değil. Diğer kütüphanelerin varsayılanlarını [HTTPX, Requests ve AIOHTTP Karşılaştırması](/tr/blog/httpx-vs-requests-vs-aiohttp) yazısında bulabilirsiniz.

## Aynı hata pip'te: "Retrying ... after connection broken by"

pip kendi Requests ve urllib3 kopyalarını taşır, bu yüzden `pip install` aynı nedenlerle düşer. [pip dokümantasyonu](https://pip.pypa.io/en/stable/cli/pip/) varsayılanları `--retries 5` ve `--timeout 15` saniye olarak verir. pip 26.2.1'i `--retries 2` ile, her CONNECT'i `403` ile reddeden yerel bir proxy üzerinden çalıştırdık:

```text
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'OSError('Tunnel connection failed: 403 Forbidden')': /simple/six/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'OSError('Tunnel connection failed: 403 Forbidden')': /simple/six/
ERROR: Could not find a version that satisfies the requirement six (from versions: none)
ERROR: No matching distribution found for six
```

Paket var; pip paket dizinine hiç ulaşamadı. Neden `WARNING` satırlarında yazıyor. pip 25.2 aynı uyarıyı urllib3 1.26'nın ifadesiyle bastı: `ProxyError('Cannot connect to proxy.', ...)`.

TLS trafiğini inceleyen bir kurumsal proxy arkasında `CERTIFICATE_VERIFY_FAILED` alıyorsanız kurumun kök sertifikasını `--cert` ile verin; `--trusted-host` doğrulamayı kapatır ve son çaredir. pip'e proxy tanıtmayı [Linux Proxy Ayarları](/tr/blog/linux-proxy-settings) yazısında anlattık.

## Nedeni söyleyen bir Python betiği

Betik bir istisnayı tek satıra çevirir: neyin düştüğünü ve neyin kontrol edileceğini söyler. Şunları yapar:

- yalnız başarısız bağlantıları, iki kez yeniden dener;
- `read=False` ayarını korur: testimizde `read=0`, bir `ReadTimeout` hatasını sarılmış bir `ConnectionError`'a çevirdi;
- `other=0` ayarlar: bu ayar olmadan `403` ya da `407` ile reddedilen bir tünel üç kez denendi;
- her istekte `proxies=` ve `timeout=(3.05, 20)` verir;
- `ProxyError`, `SSLError` ve `ConnectTimeout` istisnalarını, üst sınıfları olan `ConnectionError`'dan önce yakalar.

Durum koduna göre yeniden deneme ayrı bir katmandır ([Scraping'de HTTP Hata Kodları](/tr/blog/http-status-codes-web-scraping)), proxy döndürme de öyle ([Python'da Proxy'ler Nasıl Döndürülür?](/tr/blog/rotating-proxy-python)).

```python
"""Max retries exceeded with url hatasının arkasındaki asıl nedeni bulur ve neye bakılacağını söyler."""
import re
import ssl
import time

import requests
from requests.adapters import HTTPAdapter
from urllib3.exceptions import (
    ConnectTimeoutError,
    NameResolutionError,
    NewConnectionError,
    ProxyError as Urllib3ProxyError,
)
from urllib3.util import Retry

PROXY = "http://user:pass@pr.proxynet.io:8000"  # https:// hedeflerde de http://
TIMEOUT = (3.05, 20)  # saniye: (bağlantı, okuma)

def make_session():
    """Başarısız bağlantıları iki kez yeniden deneyen, başka hiçbir şeyi denemeyen bir oturum."""
    retry = Retry(
        total=2,
        connect=2,      # DNS hataları, reddedilen ve zaman aşımına uğrayan bağlantılar
        read=False,     # ReadTimeout, ReadTimeout olarak kalsın: istek sunucuya ulaşmış olabilir
        other=0,        # tüneli reddeden proxy onu yine reddeder
        status=0,       # durum koduna göre yeniden deneme başka bir katmanın işi
        backoff_factor=0.5,
    )
    adapter = HTTPAdapter(max_retries=retry)
    session = requests.Session()
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    return session

def causes(exc):
    """İstisnanın kendisi ve içine sarılmış her hata, dıştan içe."""
    chain = []
    while exc is not None and all(exc is not seen for seen in chain):
        chain.append(exc)
        inner = None
        for candidate in (getattr(exc, "reason", None), getattr(exc, "original_error", None),
                          exc.__cause__, exc.__context__, *exc.args[:2]):
            if isinstance(candidate, BaseException):
                inner = candidate
                break
        exc = inner
    return chain

def explain(exc):
    """Tek satır: ne düştü, hangi tarafta ve önce neye bakılmalı."""
    chain = causes(exc)
    text = " | ".join(str(e) for e in chain)
    side = "proxy" if any(isinstance(e, Urllib3ProxyError) for e in chain) else "target"

    tunnel = re.search(r"Tunnel connection failed: (\d{3})", text)
    if tunnel:
        code = tunnel.group(1)
        if code == "407":
            return "proxy asked for credentials (407): check user:pass or the IP whitelist"
        if code == "403":
            return "proxy refused the CONNECT tunnel (403): check the target port and the proxy's allow rules"
        return f"proxy was reached but could not reach the target ({code}): check the target host and port"
    if "appears to only use HTTP" in text:
        return "proxy URL starts with https:// but the proxy speaks plain HTTP: write http://"
    if any(isinstance(e, NameResolutionError) for e in chain):
        host = re.search(r"Failed to resolve '([^']+)'", text)
        return f"{side} name {host.group(1) if host else ''} does not resolve: check spelling, DNS and VPN"
    if any(isinstance(e, ssl.SSLCertVerificationError) for e in chain):
        return "certificate not trusted: update certifi or set REQUESTS_CA_BUNDLE to your company root CA"
    if isinstance(exc, requests.exceptions.ReadTimeout):
        return "connected, but no answer within the read timeout: the server may have the request"
    if any(isinstance(e, NewConnectionError) for e in chain):
        return f"{side} refused the connection: wrong port, service down, or a firewall rejects it"
    if any(isinstance(e, ConnectTimeoutError) for e in chain):
        return f"no TCP connection to the {side} within the connect timeout: check address, port, firewall"
    return f"unrecognised, read the innermost error: {chain[-1]!r}"

def fetch(session, url, proxy=PROXY):
    """Tek bir URL'ye GET atar; durumu ya da istek düştüyse teşhisi yazdırır."""
    proxies = {"http": proxy, "https": proxy} if proxy else None  # istek başına: ortam değişkenleri bunu ezemez
    start = time.monotonic()
    try:
        resp = session.get(url, proxies=proxies, timeout=TIMEOUT)
    except requests.exceptions.ProxyError as exc:      # ConnectionError'dan önce: onun alt sınıfı
        kind, error = "ProxyError", exc
    except requests.exceptions.SSLError as exc:        # bu da bir ConnectionError
        kind, error = "SSLError", exc
    except requests.exceptions.ConnectTimeout as exc:  # aynı anda hem ConnectionError hem Timeout
        kind, error = "ConnectTimeout", exc
    except requests.exceptions.ReadTimeout as exc:     # asla "Max retries exceeded" içine sarılmaz
        kind, error = "ReadTimeout", exc
    except requests.exceptions.ConnectionError as exc:
        kind, error = "ConnectionError", exc
    else:
        print(f"{'OK':<16}{time.monotonic() - start:6.2f}s  {url}  HTTP {resp.status_code}")
        return resp
    print(f"{kind:<16}{time.monotonic() - start:6.2f}s  {url}\n{'':<24}{explain(error)}")
    return None

if __name__ == "__main__":
    session = make_session()
    for url in ["https://httpbin.org/ip", "https://example.com/"]:
        fetch(session, url)
```

urllib3 2.x'te `NameResolutionError`, `NewConnectionError` sınıfının alt sınıfıdır; o da `ConnectTimeoutError` sınıfının alt sınıfıdır. Bu yüzden `explain()` önce en özel sınıfı sınar. Betik için `pip install requests` yeterli.

### Çıktı nasıl görünüyor?

`fetch()` fonksiyonunu Windows 11'de her durum için bir kez çalıştırdık: yerel bir test proxy'si (doğru ve yanlış şifre, kapalı port, yanlış yazılmış ad, `https://` şeması), her CONNECT'i reddeden ikinci bir proxy, sertifika ve zaman aşımı durumları için de gerçek host'lar. Okuma zaman aşımı 5 saniyeydi:

```text
OK                0.77s  https://httpbin.org/ip  HTTP 200
ProxyError        0.02s  https://httpbin.org/ip
                        proxy asked for credentials (407): check user:pass or the IP whitelist
ProxyError        0.00s  https://example.com/
                        proxy refused the CONNECT tunnel (403): check the target port and the proxy's allow rules
ProxyError        0.02s  https://no-such-host.invalid/
                        proxy was reached but could not reach the target (502): check the target host and port
ProxyError        7.10s  https://httpbin.org/ip
                        proxy refused the connection: wrong port, service down, or a firewall rejects it
ProxyError        1.02s  https://httpbin.org/ip
                        proxy name pr.proxynet.invalid does not resolve: check spelling, DNS and VPN
ProxyError        0.21s  https://httpbin.org/ip
                        proxy URL starts with https:// but the proxy speaks plain HTTP: write http://
SSLError          0.63s  https://self-signed.badssl.com/
                        certificate not trusted: update certifi or set REQUESTS_CA_BUNDLE to your company root CA
ConnectTimeout   10.16s  http://10.255.255.1/
                        no TCP connection to the target within the connect timeout: check address, port, firewall
ReadTimeout       5.02s  http://127.0.0.1:8082/
                        connected, but no answer within the read timeout: the server may have the request
ConnectionError  13.12s  http://localhost:8083/
                        target refused the connection: wrong port, service down, or a firewall rejects it
```

Reddedilen tüneller milisaniyeler içinde düştü, çünkü `other=0` onları durdurdu. Kapalı proxy portunda süre, yaklaşık ikişer saniyelik üç deneme ile bir saniyelik beklemeden oluştu; bağlantı zaman aşımında ise üç kez 3,05 saniye ile beklemeden. `localhost` 13 saniye sürdü, çünkü her deneme önce IPv6'yı, sonra IPv4'ü denedi. `502` ise hedefi çözemeyen test proxy'mizden geldi.

## Bu hatayla nerelerde karşılaşırsınız?

- **Proxy üzerinden web scraping (veri kazıma):** sitelerden otomatik veri toplarken proxy hataları, herhangi bir durum kodu görmeden önce bu mesajla karşınıza çıkar ([proxy üzerinden veri toplama](/tr/data-scraping)).
- **Kurumsal proxy arkasında CI ve Docker derlemeleri:** derlemeler çoğu zaman makinenin proxy ayarlarını almaz, `localhost` da konteynerin kendisidir ([Linux Proxy Ayarları](/tr/blog/linux-proxy-settings)).
- **Sabit çıkış IP'siyle çalışan API entegrasyonları:** reddedilen bir tünel API kesintisi gibi görünür ([API için Statik IP](/tr/blog/static-ip-for-api-access)).
- **Yeni bir proxy'yi denemek:** bütün işi başlatmadan önce zaman aşımı verilmiş tek bir istek gönderin ([Proxy Nasıl Test Edilir?](/tr/blog/how-to-test-a-proxy)).
- **Tarayıcı otomasyonu:** aynı tünel hatası `ERR_TUNNEL_CONNECTION_FAILED` olarak görünür ([Playwright ile proxy kullanımı](/tr/blog/playwright-proxy)).
- **Kurumsal ağlar:** bağlantıları hem güvenlik duvarı hem proxy süzer ([Proxy ve Firewall Farkı](/tr/blog/proxy-vs-firewall)).

## Sık yapılan hatalar

- **Yeniden deneme sayısını artırmak.** Kalıcı bir neden kalıcı kalır; yalnız daha uzun beklersiniz.
- **Adı havuz satırında geçtiği için hedefi suçlamak.** `https://` URL'lerde proxy yalnız parantez içinde görünür.
- **Eski bir `HTTPS_PROXY` değişkenini unutmak.** `session.proxies` ayarının yerine sessizce geçebilir.
- **Canlı ortamda `verify=False` bırakmak.** Requests dokümantasyonu bu ayarın sizi ortadaki adam (man-in-the-middle) saldırılarına açık bıraktığını söyler. certifi'yi güncelleyin ya da `REQUESTS_CA_BUNDLE` ayarlayın; yerel bir hata ayıklama proxy'si için [MITM Proxy](/tr/blog/mitm-proxy) yazısına bakın.
- **Önce `ConnectionError` yakalamak.** `ProxyError`, `SSLError` ve `ConnectTimeout` hatalarını yutar.
- **Tünel `403`'ünü `407` ile karıştırmak.** Biri kural, diğeri kimlik bilgisi sorunudur.
- **pip'te yalnız son satırı okumak.** Neden, onun üstündeki `WARNING` satırlarındadır.

## Karar rehberi

| Ne görüyorsunuz | Ne yapmalı |
|---|---|
| Caused by içinde `NameResolutionError` | Çözülemeyen adı düzeltin (proxy host'u ya da URL); yeniden deneme eklemeyin |
| `NewConnectionError` ile gelen `ProxyError` | Proxy host ve portunu yeniden kopyalayın; yerel güvenlik duvarını kontrol edin |
| `Tunnel connection failed: 403` | Hedef portu, proxy türünü ve portunu, izin kurallarını kontrol edin |
| `Tunnel connection failed: 407` | Kimlik bilgilerini ya da IP whitelist'i kontrol edin |
| `SSLError: CERTIFICATE_VERIFY_FAILED` | certifi'yi güncelleyin ya da `REQUESTS_CA_BUNDLE` ayarlayın (pip: `--cert`) |
| Çağrılar ara sıra asılı kalıyor ya da zaman aşımına uğruyor | `timeout=(3.05, 20)` ve yalnız bağlantı hatalarını deneyen bir `Retry` |
| pip "No matching distribution found" diyor | `WARNING: Retrying` satırını okuyun |

## Sıkça sorulan sorular

### Yeniden deneme sayısını artırmak "Max retries exceeded" hatasını çözer mi?

Yalnız ağ bir anlığına koptuğunda. Çözülemeyen bir ad, kapalı bir port ya da reddedilen bir tünelde her yeniden deneme aynı şekilde düşer. Önce `Caused by` kısmını okuyun.

### Python Requests'te varsayılan timeout nedir?

Yoktur: `timeout=` vermezseniz bir istek süresiz bekleyebilir. Her çağrıya bir `(bağlantı, okuma)` tuple'ı verin.

### Requests'te timeout saniye mi, milisaniye mi?

Saniye. `3.05` gibi ondalıklı bir değer de çalışır; tek bir sayı iki aşamayı birlikte ayarlar, `(3.05, 20)` gibi bir tuple ise ikisini ayrı ayrı.

### CERTIFICATE_VERIFY_FAILED için verify=False kullanabilir miyim?

Yalnız kısa bir yerel denemede, çünkü bu ayar yoldaki herkesin trafiği okumasına ya da değiştirmesine izin verir. Kalıcı çözüm güncel bir certifi ya da, TLS'i inceleyen bir kurumsal proxy arkasındaysanız, o proxy'nin kök sertifikasını `REQUESTS_CA_BUNDLE` ile göstermektir.

### Paket var, pip neden "No matching distribution found" diyor?

pip paket dizinine ulaşamadı, bu yüzden hiçbir sürüm bulamadı. Üstteki `WARNING: Retrying ... after connection broken by` satırları asıl nedeni söyler, örneğin `Tunnel connection failed: 403 Forbidden`.

### localhost:8000'e istek atarken neden bu hatayı alıyorum?

O portu dinleyen bir şey yok: sunucu kapalı, başka bir port kullanıyor ya da kodunuz Docker içinde çalışıyor ve orada `localhost` konteynerin kendisi; en içteki hata `[Errno 111]` ya da `[WinError 10061]` olur. Portu hangi programın tuttuğunu bulmayı [8080 portu yazımızda](/tr/blog/port-8080) anlattık.

## Özet

"Max retries exceeded with url" asıl hatayı saran bir mesajdır: neden `Caused by` sonrasında yazar ve Requests varsayılan olarak yeniden deneme yapmadığı için mesaj tek denemeden sonra da çıkar. Proxy hatalarında proxy'ye giden yoldaki bir sorunu proxy'nin reddettiği bir tünelden ayırın ve proxy URL'sinde `http://` kullanın. Her isteğe bir zaman aşımı tuple'ı verin ve yalnız bağlantı hatalarını yeniden deneyin. Yeni bir kurulumu önce tek bir istekle deneyin ([proxy nasıl test edilir](/tr/blog/how-to-test-a-proxy)), seçenekleri de [proxy hizmetlerimiz](/tr/proxy) sayfasında karşılaştırın.
