Geliştirici Rehberleri5 dk okuma

Python ile proxy kullanımı: requests, httpx, SOCKS5 ve hatalar

Python’da proxy kullanmanın en kısa yolu requests’te proxies sözlüğü, httpx’te proxy argümanıdır. Güvenilir bir betik için bunlara zaman aşımı, yeniden deneme, ortam değişkenlerinin etkisi ve doğru hata yakalama eklenmelidir.

FİG. 01 — Komut satırı ve JSON yanıtı

Kısa cevap: requests.get(url, proxies={"http": PROXY, "https": PROXY}, timeout=(5, 20)) ya da httpx.Client(proxy=PROXY). Bu rehber, bu iki satırın arkasındaki ayrıntıları çalışır örneklerle açıyor: SOCKS5 ve uzak DNS, oturumlarda ortam değişkeni tuzağı, urllib3.Retry ile yeniden deneme, httpx’in değişen proxy API’si ve hataların ayırt edilmesi. Örneklerde yer tutucular KULLANICI, PAROLA, PROXY_ADRESI ve PORT; test adresi https://api.ipify.org?format=json. Farklı dillerde kısa bağlantı örnekleri için Geliştirici sayfasına bakabilirsiniz.

Kurulum

Kütüphaneler
python -m pip install "requests[socks]" "httpx[socks]"

requests[socks] SOCKS desteği için PySocks’u, httpx[socks] ise socksio’yu kurar. Yalnızca HTTP proxy kullanacaksanız ekler gerekmez.

requests ile ilk istek

HTTP proxy üzerinden istek
import requests

PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
proxies = {"http": PROXY, "https": PROXY}

r = requests.get(
    "https://api.ipify.org",
    params={"format": "json"},
    proxies=proxies,
    timeout=(5, 20),
)
r.raise_for_status()
print(r.json()["ip"])
  • Sözlüğün anahtarı hedefin şemasıdır, değeri proxy’nin adresidir. "https" anahtarına http:// ile başlayan bir proxy yazmak doğrudur: bu, HTTPS isteklerinin bir HTTP proxy üzerinden CONNECT tüneliyle gideceği anlamına gelir. Değeri https:// ile başlatmak, proxy’ye TLS ile bağlanmak demektir ve yalnızca proxy bunu destekliyorsa çalışır.
  • timeout her zaman verilmeli. requests’in varsayılan zaman aşımı yoktur; yanıt vermeyen bir proxy betiğinizi süresiz bekletebilir. (5, 20) bağlantı için 5, okuma için 20 saniye demektir.
  • Paroladaki özel karakterleri kodlayın. @, :, / gibi karakterler URL’yi bozar; urllib.parse.quote(parola, safe="") ile kodlayın.

SOCKS5 ve socks5h

SOCKS5 proxy, adı proxy çözer
import requests

PROXY = "socks5h://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
proxies = {"http": PROXY, "https": PROXY}

r = requests.get(
    "https://api.ipify.org",
    params={"format": "json"},
    proxies=proxies,
    timeout=(5, 20),
)
print(r.json())

requests belgelerine (yeni sekmede açılır) göre socks5:// şeması hedef adını istemcide çözer, socks5h:// ise çözümlemeyi proxy’ye bırakır. Yerel ağınızın çözümleyicisine sorgu gitmesini istemiyorsanız socks5h kullanın; nedenini DNS sızıntısı nedir? rehberi anlatıyor. HTTP mi SOCKS5 mi kararını henüz vermediyseniz HTTP & SOCKS5 Proxy sayfası iki protokolün hangi paketlerde seçilebildiğini gösterir.

Kimlik bilgilerini koddan ayırmak

Örneklerde okunabilirlik için proxy adresini doğrudan yazdık; gerçek bir projede kullanıcı adı ve parola kaynak koda girmemelidir. Değerleri ortam değişkeninden ya da bir gizli bilgi yöneticisinden okuyun ve URL’ye yerleştirmeden önce kodlayın. quote(…, safe="") parola içindeki @, : ve / gibi karakterleri URL’yi bozmayacak biçime çevirir; requests bu kodlamayı bağlanmadan önce geri çözer.

Proxy URL’sini ortam değişkenlerinden kurmak
import os
from urllib.parse import quote

import requests

user = quote(os.environ["PROXY_KULLANICI"], safe="")
password = quote(os.environ["PROXY_PAROLA"], safe="")
host = os.environ["PROXY_ADRESI"]
port = os.environ["PROXY_PORT"]

PROXY = f"http://{user}:{password}@{host}:{port}"
proxies = {"http": PROXY, "https": PROXY}

r = requests.get(
    "https://api.ipify.org",
    params={"format": "json"},
    proxies=proxies,
    timeout=(5, 20),
)
print(r.json()["ip"])

Session ve ortam değişkeni tuzağı

Çok sayıda istek yapacaksanız requests.Session bağlantıları yeniden kullanır ve her istekte yeni TCP ve TLS kurulumunu önler. Ancak belgelerde açıkça uyarıldığı gibi session.proxies ile verdiğiniz değerin üzerine ortam değişkenlerindeki proxy ayarları yazılabilir. İki güvenli yol vardır: proxy’yi her isteğe proxies= ile vermek ya da oturumda trust_env = False ayarlamak. İkincisi .netrc kimlik bilgilerini ve REQUESTS_CA_BUNDLE gibi ortam ayarlarını da devre dışı bırakır.

