Scraping altyapınızı kuruyorsunuz: TLS parmak izinizi JA4 ile Chrome 148'e eşlediniz, header sıralamanız doğru, hatta User-Agent bile güncel. Yine de ilk istek 403 dönüyor. Sorun HTML yüklemeden önce başlıyor — HTTP/2 SETTINGS frame'iniz sizi ele veriyor. HTTP/2 parmak izi açıklaması bu rehberin odak noktası: protokol seviyesindeki sinyallerin otomasyonu nasıl ifşa ettiğini, JA4H ve Akamai h2 fingerprint'in nasıl çalıştığını ve tutarlı bir tarayıcı parmak izinin residential proxy ile nasıl sunulacağını adım adım inceleyeceğiz.
HTTP/2 Parmak İzi Açıklaması: Temel Kavramlar
HTTP/2, RFC 9113 ile tanımlanan bir protokoldür ve istemci-sunucu iletişimini binary framing üzerinden yapar. Bağlantı kurulduğunda, istemci bir SETTINGS frame'i gönderir ve bu frame'in içeriği her istemci için farklıdır. Anti-bot sistemleri bu farkı kullanır.
HTTP/2 parmak izi, bağlantı öncesi el sıkışma (TLS) ile bağlantı sonrası protokol davranışını birleştirir. Bir istemcinin gerçek bir tarayıcı mı yoksa bir otomasyon aracı mı olduğunu belirlemek için aşağıdaki sinyaller kullanılır:
- SETTINGS frame değerleri: HEADER_TABLE_SIZE, ENABLE_PUSH, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, MAX_FRAME_SIZE, MAX_HEADER_LIST_SIZE
- WINDOW_UPDATE: Bağlantı seviyesinde ve stream seviyesinde gönderilen pencere güncellemeleri
- Stream priority: Weight ve dependency bilgileri
- Pseudo-header sırası:
:method,:authority,:scheme,:pathsırası (m,a,s,p) - Akamai h2 fingerprint string: Tüm bu değerleri tek bir compact string'de birleştirir
- JA4H: HTTP isteğinin metod, header listesi, cookie varlığı ve dil tercihinden üretilen hash
Akamai Compact H2 Fingerprint
Akamai, HTTP/2 SETTINGS frame değerlerini ve WINDOW_UPDATE artışlarını tek bir string'de kodlar. Bu string, Cloudflare ve diğer WAF sağlayıcıları tarafından da benzer şekillerde kullanılır. Format kabaca şu şekildedir:
SETTINGS:HEADER_TABLE_SIZE:ENABLE_PUSH:MAX_CONCURRENT_STREAMS:INITIAL_WINDOW_SIZE:MAX_FRAME_SIZE:MAX_HEADER_LIST_SIZE
WINDOW_UPDATE:connection_level_increment
PRIORITY:stream_tree_structure
Örneğin Chrome 148'in Akamai h2 fingerprint'i şu değerleri içerir: HEADER_TABLE_SIZE = 65536, INITIAL_WINDOW_SIZE = 6291456, MAX_CONCURRENT_STREAMS = 1000. Bu değerler her Chrome sürümünde küçük farklılıklar gösterebilir ancak temel yapı korunur.
JA4H Parmak İzi
JA4H, FoxIO tarafından geliştirilen JA4 ailesinin HTTP bileşenidir. JA4H, HTTP isteğinin aşağıdaki özelliklerini kodlar:
- HTTP metodu ve sürümü (örn.
ge= GET, HTTP/2) - Header sayısı, cookie varlığı, Accept-Language varlığı
- Sıralanmamış header isim listesi
- Belirli header değerlerinin hash'i
JA4H çıktısı şu formata sahiptir: ja4h_ge11cn13enus_000000000000_000000000000_. İlk bölüm HTTP sürümü ve metod, ikinci bölüm header sayısı ve özellikleri, üçüncü bölüm header isimleri hash'i, dördüncü bölüm değer hash'idir. JA4H, JA4 TLS parmak izi ile birlikte değerlendirilir ve ikisi arasında uyuşmazlık tespit edilirse bot skoru artırılır.
SETTINGS Frame: Hangi Değerler Ele Verir?
HTTP/2 SETTINGS frame'i, bağlantı kurulduktan hemen sonra gönderilir ve istemcinin protokol seviyesi tercihlerini bildirir. Anti-bot sistemleri bu değerleri bilinen tarayıcı profilleriyle karşılaştırır. Tek bir yanlış değer, bot skorunun maksimuma çıkmasına neden olur.
Aşağıdaki tablo yaygın istemcilerin SETTINGS değerlerini karşılaştırmaktadır:
| İstemci | HEADER_TABLE_SIZE | INITIAL_WINDOW_SIZE | MAX_CONCURRENT_STREAMS | Akamai Eşleşmesi |
|---|---|---|---|---|
| Chrome 148 | 65536 | 6291456 | 1000 | Evet |
| Firefox 133 | 65536 | 131072 | 1000 | Evet |
| Safari 18 | 65536 | 4194304 | 1000 | Evet |
| httpx (Python h2) | 4096 | 65535 | 100 | Hayır |
| Node.js http2 | 4096 | 65535 | 100 | Hayır |
| curl (libcurl) | 65536 | 2147483647 | 100 | Kısmi |
Tablodan da görüldüğü gibi, httpx ve Node.js http2 modülünün varsayılan değerleri hiçbir tarayıcıyla eşleşmiyor. HEADER_TABLE_SIZE = 4096 değeri, Python'un h2 kütüphanesinin varsayılanıdır ve hiçbir modern tarayıcı bu değeri kullanmaz. Bu, JA4 fingerprint'iniz Chrome 148'i gösterse bile, protokol seviyesinde anında tespit edilmenize neden olur.
Pseudo-Header Sırası (m,a,s,p)
HTTP/2'de pseudo-header'ların sırası tarayıcıya özgüdür. Chrome şu sırayı kullanır:
:method(m):authority(a):scheme(s):path(p)
Firefox ise :method, :path, :scheme, :authority sırasını kullanır. httpx ve birçok Python HTTP istemcisi, RFC 9113'ün önerdiği sırayı takip eder ancak bu sıra Chrome ile eşleşmez. Anti-bot sistemleri bu farkı bir kontrol noktası olarak kullanır.
Stream Priority ve WINDOW_UPDATE
Chrome, HTTP/2 bağlantısı kurulduktan sonra bağlantı seviyesinde bir WINDOW_UPDATE frame'i gönderir ve pencere boyutunu 15663105 byte artırır. Bu değer Chrome'a özgüdür ve Python h2 kütüphanesi farklı bir değer gönderir. Ayrıca Chrome, stream priority tree'sini belirli bir yapıda kurar: her stream belirli bir weight değerine ve parent dependency'e sahiptir. Bu yapı, tarayıcının kaynak yükleme önceliklerini yansıtır ve otomasyon araçları genellikle bu yapıyı taklit etmez.
JA4 Chrome 148 Ama HEADER_TABLE_SIZE 4096: Bot Skoru Maksimumu
En yaygın hata şudur: Geliştirici, curl_cffi veya benzeri bir kütüphane kullanarak JA4 fingerprint'ini Chrome 148'e eşler. TLS el sıkışması kusursuzdur — ALPN h2 içerir, cipher suite sırası Chrome ile birebir aynıdır, hatta TLS extension listesi bile eşleşir. Ancak bağlantı kurulduktan sonra gönderilen SETTINGS frame'inde HEADER_TABLE_SIZE = 4096 görünür.
Akamai ve benzeri sistemler bu uyuşmazlığı şu şekilde işler:
- TLS el sıkışmasını alır → JA4 = Chrome 148 profili
- HTTP/2 SETTINGS frame'ini alır → HEADER_TABLE_SIZE = 4096 (Python h2 varsayılanı)
- Profil uyuşmazlığını tespit eder → JA4 "Chrome 148" diyor ama h2 ayarları "httpx" diyor
- Bot skorunu maksimum seviyeye çıkarır
- İstek henüz HTML yüklemeden reddedilir
Bu senaryoda, User-Agent, Accept-Language ve diğer HTTP header'ları ne kadar doğru olursa olsun, istek reddedilir. Çünkü anti-bot sistemi iki farklı parmak izini karşılaştırır ve uyuşmazlık tespit eder. Bu, "protokol tutarlılığı" olarak adlandırılır ve modern WAF'lerin en güçlü savunma mekanizmalarından biridir. Sistem, tek bir SETTINGS değerinin bile yanlış olmasını bir bot işareti olarak değerlendirir.
TLS ve HTTP/2 Uyumu: JA3/JA4 ile H2'nin Anlaşması
TLS parmak izi (JA3 veya JA4) ile HTTP/2 parmak izi birbiriyle uyumlu olmalıdır. Eğer JA4 fingerprint'iniz "Chrome 148" diyorsa, HTTP/2 SETTINGS frame'iniz de Chrome 148'in değerlerini göndermelidir. Bu iki sinyal birbirini doğrular ve aralarındaki uyuşmazlık, herhangi bir header kontrolünden daha güçlü bir bot sinyalidir.
Sorun şu ki, birçok Python ve Node.js kütüphanesi bu uyumu bozar:
- httpx + h2: TLS parmak izini BoringSSL üzerinden Chrome'a eşleyebilir (örn.
curl_cffiile), ancak h2 SETTINGS frame'i hala Python h2 kütüphanesinin varsayılan değerlerini kullanır. Çünkü curl_cffi TLS katmanını taklit eder ama HTTP/2 framing'i libcurl'un kendi implementasyonuna bırakır. - Node.js undici: TLS parmak izi Node.js'in OpenSSL build'ine bağlıdır ve Chrome ile eşleşmez. HTTP/2 ayarları da Node.js http2 modülünün varsayılanlarıdır.
- Python requests: HTTP/2 desteği yoktur. Sadece HTTP/1.1 kullanır, bu da modern tarayıcılarla uyumsuzdur ve ALPN müzakeresinde
h2göndermemesi ayrı bir sinyaldir. - aiohttp: HTTP/2 desteği sınırlıdır ve varsayılan SETTINGS değerleri tarayıcılarla eşleşmez.
Bu uyuşmazlık, anti-bot sistemleri için bir kırmızı bayraktır. Gerçek bir Chrome kullanıcısının TLS el sıkışması Chrome'un BoringSSL build'inden gelir ve HTTP/2 SETTINGS frame'i Chrome'un net/http modülünden gelir. Bu iki sinyal doğal olarak uyumludur. Yapay olarak birini taklit edip diğerini taklit etmemek, otomasyonu ifşa eder.
HTTP/3 ve QUIC Parmak İzi
HTTP/3, QUIC protokolü üzerinden çalışır ve TLS 1.3 el sıkışması doğrudan QUIC paketlerinin içine gömülür. Bu, JA3/JA4 fingerprint'inin HTTP/3 için farklı bir şekilde hesaplanmasını gerektirir. Ayrıca, HTTP/3 SETTINGS frame'i de HTTP/2'den farklı değerler içerir.
Chrome 148'in HTTP/3 SETTINGS frame'i şu değerleri içerir: QPACK_MAX_TABLE_CAPACITY = 65536, MAX_FIELD_SECTION_SIZE = 262144. Bu değerler HTTP/2 SETTINGS ile uyumlu olmalıdır. Cloudflare, HTTP/3 parmak izini ayrı bir sinyal olarak değerlendirir ve HTTP/2 ile karşılaştırır.
Şu anda çoğu scraping aracı HTTP/3'ü desteklemez. Bu, HTTP/3 kullanan bir hedefe istek yaptığınızda otomatik olarak HTTP/2'ye fallback yapılması anlamına gelir. Bu fallback davranışı da bir parmak izi sinyalidir: gerçek bir Chrome kullanıcısı HTTP/3'ü destekler ve öncelikli olarak kullanır. Eğer hedef HTTP/3 duyuruyor ama istemciniz HTTP/2'ye geri düşüyorsa, bu bir otomasyon işaretidir.
Neden Residential Proxy Hala Gerekli
Protokol parmak izinizi mükemmel bir şekilde taklit ettiğinizi varsayalım: JA4 Chrome 148, HTTP/2 SETTINGS Chrome 148, pseudo-header sırası Chrome 148, WINDOW_UPDATE doğru. Yine de reddedilebilirsiniz. Çünkü protokol spoofing tek başına yeterli değildir — IP itibar puanlaması da devreye girer.
Anti-bot sistemleri aşağıdaki IP sinyallerini değerlendirir:
- ASN tipi: Datacenter IP'leri (AWS, GCP, Azure) otomatik olarak yüksek risk puanı alır. Residential IP'ler ise normal kullanıcı trafiği olarak değerlendirilir.
- Geçmiş davranış: Bir IP'den daha önce kaç istek geldi, bu istekler ne kadar şüpheliydi? Bir datacenter IP'si günde 10.000+ istek gönderiyorsa, bu otomatik olarak flag'lenir.
- Geo-tutarlılık: IP'nin coğrafi konumu ile Accept-Language header'ı uyumlu mu? Almanya IP'si ile
Accept-Language: en-USgöndermek bir uyuşmazlıktır. - Port tarama: 8080, 1080 gibi proxy portlarının açık olması, IP'nin bir proxy olarak işaretlenmesine neden olabilir.
Bu nedenle, protokol seviyesinde mükemmel bir taklit yapsanız bile, datacenter IP'leri kullanıyorsanız, anti-bot sistemi sizi yine de engelleyebilir. Residential proxy'ler, IP itibar puanını doğal olarak yükseltir ve protokol parmak izi ile birlikte tutarlı bir kullanıcı profili sunar. Mobile proxy'ler de iyi bir seçenektir ancak maliyet daha yüksektir.
ProxyHat ile Tutarlı Chrome H2 Parmak İzi
Şimdi, pratik bir uygulama örneğine geçelim. Amaç: Chrome ile tutarlı bir TLS + HTTP/2 parmak izi sunmak ve bunu ProxyHat residential proxy'leri üzerinden yönlendirmek.
Yöntem 1: curl_cffi ile Python
curl_cffi, libcurl'un BoringSSL fork'unu kullanarak Chrome'un TLS parmak izini taklit eder. HTTP/2 SETTINGS frame'i de libcurl'un yapılandırmasına bağlıdır. Doğru yapılandırma ile hem TLS hem de HTTP/2 parmak izi Chrome ile eşleşebilir.
from curl_cffi import requests
# ProxyHat residential proxy - ABD çıkışı
proxy_url = "http://user-country-US:pass@gate.proxyhat.com:8080"
# Chrome impersonation
response = requests.get(
"https://httpbin.org/headers",
impersonate="chrome124",
proxies={"https": proxy_url, "http": proxy_url},
timeout=30,
)
print(response.status_code)
print(response.json())
Bu örnekte impersonate="chrome124" parametresi, curl_cffi'nin TLS el sıkışmasını ve HTTP/2 SETTINGS frame'ini Chrome 124 profiliyle eşleştirir. ProxyHat residential proxy'si üzerinden çıkış yapılır, bu da IP itibar puanını doğal tutar. 30 saniyelik timeout, residential proxy'lerin datacenter proxy'lere göre biraz daha yüksek latency'sini telafi eder.
Yöntem 2: Playwright ile Gerçek Tarayıcı
Daha yüksek güvenilirlik için, gerçek bir Chromium tarayıcısı kullanmak en temel yaklaşımdır. Playwright, gerçek bir Chrome tarayıcısı başlattığı için TLS, HTTP/2 ve JavaScript parmak izi doğal olarak tutarlıdır.
from playwright.sync_api import sync_playwright
proxy_config = {
"server": "http://gate.proxyhat.com:8080",
"username": "user-country-US",
"password": "pass",
}
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy=proxy_config,
args=["--disable-blink-features=AutomationControlled"],
)
context = browser.new_context(
locale="en-US",
timezone="America/New_York",
)
page = context.new_page()
page.goto("https://httpbin.org/headers", timeout=30000)
content = page.content()
print(content)
browser.close()
Bu yöntemde, tarayıcı doğal olarak Chrome'un TLS ve HTTP/2 parmak izini üretir. ProxyHat residential proxy'si, IP seviyesinde tutarlı bir kullanıcı profili sunar. --disable-blink-features=AutomationControlled bayrağı, navigator.webdriver özelliğini gizler. locale="en-US" ve timezone="America/New_York" ayarları, ABD IP'si ile tutarlı bir coğrafi profil sunar.
Yöntem 3: SOCKS5 ile Daha Düşük Seviye
Bazı durumlarda SOCKS5 daha uygun olabilir, özellikle UDP trafiğini yönlendirmeniz gerektiğinde veya HTTP proxy'nin ek header eklemesinden kaçınmak istediğinizde:
from curl_cffi import requests
# ProxyHat SOCKS5 proxy
proxy_url = "socks5://user-country-US:pass@gate.proxyhat.com:1080"
response = requests.get(
"https://httpbin.org/headers",
impersonate="chrome124",
proxies={"https": proxy_url, "http": proxy_url},
timeout=30,
)
print(response.status_code)
Sticky Session ile Geo-Tutarlılık
Birden fazla istek gönderirken aynı IP'den çıkmak gerekiyorsa, ProxyHat'ın sticky session özelliğini kullanın:
from curl_cffi import requests
# Sticky session ile aynı IP'den çıkış
proxy_url = "http://user-session-mytask123-country-DE:pass@gate.proxyhat.com:8080"
response = requests.get(
"https://example.de/api/data",
impersonate="chrome124",
proxies={"https": proxy_url, "http": proxy_url},
timeout=30,
headers={"Accept-Language": "de-DE,de;q=0.9,en;q=0.8"},
)
print(response.status_code)
Bu örnekte user-session-mytask123 flag'i, aynı IP'den çıkış yapmanızı sağlar. country-DE flag'i ise trafiği Almanya residential IP'si üzerinden yönlendirir. Accept-Language: de-DE header'ı ile geo-tutarlılık sağlanır. Bu üç sinyal — IP lokasyonu, dil tercihi ve TLS/h2 parmak izi — birlikte tutarlı bir Alman Chrome kullanıcısı profili sunar.
Daha fazla lokasyon ve yapılandırma seçeneği için ProxyHat lokasyonlar sayfasını inceleyebilirsiniz. Fiyatlandırma detayları için ProxyHat fiyatlandırma sayfasına bakabilirsiniz.
Yaygın Hatalar ve Edge Case'ler
1. Sadece TLS'i Taklit Etmek
En yaygın hata, curl_cffi veya benzeri bir araç ile TLS parmak izini Chrome'a eşleyip HTTP/2 SETTINGS frame'ini varsayılan bırakmaktır. Bu, JA4 "Chrome" ama h2 "Python" uyuşmazlığına neden olur ve bot skorunu anında maksimuma çıkarır.
2. Pseudo-Header Sırasını Göz Ardı Etmek
Bazı HTTP/2 kütüphaneleri, pseudo-header'ları RFC sırasına göre gönderir ancak bu sıra Chrome ile eşleşmeyebilir. Header'ları manuel olarak sıralamak gerekebilir. Özellikle :authority ve :scheme'in sırası, Chrome ve Firefox arasında farklıdır.
3. Geo-Uyuşmazlık
ABD IP'si ile Accept-Language: tr-TR göndermek veya Türkiye IP'si ile Accept-Language: en-US göndermek, geo-uyuşmazlık olarak işaretlenir. IP lokasyonu ile dil tercihi tutarlı olmalıdır. Ayrıca timezone ve locale ayarları da IP ile uyumlu olmalıdır.
4. HTTP/2'ye Zorlamak
Bazı hedefler HTTP/3'ü destekler ve Chrome öncelikli olarak HTTP/3'ü kullanır. Eğer aracınız HTTP/3'ü desteklemiyorsa ve sadece HTTP/2'ye zorluyorsa, bu davranış bir parmak izi sinyalidir. Chrome, HTTP/3 duyurusu aldığında otomatik olarak QUIC'e geçer.
5. WINDOW_UPDATE Değerlerinin Yanlış Olması
Chrome, bağlantı kurulduktan sonra belirli bir WINDOW_UPDATE değeri gönderir. Bu değer 15663105 byte gibi spesifik bir sayıdır. Python h2 kütüphanesi farklı bir değer gönderebilir. Bu fark, anti-bot sistemleri tarafından tespit edilebilir.
6. Behavioral Fingerprinting
Protokol parmak izinin ötesinde, modern anti-bot sistemleri davranışsal analiz de yapar. Fare hareketleri, scroll hızı, tuş basış aralıkları ve JavaScript çalışma zamanı özellikleri (canvas fingerprint, WebGL renderer, AudioContext) gibi sinyaller de toplanır. Protokol seviyesinde mükemmel bir taklit yapsanız bile, JavaScript parmak izi tutarsızsa tespit edilirsiniz. Bu nedenle, gerçek tarayıcı kullanımı (Playwright/Puppeteer) çoğu durumda en güvenli yaklaşımdır.
Uygun Kullanım ve Yasal Çerçeve
Bu teknikleri kullanırken yasal sınırlara dikkat etmek kritiktir. Amerikan Bilgisayar Dolandırıcılığı ve Kötüye Kullanım Yasası (CFAA), yetkisiz erişimi suç sayar. Avrupa Birliği'nde GDPR, kişisel verilerin işlenmesine katı kurallar getirir. Türkiye'de KVKK benzer korumalar sağlar.
Uygun kullanım alanları:
- Yetkili güvenlik araştırması: Kendi sistemlerinizde veya izin verilmiş hedeflerde penetrasyon testi ve vulnerability scanning
- Rekabet intelligence'ı: Halka açık fiyat verilerinin toplanması (hedefin ToS'unu ihlal etmeden)
- SERP takibi ve SEO analizi
- Web scraping ile halka açık verilerin toplanması
- AI eğitim verisi toplama: Halka açık içeriklerin izinli olarak toplanması
Uygun olmayan kullanım alanları:
- Hedef sistemin ToS'unu ihlal etmek
- Rate limit'leri aşmak için agresif proxy rotasyonu yapmak (hedefe zarar vermek)
- Kişisel verileri izinsiz toplamak (GDPR/KVKK ihlali)
- Sahte hesap oluşturmak veya sahte trafik üretmek (click fraud)
- Kredi kartı veya ticket fraud yapmak
Her zaman robots.txt dosyasını kontrol edin ve hedefin ToS'unu okuyun. Şüphede kaldığınızda, hedefin API'sini kullanmayı tercih edin. Protokol parmak izi taklit teknikleri, yalnızca meşru araştırma ve izinli veri toplama için kullanılmalıdır.
Key Takeaways
HTTP/2 parmak izi açıklamasının temel noktaları:
- TLS (JA3/JA4) ve HTTP/2 SETTINGS frame'i birbiriyle uyumlu olmalıdır — tek bir uyuşmazlık bot skorunu maksimuma çıkarır.
- HEADER_TABLE_SIZE = 4096, hiçbir modern tarayıcının kullanmadığı bir değerdir ve Python h2 kütüphanesinin varsayanıdır.
- Akamai h2 fingerprint string'i, SETTINGS + WINDOW_UPDATE + priority değerlerini tek bir compact string'de birleştirir.
- JA4H, HTTP isteğinin metod, header ve dil tercihinden üretilen bir hash'tir ve JA4 TLS parmak izi ile birlikte değerlendirilir.
- Protokol spoofing tek başına yeterli değildir — residential proxy ile IP itibar puanı da yönetilmelidir.
curl_cffiveya gerçek bir tarayıcı + ProxyHat residential proxy, en tutarlı sonucu verir.- Geo-tutarlılık: IP lokasyonu, Accept-Language header'ı, timezone ve locale ayarları uyumlu olmalıdır.
- HTTP/3 desteklenmiyorsa, HTTP/2'ye fallback davranışı bile bir parmak izi sinyalidir.
ProxyHat hakkında daha fazla teknik detay için resmi dokümantasyonu inceleyebilirsiniz.






