---
title: "HTTPX, Requests ve AIOHTTP Karşılaştırması"
description: "Requests basit ve senkron, AIOHTTP asenkron, HTTPX ise ikisini de sunar. Proxy kullanımı, performans ve hangi projede hangisinin seçileceği kod örnekleriyle."
url: https://proxynet.io/tr/blog/httpx-vs-requests-vs-aiohttp
date: 2026-09-13
author: "Acar Diveroli"
category: "Karşılaştırma, Web Scraping"
lang: tr
---

# HTTPX, Requests ve AIOHTTP Karşılaştırması

Python'da HTTP isteği göndermek için üç kütüphane öne çıkar: **Requests**, **HTTPX** ve **AIOHTTP**. Üçü de aynı temel işi yapar, ama aralarındaki fark küçük bir betik yazarken değil, binlerce isteği aynı anda yönetmeniz gerektiğinde ortaya çıkar. Bu yazıda üç kütüphaneyi kullanım kolaylığı, eşzamanlılık, proxy desteği, hata yönetimi ve ekosistem açısından karşılaştırıyor, her biri için çalışan örnekler veriyor ve Requests'ten asenkrona geçişin yolunu gösteriyoruz.

Örneklerdeki kodlar Python 3.13 ile Requests 2.32, HTTPX 0.28 ve AIOHTTP 3.13 sürümlerinde denenmiştir.

> **Not: Kısa cevap**
>
> Küçük betikler ve API entegrasyonları için Requests; bugün senkron başlayıp yarın asenkrona geçme ihtimali olan projeler ve HTTP/2 için HTTPX; baştan asenkron tasarlanmış, çok yüksek hacimli işler için AIOHTTP. Üçü de HTTP proxy'yi yerleşik destekler.

## Kısaca üç kütüphane

- **Requests:** Python'un en yaygın HTTP kütüphanesi. Senkron çalışır, öğrenmesi çok kolaydır ve belgelerle örnekler her yerdedir. Her istek bitene kadar programın o satırda beklediğini unutmayın.
- **HTTPX:** Requests'e çok benzeyen bir arayüzü hem senkron hem asenkron olarak sunar. HTTP/2 desteği de vardır. Mevcut Requests kodunu asenkrona taşımanın en az zahmetli yolu genellikle HTTPX'tir.
- **AIOHTTP:** Baştan asenkron tasarlanmış bir kütüphane. İstemcinin yanında bir web sunucusu da içerir. Çok yüksek eşzamanlılık gereken işlerde olgun ve yaygın bir tercihtir.

## Senkron ve asenkron ne demek?

Karşılaştırmanın merkezindeki kavram bu olduğu için kısaca açıklayalım. **Senkron** bir istemci, isteği gönderir ve yanıt gelene kadar bekler; bu sırada program başka hiçbir şey yapmaz. **Asenkron** bir istemci ise isteği gönderdikten sonra kontrolü olay döngüsüne bırakır; yanıt beklenirken başka istekler yola çıkabilir.

Bir web isteğinin süresinin büyük kısmı ağda, yani hedef sunucunun yanıt vermesini beklerken geçer. Senkron kodda bu bekleme boşa gider; asenkron kodda aynı süre içinde onlarca başka istek beklenebilir. Fark, yüz sayfayı çekerken hissedilmez; on bin sayfayı çekerken saatler ile dakikalar arasındaki farka dönüşür.

Bu üstünlüğün bedeli karmaşıklıktır: `async`/`await` sözdizimi, olay döngüsü ve asenkron olmayan kütüphanelerle uyumsuzluk. Bu yüzden "asenkron her zaman daha iyi" demek yanlıştır; ihtiyaç yoksa senkron kod daha okunaklı ve bakımı daha kolaydır.

## Temel farklar tek tabloda