Yeniden deneme: urllib3 Retry

Session + HTTPAdapter + Retry
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
PROXIES = {"http": PROXY, "https": PROXY}

retry = Retry(
    total=3,
    connect=3,
    read=2,
    backoff_factor=0.5,
    status_forcelist=(429, 500, 502, 503, 504),
    allowed_methods=frozenset({"GET", "HEAD"}),
    respect_retry_after_header=True,
)
adapter = HTTPAdapter(max_retries=retry)

with requests.Session() as s:
    s.mount("http://", adapter)
    s.mount("https://", adapter)
    r = s.get(
        "https://api.ipify.org",
        params={"format": "json"},
        proxies=PROXIES,
        timeout=(5, 20),
    )
    print(r.status_code, r.json())

urllib3 Retry (yeni sekmede açılır) denemeler arasında artan aralıklarla bekler ve Retry-After başlığına uyar. Yalnızca güvenle tekrarlanabilen yöntemleri (GET, HEAD) yeniden deneyin. status_forcelist içindeki kodlarda denemeler tükenirse requests RetryError yükseltir. 407’yi listeye eklemeyin: hatalı kimlik bilgisini tekrar göndermek sonucu değiştirmez.

Hataları ayırt etmek

requests hata türleri
import requests
from requests.exceptions import (
    ConnectTimeout,
    ProxyError,
    ReadTimeout,
    RequestException,
    SSLError,
)

PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
proxies = {"http": PROXY, "https": PROXY}

try:
    r = requests.get(
        "https://api.ipify.org",
        params={"format": "json"},
        proxies=proxies,
        timeout=(5, 20),
    )
    r.raise_for_status()
    print("Çıkış IP adresi:", r.json()["ip"])
except ProxyError as exc:
    print("Proxy hatası:", exc)
except ConnectTimeout:
    print("Bağlantı zaman aşımına uğradı")
except ReadTimeout:
    print("Yanıt zaman aşımına uğradı")
except SSLError as exc:
    print("TLS hatası:", exc)
except RequestException as exc:
    print("Diğer istek hatası:", exc)
requests istisnaları ve olası nedenleri.
HataGenellikle ne anlama gelir?
ProxyErrorProxy’ye bağlanılamadı, bağlantı reddedildi ya da HTTPS tüneli kurulamadı (Tunnel connection failed: 407 kimlik doğrulama hatasıdır). urllib3, proxy’ye bağlanırken oluşan zaman aşımını da bu hatanın içinde sarabilir.
ConnectTimeoutTCP bağlantısı, bağlantı zaman aşımı içinde kurulamadı.
ReadTimeoutBağlantı kuruldu ama okuma zaman aşımı içinde veri gelmedi.
SSLErrorHedefle TLS el sıkışması başarısız oldu. Sertifikayı kendi sertifikasıyla değiştiren bir ara katman olabilir; verify=False ile susturmayın.
Yanıt kodu 407Düz HTTP hedeflerde istisna değil, yanıt olarak gelir; kimlik bilgilerini kontrol edin.
ConnectionErrorSOCKS tarafındaki hatalar (el sıkışma, doğrulama) çoğunlukla bu genel bağlantı hatası olarak görünür.

httpx: proxy= argümanı

httpx’in proxy API’si değişti: proxy= argümanı 0.26.0 sürümünde geldi, eski proxies= argümanı aynı sürümde kullanımdan kaldırıldı ve 0.28.0’da tamamen silindi. Eski örneklerdeki proxies= güncel sürümlerde hata verir. Farklı şemalar için farklı proxy gerekiyorsa mounts= ile taşıyıcı (transport) tanımlanır (httpx proxy belgeleri (yeni sekmede açılır)).

httpx, eşzamanlı istemci
import httpx

PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
timeout = httpx.Timeout(20.0, connect=5.0)

try:
    with httpx.Client(proxy=PROXY, timeout=timeout) as client:
        r = client.get("https://api.ipify.org", params={"format": "json"})
        r.raise_for_status()
        print(r.json()["ip"])
except httpx.ProxyError as exc:
    print("Proxy hatası:", exc)
except httpx.TimeoutException as exc:
    print("Zaman aşımı:", exc)
except httpx.HTTPError as exc:
    print("Diğer hata:", exc)
httpx, asenkron istemci
import asyncio

import httpx

PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"


async def main():
    async with httpx.AsyncClient(proxy=PROXY, timeout=20.0) as client:
        r = await client.get("https://api.ipify.org", params={"format": "json"})
        print(r.json())


asyncio.run(main())

requests’ten farklı olarak httpx’in varsayılan bir zaman aşımı vardır (5 saniye). SOCKS5 için httpx[socks] kurulur ve proxy="socks5://…" verilir; 0.28.0’dan itibaren socks5h:// şeması da kabul edilir. httpx’in yerleşik yeniden denemesi yalnızca bağlantı hatalarını kapsar: httpx.HTTPTransport(proxy=PROXY, retries=3) taşıyıcısını transport= ile verebilirsiniz.

