CAPTCHA korumalı bir siteyi güvenilir şekilde kazımanın yolu, siteyi baştan zorlamak değildir: kazıyıcınızı normal çalıştırın, karşınıza bir doğrulama çıktığı anda türünü tanıyın, CaptchaAI API'ye gönderip dönen token'ı forma enjekte edin ve kaldığınız yerden devam edin. Bu yazı, reCAPTCHA'dan Cloudflare Turnstile'a en sık karşılaşılan korumaları bu akışla çözen, üretimde ayakta kalan bir kazıyıcının nasıl kurulacağını gösterir.
Pratikte akış her zaman aynı dört adımdan oluşur:
- Kazıyıcı sayfayı çeker ve yanıtta bir CAPTCHA işareti olup olmadığını kontrol eder.
- Varsa doğrulama türünü tanır ve gerekli parametreleri (sitekey, pageurl) çıkarır.
- Bu parametreleri CaptchaAI API'ye gönderir ve sonucu sorgulayarak token'ı alır.
- Token'ı forma enjekte eder, isteği tekrarlar ve kaldığı yerden devam eder.
E-ticaret fiyat takibi, pazar araştırması veya QA otomasyonu üzerinde çalışan bir geliştirici için bu, tek seferlik bir numara değil tekrarlanabilir bir iş akışı meselesidir. Aşağıdaki desenler, CAPTCHA'yı sayfa başına tek tek uğraştığınız bir engel olmaktan çıkarıp kazıma hattınızın sıradan bir adımına dönüştürür.
Karşılaşacağınız CAPTCHA türleri ve CaptchaAI yöntemleri
Bir siteyi kazımadan önce hangi doğrulama türüyle karşı karşıya olduğunuzu bilmek, doğru method değerini seçmenizi sağlar. En yaygın türler ve CaptchaAI API'de karşılık gelen yöntemler:
| CAPTCHA | Nerede karşınıza çıkar | CaptchaAI yöntemi |
|---|---|---|
| reCAPTCHA v2 | Giriş ve arama formları | method=userrecaptcha |
| reCAPTCHA v3 | Sayfa arka planında puanlama | method=userrecaptcha&version=v3 |
| Cloudflare Turnstile | Cloudflare arkasındaki siteler | method=turnstile |
| Cloudflare doğrulama akışı | Tam sayfa Cloudflare bloğu | method=cloudflare_challenge |
| Image/OCR CAPTCHA | Eski siteler, görsel kodlar | method=base64 |
| GeeTest v3 | Kaydırmalı/yapboz doğrulamalar | method=geetest |
| BLS CAPTCHA | BLS vize başvuru portalları | method=bls |
Strateji 1: CAPTCHA'yı yalnızca göründüğünde çözün
En güvenilir yaklaşım, siteyi normal şekilde kazımak ve doğrulamayı yalnızca gerçekten ortaya çıktığında çözmektir. Kazıyıcı her yanıtı kontrol eder; sayfada bir CAPTCHA işareti görürse çözüm akışını devreye alır, görmezse hiç API çağrısı yapmadan devam eder. Böylece hem gereksiz çözüm maliyetinden hem de fazladan gecikmeden kaçınırsınız.
Aşağıdaki ProtectedScraper sınıfı tam olarak bu mantığı uygular: yanıt HTML'inde g-recaptcha veya cf-turnstile işaretlerini arar, ilgili sitekey'i çıkarır, CaptchaAI'ye gönderir ve dönen token'ı forma ekleyerek isteği tekrarlar.
import requests
import time
from bs4 import BeautifulSoup
API_KEY = "YOUR_API_KEY"
class ProtectedScraper:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def scrape(self, url):
resp = self.session.get(url)
# Check for CAPTCHA
if self._has_captcha(resp.text):
resp = self._handle_captcha(resp.text, url)
return resp.text
def _has_captcha(self, html):
indicators = ["g-recaptcha", "cf-turnstile", "h-captcha", "captcha"]
return any(ind in html.lower() for ind in indicators)
def _handle_captcha(self, html, url):
soup = BeautifulSoup(html, "html.parser")
# reCAPTCHA v2
rc = soup.find("div", class_="g-recaptcha")
if rc:
token = self._solve_recaptcha(rc["data-sitekey"], url)
return self.session.post(url, data={"g-recaptcha-response": token})
# Cloudflare Turnstile
ts = soup.find("div", class_="cf-turnstile")
if ts:
token = self._solve_turnstile(ts["data-sitekey"], url)
return self.session.post(url, data={"cf-turnstile-response": token})
raise Exception("Unknown CAPTCHA type")
def _solve_recaptcha(self, site_key, page_url):
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": site_key, "pageurl": page_url
})
return self._poll(resp.text.split("|")[1])
def _solve_turnstile(self, site_key, page_url):
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY, "method": "turnstile",
"sitekey": site_key, "pageurl": page_url
})
return self._poll(resp.text.split("|")[1])
def _poll(self, task_id):
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id
})
if result.text == "CAPCHA_NOT_READY": continue
if result.text.startswith("OK|"): return result.text.split("|")[1]
raise Exception(result.text)
raise TimeoutError()
# Usage
scraper = ProtectedScraper()
html = scraper.scrape("https://example.com/data")
Çözüm süresi türe göre değişir: Cloudflare Turnstile genellikle 10 saniyenin altında, reCAPTCHA v2 ise 60 saniyenin altında yüksek başarı oranıyla çözülür. _poll döngüsü 5 saniyelik aralıklarla sonucu sorgular ve OK| yanıtı geldiğinde token'ı döndürür; bu yüzden ana kazıma döngünüzü bu bekleme süresine göre tasarlayın.
Strateji 2: CAPTCHA'sı bilinen sayfaları önceden çözün
Bazı sayfaların (örneğin belirli bir arama ya da giriş uç noktasının) her zaman CAPTCHA döndürdüğünü biliyorsanız, sayfayı hiç çekmeden token'ı çözüp isteği doğrudan token'la gönderebilirsiniz. Bu, fazladan bir GET isteğini atlar ve akışı kısaltır.
def scrape_known_captcha_page(url, site_key):
# Solve before even loading the page
token = solve_recaptcha(site_key, url)
# Submit directly with token
resp = requests.post(url, data={
"g-recaptcha-response": token,
"query": "search term"
})
return resp.text
Bu desen, sitekey'in sabit ve önceden bilindiği durumlarda idealdir. Sitekey sayfadan sayfaya değişiyorsa Strateji 1'deki dinamik çıkarma yöntemine geri dönün — aksi halde geçersiz bir sitekey ile boş token alırsınız.
Strateji 3: Cloudflare korumalı siteler
Cloudflare'in tam sayfa doğrulama akışı arkasındaki siteler, isteklerin geçerli sayılması için bir oturum çerezine (qa_session_cookie) ihtiyaç duyar. method=cloudflare_challenge ile bu akışı çözer, dönen çerezi ve User-Agent'ı sonraki tüm isteklerde aynen kullanırsınız.
def get_cloudflare_clearance(url, proxy):
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "cloudflare_challenge",
"pageurl": url,
"proxy": proxy,
"proxytype": "HTTP"
})
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id
})
if result.text == "CAPCHA_NOT_READY": continue
if "qa_session_cookie" in result.text:
# Parse qa_session_cookie and user_agent from response
return result.text
raise TimeoutError()
Kritik nokta: çözümden dönen çerez, onu üreten IP ve User-Agent ile eşleşmek zorundadır. Aynı proxy'yi ve aynı User-Agent'ı tüm oturum boyunca sabit tutmazsanız, site sizi yeniden doğrulama akışına sokar ve çerez bir işe yaramaz.
Birden çok sayfayı sırayla kazıma
Tek sayfalar yerine sayfalı (paginated) bir listeyi kazırken, her sayfa için aynı çözüm mantığını yeniden kullanır ve istekler arasına rastgele gecikmeler koyarsınız. Aşağıdaki desen, her sayfayı ProtectedScraper üzerinden geçirir, öğeleri toplar ve bir sayfa başarısız olsa bile tüm işi durdurmadan devam eder.
def scrape_multiple_pages(base_url, site_key, pages):
scraper = ProtectedScraper()
results = []
for page in pages:
url = f"{base_url}?page={page}"
try:
html = scraper.scrape(url)
soup = BeautifulSoup(html, "html.parser")
items = soup.find_all("div", class_="item")
results.extend([item.text.strip() for item in items])
print(f"Page {page}: {len(items)} items")
except Exception as e:
print(f"Page {page} failed: {e}")
time.sleep(random.uniform(2, 5))
return results
time.sleep(random.uniform(2, 5)) satırı, isteklerinizi daha insan temposuna yaklaştırarak sitenin sizi hız sınırına takmasını azaltır. Yüksek hacimli işlerde bu aralığı yukarı çekmek, CAPTCHA'nın her sayfada tetiklenme olasılığını da düşürür.
Thread planlaması ve maliyet
CaptchaAI, çözüm başına değil eşzamanlı thread başına ücretlendirir ve her planda thread başına sınırsız çözüm vardır. Kazıma hattınızın hızını belirleyen şey, kaç isteği aynı anda çözüme gönderdiğinizdir:
- Tek bir kazıyıcı ve düşük hacim için BASIC ($15/ay, 5 thread) çoğu zaman yeterlidir.
- Paralel çok sayfalı işler veya birden çok kazıyıcı çalıştırıyorsanız STANDARD ($30/ay, 15 thread) ya da ADVANCE ($90/ay, 50 thread) daha akıcı bir throughput sağlar.
Türkiye'deki geliştiriciler için öngörülebilir aylık USD fiyatlandırma, kur dalgalanmasından bağımsız bir maliyet planlaması demektir; çözüm başına sürpriz faturalar oluşmaz. Thread sayınızı, hedef CAPTCHA türünün çözüm süresine ve saatlik istek hacminize göre seçin.
KVKK ve yetkili kazıma
Türkiye'de kişisel veri içeren sayfaları kazırken KVKK (Kişisel Verilerin Korunması Kanunu) çerçevesi devreye girer: topladığınız veri kişisel veri niteliği taşıyorsa, işleme amacınızın ve hukuki dayanağınızın net olması gerekir. CaptchaAI'yi yalnızca yetkiniz olan işlerde — kendi sistemlerinizin QA testleri veya izinli veri toplama iş akışları kapsamında — kullanın.
Bir doğrulamayı teknik olarak çözebiliyor olmanız, o veriyi toplama hakkınız olduğu anlamına gelmez. Hedef sitenin kullanım şartlarını ve
robotspolitikalarını her zaman önce gözden geçirin.
Sorun giderme
| Sorun | Çözüm |
|---|---|
| Her sayfada CAPTCHA çıkıyor | İstek oranını düşürün ve proxy kullanın |
| Token çözümden sonra reddedildi | Token'ın süresi dolmuş olabilir; 120 saniye içinde kullanın |
| Cloudflare çerezine rağmen engelleniyor | Tüm isteklerde aynı proxy ve User-Agent'ı kullanın |
| Çözümden sonra farklı bir sayfa dönüyor | Ek yönlendirmeleri ve çerezleri kontrol edin |
Sık sorulan sorular
Kazıma sırasında CAPTCHA'yı çözmek ne kadar sürer ve nasıl ücretlendirilir?
Süre türe göre değişir: Cloudflare Turnstile genellikle 10 saniyenin altında, reCAPTCHA v2 ise 60 saniyenin altında çözülür. Ücretlendirme çözüm başına değil, eşzamanlı thread başınadır ve her planda thread başına sınırsız çözüm bulunur.
CaptchaAI hCaptcha'yı çözüyor mu?
Hayır. CaptchaAI şu anda hCaptcha ve FunCaptcha (Arkose Labs) çözmez. Desteklenen türler reCAPTCHA v2/v3, Cloudflare Turnstile ve doğrulama akışı, GeeTest v3, görsel/OCR, grid ve BLS'tir; CaptchaFox, Friendly Captcha ve Lemin ise beta aşamasındadır.
JavaScript ile oluşturulan sayfaları nasıl kazırım?
Sayfayı Selenium, Puppeteer veya Playwright ile render edin, ardından CAPTCHA parametrelerini (sitekey, pageurl) çıkarıp CaptchaAI ile çözün. Ayrıntılı akış için Selenium ile CAPTCHA çözümü rehberine bakın.
Kazıyıcım her sayfada CAPTCHA ile karşılaşıyorsa ne yapmalıyım?
Bu genellikle fazla agresif bir istek temposunun işaretidir. İstek aralığını artırın, oturumu tutarlı tutun ve isteklerinizi proxy'ler arasında dağıtın; çoğu durumda CAPTCHA sıklığı belirgin biçimde düşer.