"Selenium'dan Puppeteer'a geçersek CAPTCHA derdimiz biter mi?" Hayır. Çözüm tarayıcıda değil, sunucu tarafında CaptchaAI API'sinde yapılır. Protokol seçimi yalnızca üç şeyi belirler: doğrulamanın ne sıklıkta çıkacağı, ağ katmanına erişiminiz ve geçişin maliyeti. WebDriver ile CDP'yi (Puppeteer, Playwright) bu eksenlerde karşılaştıralım.
Mimari fark: arada bir köprü var mı?
WebDriver komutları ayrı bir ChromeDriver sürecinden geçer; CDP doğrudan tarayıcıya bağlanır.
WebDriver (Selenium):
Script ──HTTP──▶ ChromeDriver ──DevTools──▶ Chrome
(JSON Wire) (bridge) (internal)
CDP (Puppeteer/Playwright):
Script ──WebSocket──▶ Chrome
(direct) (no middle layer)
Köprü her komutu bir HTTP turuna çevirir. Fark tek sayfalık testte ölçülmez, yüzlerce sayfalık koşuda süreye ve belleğe yansır.
Algılama yüzeyi: CAPTCHA neden Selenium'da daha sık çıkıyor?
CAPTCHA, tarayıcınız otomasyon olarak sınıflandırıldığında devreye girer.
ChromeDriver'ın geride bıraktığı izler
Siteler şu işaretlere bakar:
// What sites check for Selenium
navigator.userAgent // true (set by ChromeDriver)
document.$cdc_asdjflasutopfhvcZLmcfl // ChromeDriver internal variable
window.callSelenium // Older Selenium versions
window._selenium // Selenium internals
document.__webdriver_evaluate // WebDriver namespace
Bilinen bayrakları kapatsanız bile ChromeDriver iç değişkenlerini sayfaya bırakır:
# Even with flag removal, ChromeDriver leaves traces
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
driver = webdriver.Chrome(options=options)
# Still detectable via $cdc variables in document
Puppeteer tarafında tablo neden farklı
Puppeteer da bu bayrağı ayarlar, ama sayfa yüklenmeden düzeltilebilir ve $cdc izi kalmaz:
// Puppeteer sets webdriver flag too, but it's fully patchable
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
});
// No $cdc variables to worry about
// No Selenium-specific traces
});
Sonuç: CDP'de doğrulama daha seyrek çıkar; çıktığında çözüm iki tarafta da aynıdır.
WebDriver ve CDP: teknik farklar tablosu
| Özellik | WebDriver | CDP |
|---|---|---|
| Protokol | HTTP + JSON | WebSocket |
| Algılama yüzeyi | Yüksek (navigator.webdriver) |
Düşük (düzeltilebilir) |
| Ağa müdahale | Selenium Wire gerekir | Dahili (Fetch, Network) |
| Çapraz tarayıcı | Chrome, Firefox, Safari, Edge | Chrome/Chromium |
Tek kayıp satır sonuncusu: Firefox ve Safari gerekiyorsa CDP yetmez.
Selenium ile token akışı: sitekey'den forma
Akış iki protokolde de aynı üç adım: sitekey çıkarın, görevi CaptchaAI'ye gönderin, dönen token'ı g-recaptcha-response alanına yazın.
# Selenium (WebDriver) + CaptchaAI
import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
API_KEY = "YOUR_API_KEY"
API_URL = "https://ocr.captchaai.com"
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com/form")
time.sleep(2)
# Extract sitekey
sitekey = driver.execute_script(
"return document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')"
)
# Solve via CaptchaAI
resp = requests.post(f"{API_URL}/in.php", data={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": driver.current_url, "json": 1,
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{API_URL}/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
})
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
break
token = data["request"]
# Inject token
driver.execute_script(f"""
document.querySelector('#g-recaptcha-response').value = '{token}';
document.querySelectorAll('[name="g-recaptcha-response"]')
.forEach(el => {{ el.value = '{token}'; }});
""")
driver.find_element(By.CSS_SELECTOR, "form").submit()
driver.quit()
Göndermeden önce alanın dolduğunu doğrulayın; yanlış iframe seçimi hata vermeden boş alan bırakır.
Puppeteer ile token akışı: enjeksiyonu alt katmandan yapmak
Aynı üç adımı Runtime.evaluate ile daha alt seviyeden yazarsınız; ağ olaylarını da aynı oturumda dinlersiniz — bu, sorun gidermeyi kısaltır.
// Puppeteer (CDP) + CaptchaAI
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
const https = require("https");
puppeteer.use(StealthPlugin());
const API_KEY = "YOUR_API_KEY";
const API_URL = "https://ocr.captchaai.com";
function solveCaptcha(siteUrl, sitekey) {
// Submit + poll (simplified)
return new Promise(async (resolve, reject) => {
const submitResp = await httpPost(`${API_URL}/in.php`, {
key: API_KEY, method: "userrecaptcha",
googlekey: sitekey, pageurl: siteUrl, json: "1",
});
const taskId = submitResp.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await httpGet(
`${API_URL}/res.php?key=${API_KEY}&action=get&id=${taskId}&json=1`
);
if (result.request !== "CAPCHA_NOT_READY") {
return resolve(result.request);
}
}
reject(new Error("Timeout"));
});
}
(async () => {
const browser = await puppeteer.launch({
headless: "new",
args: ["--no-sandbox", "--window-size=1920,1080"],
});
const page = await browser.newPage();
// CDP: Enable network interception
const cdp = await page.createCDPSession();
await cdp.send("Network.enable");
// Monitor CAPTCHA-related requests
cdp.on("Network.requestWillBeSent", (params) => {
if (params.request.url.includes("recaptcha")) {
console.log(`CAPTCHA request: ${params.request.url}`);
}
});
await page.goto("https://example.com/form", { waitUntil: "networkidle0" });
const sitekey = await page.evaluate(() =>
document.querySelector("[data-sitekey]")?.getAttribute("data-sitekey")
);
if (sitekey) {
const token = await solveCaptcha(page.url(), sitekey);
// CDP: Inject via Runtime.evaluate (lower-level than page.evaluate)
await cdp.send("Runtime.evaluate", {
expression: `
document.querySelector('#g-recaptcha-response').value = '${token}';
document.querySelector('form').submit();
`,
});
}
await browser.close();
})();
Cloudflare Turnstile'da token alanı cf-turnstile-response olur; gönder–sorgula deseni GeeTest v3'te de aynıdır.
Yalnızca CDP'de olan yetenekler
İsteklere müdahale
WebDriver'da yerleşik müdahale API'si yok; Selenium Wire trafiği yerel proxy'den geçirir:
# WebDriver: Cannot intercept requests natively
# Requires selenium-wire (third-party)
from seleniumwire import webdriver
driver = webdriver.Chrome()
# selenium-wire proxies all traffic through a local proxy
CDP'de bu yetenek yerleşiktir:
// CDP: Built-in request interception
await cdp.send("Fetch.enable", {
patterns: [{ urlPattern: "*recaptcha*" }],
});
cdp.on("Fetch.requestPaused", async ({ requestId, request }) => {
console.log(`Intercepted: ${request.url}`);
await cdp.send("Fetch.continueRequest", { requestId });
});
Yanıtı değiştirme
Yapılandırma yanıtını test ortamında değiştirmek yalnızca CDP'de mümkündür:
// CDP: Can modify responses (WebDriver cannot)
cdp.on("Fetch.requestPaused", async ({ requestId, request }) => {
if (request.url.includes("captcha-config")) {
// Return modified response
await cdp.send("Fetch.fulfillRequest", {
requestId,
responseCode: 200,
body: btoa(JSON.stringify({ enabled: false })),
});
} else {
await cdp.send("Fetch.continueRequest", { requestId });
}
});
httpOnly çerezlere erişim
WebDriver standart çerez API'sini sunar:
# WebDriver: Standard cookie API
driver.add_cookie({"name": "session", "value": "abc123"})
cookies = driver.get_cookies()
CDP httpOnly çerezleri de okur; WebDriver okuyamaz:
// CDP: Full cookie control including httpOnly
await cdp.send("Network.setCookie", {
name: "session",
value: "abc123",
domain: "example.com",
httpOnly: true,
secure: true,
});
// Get all cookies including httpOnly (WebDriver can't access these)
const { cookies } = await cdp.send("Network.getAllCookies");
Hibrit yol: Selenium 4 içinden CDP komutları
Seçmek zorunda değilsiniz: Selenium 4 CDP komutlarını doğrudan çalıştırır. Gezinme WebDriver'da kalır, alt seviye çağrılar CDP'ye gider:
from selenium import webdriver
driver = webdriver.Chrome()
# Use WebDriver for navigation
driver.get("https://example.com")
# Use CDP for QA testi patches
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
"""
})
# Use CDP for network events
driver.execute_cdp_cmd("Network.enable", {})
Mevcut test paketini yeniden yazmadan CDP'ye kademeli geçmenin en düşük riskli yolu budur.
Performans: sayılar nerede fark ediyor?
Aşağıdaki değerler gözlemlenen verilere ve kullanıcı raporlarına dayanır. Sonuçlar ortama, hacme ve zamana göre değişebilir.
| Metrik | WebDriver | CDP (Puppeteer/Playwright) |
|---|---|---|
| Oturum başlangıcı | ~2,5 sn | ~1,2–1,5 sn |
| Script çalıştırma | ~200 ms | ~40–50 ms |
| Oturum belleği | ~350 MB | ~260–280 MB |
| CAPTCHA çözümü | 15–30 sn | 15–30 sn |
En önemli satır sonuncusu: çözüm süresi protokolden bağımsızdır; üstteki milisaniyeler ancak oturum sayısıyla çarpılınca anlam kazanır.
Hangi iş yükü hangi protokole gider?
| Senaryo | Önerilen | Neden |
|---|---|---|
| Firefox ve Safari testi | WebDriver | Çapraz tarayıcı |
| Yüksek hacimli web kazıma | CDP | Düşük ek yük |
| Mevcut CI/CD hattı | WebDriver | Olgun ekosistem |
| CAPTCHA'nın sık çıktığı siteler | CDP + CaptchaAI | Az iz + API çözümü |
Bu kolon kural değil, tartışmanın başlangıç noktasıdır.
İstanbul'dan bir örnek: gece koşan QA hattı
Bir entegratör ekibi ödeme adımını her gece 200 kez test ediyor; reCAPTCHA v2 açık, koşu Europe/Istanbul saatiyle 02.00'de başlıyor. Ekip zaten Selenium'da: 200 oturum × 2,5 sn ≈ 8 dakika ek yük, 40 dakikalık koşuda kararı çevirmez. Asıl CDP'ye taşınacak iş, gündüz koşan 50.000 sayfalık katalog senkronizasyonu.
Fiyatlar USD ve thread tabanlı; kur oynaklığının bütçeyi bozmaması Türkiye'deki ekipler için avantaj. Gece koşusuna BASIC ($15/ay, 5 thread), kataloğa ADVANCE ($90/ay, 50 thread) uyar. Kişisel veri toplanıyorsa iş KVKK kapsamına girer.
Sorun giderme
| Sorun | WebDriver çözümü | CDP çözümü |
|---|---|---|
| Bot olarak algılandı | excludeSwitches ayarları |
Test profilini sadeleştirin |
| Token enjeksiyonu başarısız | iframe bağlamını kontrol edin | Doğru bağlamla Runtime.evaluate |
| Token reddedildi | 60 saniye içinde gönderin | Aynı kural |
Sık sorulan sorular
Firefox ve Safari testlerim varsa CDP bir seçenek mi?
Hayır, CDP yalnızca Chrome ve Chromium tabanlı tarayıcılarda çalışır. Çapraz tarayıcı matrisiniz varsa WebDriver'da kalın.
Eşzamanlılığı çözüm sayısı mı, thread sayısı mı belirler?
Thread sayısı. BASIC ($15/ay, 5 thread) aynı anda 5, ADVANCE ($90/ay, 50 thread) aynı anda 50 CAPTCHA demektir.
CaptchaAI hangi CAPTCHA türlerini destekliyor?
reCAPTCHA v2 ve v3, Cloudflare Turnstile, Cloudflare doğrulama akışı, GeeTest v3, görüntü/OCR ve metin tabanlı CAPTCHA'lar; CaptchaFox (beta), Friendly Captcha (beta) ve Lemin (beta). hCaptcha ve FunCaptcha desteklenmiyor, GeeTest v4 için "çok yakında" geçerli.
İlgili rehberler
CaptchaAI API anahtarınızı alın, örneği kopyalayın, ilk token'ınızı bugün üretin.