| Özellik | Requests | HTTPX | AIOHTTP |
|---|---|---|---|
| Senkron kullanım | Var | Var | Yok |
| Asenkron kullanım | Yok | Var | Var |
| HTTP/2 | Yok | Var (ek paketle) | Yok |
| Proxy (HTTP/HTTPS) | Yerleşik | Yerleşik | Yerleşik |
| SOCKS proxy | `requests[socks]` ile | `httpx[socks]` ile | Harici paketle |
| Varsayılan zaman aşımı | Yok (sonsuz bekler) | 5 saniye | 5 dakika (toplam) |
| Yönlendirmeleri izleme | Varsayılan açık | Varsayılan kapalı | Varsayılan açık |
| Bağlantı havuzu | `Session` ile | `Client` ile | `ClientSession` ile |
| Öğrenme eğrisi | Çok kolay | Kolay | Orta |
| En uygun iş | Basit betik, küçük hacim | Senkron + asenkron karışık projeler | Yüksek eşzamanlılık |

Tablodaki "varsayılan zaman aşımı" satırı, üç kütüphane arasındaki en sık gözden kaçan farktır. Requests'te zaman aşımı vermezseniz istek sonsuza kadar bekleyebilir; bu yüzden her Requests çağrısına `timeout=` eklemek bir alışkanlık olmalıdır. `ConnectTimeout` ile `ReadTimeout` farkını ve hata mesajında nasıl göründüklerini [Max Retries Exceeded With URL Hatası](/tr/blog/max-retries-exceeded-with-url) yazımızda gösterdik.

## Requests: basit ve senkron

Kurulum:

```bash
pip install requests
```

Proxy üzerinden tek bir istek:

```python
import requests

PROXY = "http://kullanici:parola@pr.proxynet.io:8000"
proxies = {"http": PROXY, "https": PROXY}

response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=20)
print(response.status_code, response.json())
```

`proxies` sözlüğündeki `https` anahtarı, HTTPS adreslere giderken kullanılacak proxy'dir. Değerin `http://` ile başlaması doğrudur: HTTPS trafiği proxy ile kurulan bağlantının içinde tünellenir.

Birden fazla istek atacaksanız `Session` kullanın; bağlantılar yeniden kullanılır, çerezler korunur ve proxy ayarı bir kez yapılır:

```python
import requests

PROXY = "http://kullanici:parola@pr.proxynet.io:8000"

with requests.Session() as session:
    session.proxies.update({"http": PROXY, "https": PROXY})
    session.headers.update({"User-Agent": "veri-toplama-botu/1.0"})
    for path in ["ip", "headers", "user-agent"]:
        r = session.get(f"https://httpbin.org/{path}", timeout=20)
        print(path, r.status_code)
```

Requests'in sınırı eşzamanlılıktır. 1.000 sayfayı sırayla çekerseniz toplam süre, her isteğin süresinin toplamına yaklaşır. Bunu `concurrent.futures.ThreadPoolExecutor` ile hafifletmek mümkündür, ancak çok yüksek hacimlerde asenkron bir kütüphane daha verimli çalışır. Buradaki örnekler yalnız GET isteği gönderiyor; JSON gövdeli POST isteklerinin, `params=` ile verilen sorgu parametrelerinin ve header'ların Requests'teki yazımını [Python Requests ile POST ve JSON: cURL Karşılıkları](/tr/blog/python-requests-post-json) yazısında anlattık.

## HTTPX: iki dünyanın arası

Kurulum:

```bash
pip install httpx
```

Senkron kullanım Requests'e neredeyse birebir benzer:

```python
import httpx

PROXY = "http://kullanici:parola@pr.proxynet.io:8000"

with httpx.Client(proxy=PROXY, timeout=20) as client:
    response = client.get("https://httpbin.org/ip")
    print(response.json())
```

> **Not**
>
> HTTPX 0.28 sürümünde eski `proxies=` parametresi kaldırıldı. Tek bir proxy için `proxy=` kullanın; farklı adresler için farklı proxy gerekiyorsa `mounts=` ile taşıyıcı tanımlayın. İnternetteki eski örnekler bu yüzden hata verebilir.

Aynı kodun asenkron hali, birden fazla isteği aynı anda gönderir:

```python
import asyncio
import httpx

PROXY = "http://kullanici:parola@pr.proxynet.io:8000"
URLS = ["https://httpbin.org/ip"] * 10

async def main():
    async with httpx.AsyncClient(proxy=PROXY, timeout=20) as client:
        responses = await asyncio.gather(*(client.get(url) for url in URLS))
        print([r.status_code for r in responses])

asyncio.run(main())
```

