Dua protokol mengontrol Chrome untuk otomatisasi: WebDriver (standar W3C, digunakan oleh Selenium) dan Chrome DevTools Protocol (CDP, digunakan oleh Puppeteer/Playwright). Masing-masing memiliki profil deteksi, kemampuan, dan karakteristik penanganan CAPTCHA yang berbeda.
Arsitektur Protokol
WebDriver (Selenium):
Script ──HTTP──▶ ChromeDriver ──DevTools──▶ Chrome
(JSON Wire) (bridge) (internal)
CDP (Puppeteer/Playwright):
Script ──WebSocket──▶ Chrome
(direct) (no middle layer)
Perbandingan Head-to-Head
| Fitur | WebDriver | CDP |
|---|---|---|
| Protokol | HTTP+JSON | Soket Web |
| Standar | standar W3C | Khusus Chrome |
| Permukaan deteksi | Tinggi (sinyal browser otomatis = true) |
Lebih rendah (dapat ditambal) |
| Intersepsi jaringan | Tidak (membutuhkan Selenium Wire) | Bawaan (Fetch, Network) |
| Evaluasi JavaScript | executeScript (dibungkus) |
Runtime.evaluate (langsung) |
| Minta modifikasi | Tidak | Ya |
| Modifikasi respons | Tidak | Ya |
| Overhead koneksi | HTTP per perintah | WebSocket yang persisten |
| ** Lintas-browser ** | Chrome, Firefox, Safari, Edge | Chrome/Chromium saja |
| Potensi standar | Rendah (selalu menyetel tanda webdriver) | Tinggi (bendera dapat ditambal) |
Perbedaan Deteksi
Deteksi WebDriver (Selenium)
// What sites check for Selenium
sinyal browser otomatis // true (set by ChromeDriver)
document.$cdc_asdjflasutopfhvcZLmcfl // ChromeDriver internal variable
window.callSelenium // Older Selenium versions
window._selenium // Selenium internals
document.__webdriver_evaluate // WebDriver namespace
# Even with flag removal, ChromeDriver leaves traces
from selenium import webdriver
options = webdriver.ChromeOptions()
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
Deteksi CDP (Puppeteer)
// 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
});
Pemecahan CAPTCHA: Pendekatan WebDriver
# 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()
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()
Pemecahan CAPTCHA: Pendekatan CDP
// Puppeteer (CDP) + CaptchaAI
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra (mode standar)");
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();
})();
Perbandingan Kemampuan untuk Alur Kerja CAPTCHA
Intersepsi Jaringan
# 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: 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 });
});
Modifikasi Respon
// 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 });
}
});
Manipulasi cookie
# WebDriver: Standard cookie API
driver.add_cookie({"name": "session", "value": "abc123"})
cookies = driver.get_cookies()
// 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");
Matriks Keputusan
| Skenario | Direkomendasikan | Mengapa |
|---|---|---|
| Pengujian multi-browser | WebDriver | Dukungan lintas browser |
| standar maksimal | CDP | Permukaan deteksi yang lebih rendah |
| Proses debug jaringan | CDP | Intersepsi bawaan |
| Tim tidak terbiasa dengan CDP | WebDriver | API yang lebih sederhana, lebih banyak dokumen |
| Scraping skala tinggi | CDP | Biaya overhead yang lebih rendah per sesi |
| Integrasi CI/CD | WebDriver | Dukungan perkakas yang lebih baik |
| Situs yang banyak CAPTCHA | CDP + CaptchaAI | Kombo standar + pecahkan |
| Pengisian formulir sederhana | WebDriver + CaptchaAI | Lebih mudah untuk diterapkan |
Pendekatan Hibrid: WebDriver + CDP
Selenium 4 mendukung perintah CDP melalui BiDi (dua arah):
from selenium import webdriver
driver = webdriver.Chrome()
# Use WebDriver for navigation
driver.get("https://example.com")
# Use CDP for konfigurasi standar
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
"""
})
# Use CDP for network events
driver.execute_cdp_cmd("Network.enable", {})
Tolok Ukur Kinerja
| Metrik | WebDriver (Selenium) | CDP (Puppeteer) | CDP (Playwright) |
|---|---|---|---|
| Sesi dimulai | ~2,5 detik | ~1,5 detik | ~1,2 detik |
| Navigasi halaman | ~500ms di atas kepala | ~100ms di atas kepala | ~80ms di atas kepala |
| Eksekusi skrip | ~200ms per panggilan | ~50ms per panggilan | ~40ms per panggilan |
| Memori per sesi | ~350 MB | ~280 MB | ~260 MB |
| Pemecahan CAPTCHA (CaptchaAI) | 15-30an | 15-30an | 15-30 detik |
Waktu penyelesaian CaptchaAI sama — ini merupakan panggilan API yang tidak bergantung pada protokol browser.
Pemecahan masalah
| Masalah | Perbaikan WebDriver | Perbaikan CDP |
|---|---|---|
| Terdeteksi sebagai bot | excludeSwitches + opsi |
konfigurasi standar + tambalan |
| Tidak dapat mencegat permintaan | Gunakan Selenium Wire | Gunakan Fetch.enable |
| Eksekusi lambat | Kurangi panggilan execute_script |
Perintah CDP batch |
| pengaturan token gagal | Periksa konteks iframe | Gunakan Runtime.evaluate dengan konteks |
| Ketidakstabilan sesi | Perbarui ChromeDriver | Periksa koneksi WebSocket |
Pertanyaan Umum
Protokol mana yang memberikan tingkat keberhasilan CAPTCHA lebih baik?
Tingkat keberhasilannya sama — CaptchaAI menyelesaikan masalah di sisi server. Protokol hanya mempengaruhi frekuensi deteksi (seberapa sering CAPTCHA muncul).
Bisakah saya menggabungkan WebDriver dan CDP?
Ya. Selenium 4 mengekspos execute_cdp_cmd(). Gunakan WebDriver untuk navigasi dan CDP untuk patch standar.
Apakah Playwright lebih baik dari keduanya?
Penulis naskah menggunakan CDP secara internal tetapi menyediakan API tingkat yang lebih tinggi dengan tunggu otomatis dan penanganan kesalahan yang lebih baik. Ini adalah jalan tengah yang bagus.
Haruskah saya beralih dari Selenium ke Puppeteer agar CAPTCHA berfungsi?
Jika deteksi adalah masalah utama Anda, ya. Jika Anda memerlukan dukungan lintas browser, tetap menggunakan Selenium + CaptchaAI.
Panduan Terkait
Pilih protokol otomatisasi yang tepat untuk alur kerja CAPTCHA Anda —dapatkan kunci CaptchaAI Andadan selesaikan CAPTCHA apa pun protokolnya.