Ortam değişkenleriyle yapılandırma

Linux / macOS kabuğu
export HTTP_PROXY="http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
export HTTPS_PROXY="http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
export NO_PROXY="localhost,127.0.0.1"
python betik.py

requests ve httpx bu değişkenleri (ve küçük harfli karşılıklarını) varsayılan olarak okur; ALL_PROXY de desteklenir. httpx’te proxy= açıkça verildiğinde o kullanılır. Ortam değişkenleri alt işlemlere de geçer; parola içeren bir değişkeni paylaşılan makinelerde dikkatle kullanın. Kimlik bilgisi saklama yöntemleri için Proxy kimlik doğrulama rehberine bakın.

Çıkış IP adresini doğrulamak

Doğrudan ve proxy üzerinden adresi karşılaştırmak
import requests

URL = "https://api.ipify.org"
PROXY = "http://KULLANICI:PAROLA@PROXY_ADRESI:PORT"
PROXIES = {"http": PROXY, "https": PROXY}

with requests.Session() as s:
    s.trust_env = False
    direct = s.get(URL, params={"format": "json"}, timeout=(5, 20)).json()["ip"]
    via_proxy = s.get(
        URL, params={"format": "json"}, proxies=PROXIES, timeout=(5, 20)
    ).json()["ip"]

print("Doğrudan:", direct)
print("Proxy ile:", via_proxy)
print("Proxy çıkışı farklı" if direct != via_proxy else "Uyarı: iki adres aynı")

trust_env = False, “doğrudan” isteğin gerçekten doğrudan gitmesini sağlar. İki adres aynı çıkıyorsa istek proxy’ye hiç uğramamıştır: sözlükte "https" anahtarının bulunduğunu, proxy URL’sinin şemayla başladığını ve NO_PROXY değişkeninin hedef adı kapsamadığını kontrol edin. Adres farklıysa ama beklediğiniz ülke ya da ağ türü değilse sorunu kodda değil, kullandığınız paketin özelliklerinde arayın. Bir liste dolusu proxy’yi tek tek denemek yerine Proxy Kontrol aracını kullanabilirsiniz.

Sık yapılan hatalar

  • Sözlükte yalnızca "http" anahtarı: requests proxy’yi hedefin şemasına göre seçer. "https" anahtarı yoksa HTTPS istekleri proxy’ye hiç uğramadan doğrudan gider ve çıkış adresiniz değişmez.
  • Şemasız proxy adresi: PROXY_ADRESI:PORT yerine http://PROXY_ADRESI:PORT yazın; requests belgeleri proxy URL’sinin şema içermesi gerektiğini belirtir.
  • verify=False ile TLS hatasını susturmak: Sertifika doğrulamasını kapatmak, araya giren herhangi bir sunucuya güvenmek demektir. Hatanın nedenini bulun; kurum içi bir ara katman varsa onun kök sertifikasını verify= ile gösterin.
  • Zaman aşımı vermemek: Tek bir yanıt vermeyen proxy, iş parçacığını veya bütün betiği kilitleyebilir.
  • socks5 yazıp DNS’in yerelde çözüldüğünü fark etmemek: Hedef adının proxy’de çözülmesini istiyorsanız socks5h kullanın.
  • session.proxies ile ortam değişkenlerini birlikte kullanmak: Hangi proxy’nin kullanıldığı belirsizleşir; proxy’yi her isteğe verin ya da trust_env = False ayarlayın.

Özet: requests mi, httpx mi?

İki kütüphanenin proxy ile ilgili farkları.
İhtiyaçrequestshttpx
HTTP proxyproxies={"http": P, "https": P}proxy=P
SOCKS5requests[socks], socks5h://httpx[socks], socks5:// veya socks5h://
Zaman aşımıtimeout=(5, 20); varsayılan yokhttpx.Timeout(…); varsayılan 5 sn
Yeniden denemeHTTPAdapter + urllib3 RetryHTTPTransport(retries=…), yalnızca bağlantı hataları
Ortam değişkenleriOkunur (trust_env)Okunur (trust_env)
AsenkronYokAsyncClient

Sık sorulanlar

Akılda kalan sorular

02Okumaya devam

Devamını okuyun

03Konuyla bağlantılı

Ürünler ve araçlar

Ürün sayfaları paketleri ve fiyatları gösterir; araçlar ise elinizdeki bir proxy’yi ya da adresi sınamanız içindir.

Ürünler

Araçlar

  • Proxy Kontrol

    HTTP, HTTPS ve SOCKS5 proxy listelerini canlılık, gecikme ve çıkış IP’si açısından test edin.

  • HTTP Proxy Kontrol

    HTTP proxy’nizin düz istekleri ve HTTPS tünelini (CONNECT) doğru taşıyıp taşımadığını ölçün.

  • SOCKS5 Kontrol

    SOCKS5 el sıkışmasını, kullanıcı adı / parola doğrulamasını ve çıkış adresini sınayın.