Burada 10 istek sırayla değil, aynı anda yola çıkar. Toplam süre en yavaş isteğin süresine yaklaşır.

HTTP/2 kullanmak için `pip install "httpx[http2]"` kurup istemciye `http2=True` geçmeniz yeterlidir. Aynı sunucuya çok sayıda istek atarken tek bağlantı üzerinden çoklama yapıldığı için bağlantı kurma maliyeti düşer. Proxy kullanırken HTTP/2, `CONNECT` tünelinin içinde sizin ile hedef site arasında çalışır; proxy'nin HTTP/2 desteklemesi gerekmez.

## AIOHTTP: yüksek eşzamanlılık için

Kurulum:

```bash
pip install aiohttp
```

```python
import asyncio
import aiohttp

PROXY = "http://pr.proxynet.io:8000"
AUTH = aiohttp.BasicAuth("kullanici", "parola")
URLS = ["https://httpbin.org/ip"] * 10

async def fetch(session, url):
    async with session.get(url, proxy=PROXY, proxy_auth=AUTH) as response:
        return response.status

async def main():
    async with aiohttp.ClientSession() as session:
        statuses = await asyncio.gather(*(fetch(session, url) for url in URLS))
        print(statuses)

asyncio.run(main())
```

AIOHTTP'de proxy, oturum yerine her istekte `proxy=` parametresiyle verilir. Kimlik bilgilerini `proxy_auth` ile ayrı geçebileceğiniz gibi adresin içine de (`http://kullanici:parola@...`) yazabilirsiniz. Her istekte farklı proxy vermek bu tasarımla doğal biçimde mümkündür; kendi IP listenizi döndürmek istiyorsanız AIOHTTP bunu kolaylaştırır.

AIOHTTP'nin bir başka farkı, yanıt gövdesinin bağlam yöneticisi içinde okunması gerektiğidir. `async with` bloğundan çıktıktan sonra `await response.text()` çağırmak hata verir; gövdeyi blok içinde okuyup değişkene alın.

## Eşzamanlılığı sınırlamak

Asenkron kullanırken eşzamanlılığı sınırsız bırakmayın. On bin URL'yi `asyncio.gather` ile tek seferde başlatmak hem kendi sisteminizin dosya tanıtıcı sınırını zorlar hem de hedef siteyi anında hız sınırına iter. `asyncio.Semaphore` ile aynı anda açık istek sayısını sınırlamak iki tarafı da korur:

```python
import asyncio
import httpx

PROXY = "http://kullanici:parola@pr.proxynet.io:8000"
URLS = [f"https://httpbin.org/get?i={i}" for i in range(100)]
LIMIT = asyncio.Semaphore(10)

async def fetch(client, url):
    async with LIMIT:
        r = await client.get(url)
        return r.status_code

async def main():
    async with httpx.AsyncClient(proxy=PROXY, timeout=20) as client:
        results = await asyncio.gather(*(fetch(client, u) for u in URLS))
        print(sum(1 for s in results if s == 200), "başarılı")

asyncio.run(main())
```

Bu örnekte yüz istek kuyruğa alınır, ancak aynı anda en fazla on tanesi açık olur. Sınırı hedef sitenin toleransına ve proxy paketinizin eşzamanlı bağlantı hakkına göre ayarlayın.

## Hata yönetimi ve yeniden deneme

Üç kütüphanede de ağ hataları istisna olarak gelir; ancak HTTP hata kodları (404, 429, 500) varsayılan olarak istisna **değildir**. Yanıtı kontrol etmek sizin işinizdir:

- Requests ve HTTPX'te `response.raise_for_status()` çağrısı 4xx ve 5xx yanıtlarda istisna fırlatır.
- AIOHTTP'de aynı iş `response.raise_for_status()` ile ya da oturum açılırken `raise_for_status=True` ile yapılır.

Proxy ile çalışırken en sık göreceğiniz kodlar şunlardır:

| Kod | Anlamı | Ne yapmalı? |
|---|---|---|
| 407 | Proxy kimlik doğrulaması başarısız | Kullanıcı adı, parola ve özel karakter kodlamasını kontrol edin |
| 429 | Hedef site hız sınırı uyguluyor | Eşzamanlılığı düşürün, bekleyip yeniden deneyin, IP dağıtımını artırın |
| 403 | Hedef site isteği reddediyor | User-Agent ve IP türünü gözden geçirin |
| 502 / 504 | Proxy hedefe ulaşamadı | Farklı bir çıkış IP'siyle yeniden deneyin |

Yeniden deneme mantığını üstel bekleme ile yazın: ilk denemede bir saniye, sonra iki, sonra dört. Sabit aralıklarla ısrar etmek 429 alan bir IP'nin tamamen engellenmesiyle sonuçlanabilir.

## Performans: hangisi daha hızlı?

Kütüphane seçiminde "hangisi daha hızlı" sorusu genellikle yanlış yere bakar. Bir web isteğinin süresinin büyük kısmı ağda geçer; kütüphanenin kendi işlem süresi bunun yanında küçüktür.

Belirleyici olan **aynı anda kaç isteği bekleyebildiğinizdir**:

- Senkron bir istemci her isteği sırayla bekler.
- Asenkron bir istemci yüzlerce isteği aynı anda bekleyebilir.

Yani 10 sayfalık bir iş için Requests yeterlidir. 10.000 sayfalık bir iş için HTTPX'in asenkron istemcisi veya AIOHTTP süreyi ciddi biçimde kısaltır. Aynı sınıf içinde (asenkron HTTPX ile AIOHTTP arasında) ölçülebilir farklar vardır ve AIOHTTP ham verimde genellikle önde gelir; ancak bu fark çoğu projede hedef sitenin yanıt süresinin ve proxy gecikmesinin gölgesinde kalır.

## Proxy ve eşzamanlılık birlikte nasıl düşünülmeli?

Asenkron kütüphaneler çok sayıda isteği aynı anda gönderebilir; ama bu isteklerin hepsi tek bir IP'den çıkıyorsa hedef site kısa sürede hız sınırı uygular. Eşzamanlılığı artırdıkça IP dağıtımını da düşünmeniz gerekir:

- **Her istekte farklı IP:** [Rotating Proxy](https://proxynet.io/tr/rotating-proxy) ile tek bir giriş adresi kullanıp her istekte farklı bir çıkış IP'si alırsınız. Kodunuzda değişiklik gerekmez; yukarıdaki örneklerin hepsi olduğu gibi çalışır.
- **Oturum boyunca aynı IP:** Giriş yapılan veya sepet gibi durum tutan akışlarda [Sticky Proxy](https://proxynet.io/tr/sticky-proxy) aynı IP'yi belirli bir süre korur.
- **Kendi listenizi döndürmek:** Elinizde sabit bir IP listesi varsa rotasyonu kodda yapabilirsiniz; adım adım örnek için [Python'da Proxy'ler Nasıl Döndürülür?](/tr/blog/rotating-proxy-python) yazımıza bakın.
- **IP türü:** Korumalı hedeflerde eşzamanlılıktan önce IP türü belirleyicidir; [Residential ve Datacenter Proxy Farkı](/tr/blog/residential-vs-datacenter-proxy) yazımızda nedenini anlattık.

## Requests'ten HTTPX'e geçiş

Mevcut bir Requests projesini asenkrona taşımak istiyorsanız HTTPX en kısa yoldur. Geçişte dikkat edilecek farklar:

| Requests | HTTPX | Not |
|---|---|---|
| `requests.get(url)` | `httpx.get(url)` | Aynı |
| `proxies={"http": p, "https": p}` | `proxy=p` | Tek parametre |
| `timeout=None` varsayılan | `timeout=5` varsayılan | HTTPX'te zaman aşımı açık gelir |
| Yönlendirme varsayılan izlenir | `follow_redirects=True` gerekir | HTTPX varsayılan izlemez |
| `Session()` | `Client()` / `AsyncClient()` | Aynı mantık |
| `response.json()` | `response.json()` | Aynı |

Kodun büyük bölümü değişmeden çalışır; farklar yukarıdaki beş satırda toplanır. Önce senkron `Client` ile geçip testleri çalıştırmak, sonra `AsyncClient`'a geçmek riski azaltır.

## Hangisini seçmelisiniz?

- **Requests** seçin: Küçük betikler, otomasyon görevleri, API entegrasyonları ve eşzamanlılığın önemli olmadığı işler için.
- **HTTPX** seçin: Bugün senkron başlayıp yarın asenkrona geçme ihtimaliniz varsa, HTTP/2 gerekiyorsa veya aynı projede iki kullanımı birlikte istiyorsanız.
- **AIOHTTP** seçin: Baştan asenkron tasarlanmış, çok yüksek hacimli veri toplama işleri ve aynı uygulamada hem istemci hem sunucu ihtiyacı için.

Sayfaları yalnızca HTTP ile çekmek yetmiyorsa, yani içerik JavaScript ile yükleniyorsa, bu kütüphaneler tek başına yeterli olmaz ve bir tarayıcı otomasyonuna ihtiyaç duyarsınız. Bu ayrımı [Web Kazıma: JavaScript mi Python mu?](/tr/blog/web-scraping-javascript-vs-python) yazımızda ele aldık. Python tarafındaki tarayıcı otomasyonu için [Selenium](/tr/blog/selenium) ve [SeleniumBase ile Proxy](/tr/blog/seleniumbase-ile-proxy) rehberlerimize bakabilirsiniz.

## Sık sorulan sorular

### Requests'ten HTTPX'e geçmek zor mu?

Genellikle hayır. `requests.get` yerine `httpx.get` yazmak çoğu basit kodda doğrudan çalışır. Farklar; zaman aşımının varsayılan olarak açık olması, yönlendirmelerin varsayılan olarak takip edilmemesi ve proxy parametresinin adı gibi ayrıntılardadır. Yukarıdaki geçiş tablosu bu farkları listeler.

### SOCKS5 proxy nasıl kullanılır?

Requests için `pip install "requests[socks]"`, HTTPX için `pip install "httpx[socks]"` kurun ve proxy adresinde `socks5://` şemasını kullanın. DNS çözümlemesinin de proxy tarafında yapılmasını istiyorsanız Requests'te `socks5h://` yazın. Protokoller arasındaki farklar için [SOCKS ve HTTP Proxy Farkı](/tr/blog/socks-vs-http-proxy) yazımıza bakabilirsiniz.

### Asenkron kod her zaman daha mı iyi?

Hayır. Asenkron kod daha karmaşıktır ve hataları ayıklamak daha zordur. Eşzamanlılıktan gerçekten fayda görmeyecek bir iş için senkron kod daha okunaklı ve bakımı daha kolaydır.

### Requests ile thread kullanmak asenkrona alternatif mi?

Orta hacimler için evet. `ThreadPoolExecutor` ile onlarca isteği paralel çalıştırmak mümkündür ve kod senkron kalır. Yüzlerce eşzamanlı istekte thread'lerin bellek maliyeti artar; o noktada asenkron istemci daha verimlidir.

### Proxy kimlik bilgilerini koda yazmak zorunda mıyım?

Hayır. Üç kütüphane de `HTTP_PROXY` ve `HTTPS_PROXY` ortam değişkenlerini okur (HTTPX'te `trust_env` varsayılan açıktır). Kimlik bilgilerini ortam değişkeninde tutmak, kodu depoya gönderirken sızıntı riskini azaltır.

### Aynı anda kaç istek açmalıyım?

Tek bir doğru sayı yoktur. Hedef sitenin toleransı, proxy paketinizin eşzamanlı bağlantı hakkı ve kendi makinenizin sınırları belirler. On ile başlayıp 429 yanıtı görmeden artırmak güvenli bir yöntemdir.

## Özetle

Üç kütüphane de işini iyi yapar; seçim projenin ölçeğine bağlıdır. Basit işler için Requests, esneklik ve geleceğe hazırlık için HTTPX, yüksek eşzamanlılık için AIOHTTP öne çıkar. Hangi kütüphaneyi seçerseniz seçin zaman aşımı verin, eşzamanlılığı sınırlayın ve yeniden denemeyi üstel bekleme ile yazın. Hacim arttıkça kütüphane kadar IP stratejisi de önem kazanır. Büyük ölçekli veri toplama altyapısı için [veri kazıma çözümlerimize](/tr/data-scraping) göz atabilirsiniz.
