Tutorials

Python Selenium + CaptchaAI Tam Entegrasyon Kılavuzu

JavaScript ile render edilen bir sayfayı otomatikleştirirken CAPTCHA'ya takıldıysanız çözüm dört adımdan ibarettir: sayfadaki CAPTCHA türünü tespit edin, CaptchaAI API'sine gönderip token'ı alın, token'ı JavaScript ile sayfaya enjekte edin ve formu gönderin. Selenium tarayıcıyı sürerken CaptchaAI çözümü kendi tarafında hallettiği için ikisini birleştirmek reCAPTCHA v2/v3, Cloudflare Turnstile ve klasik resim CAPTCHA'larını tek bir iş akışında toplar.

Senaryo çoğu geliştiriciye tanıdık gelir: bir e-ticaret ödeme adımını ya da üyelik formunu QA amacıyla otomatikleştiriyorsunuz, ama giriş sayfası hem JavaScript render'ı hem de bir CAPTCHA istiyor. Bionluk veya Upwork üzerinden teslim tarihli otomasyon işi yürütenler için en çok zaman kaybettiren nokta tam da burasıdır. CaptchaAI thread tabanlı ve USD üzerinden faturalandığından — örneğin BASIC ($15/ay, 5 thread) — TL kurundaki oynaklıktan bağımsız, öngörülebilir bir maliyetle çalışırsınız.

Akışı, türden bağımsız olarak dört adıma indirgeyebilirsiniz:

  • Tespit — sayfa kaynağından CAPTCHA türünü ve sitekey değerini okuyun.
  • Çözüm — görevi CaptchaAI API'sine gönderip token'ı alın.
  • Enjeksiyon — token'ı JavaScript ile gizli alana yazın.
  • Gönderim — formu gönderin ve yönlendirmeyi doğrulayın.

Gerekli paketler

pip install selenium requests webdriver-manager

Üç paket üç ayrı işi üstlenir:

  • selenium — tarayıcıyı programatik olarak sürer.
  • requests — CaptchaAI API'sine HTTP çağrısı yapar.
  • webdriver-manager — doğru sürücü ikilisini sizin yerinize indirir.

Selenium sürücüsünü hazırlama

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

def create_driver():
    """Create a Selenium driver with QA testi-configuredion settings."""
    options = webdriver.ChromeOptions()
    options.add_argument("--no-sandbox")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option("useAutomationExtension", False)

    driver = webdriver.Chrome(
        service=Service(ChromeDriverManager().install()),
        options=options,
    )

    # Remove webdriver flag
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
    })

    return driver

ChromeDriverManager doğru sürücü ikilisini otomatik indirir, böylece sürüm uyumsuzluğuyla uğraşmazsınız. --no-sandbox bayrağı CI konteynerlerinde tarayıcıyı sorunsuz başlatmak için gereklidir; bu standart yapılandırma, QA test akışınızın kararlı çalışmasını sağlar.


Tekrar kullanılabilir CaptchaAI çözüm fonksiyonu

Tek bir yardımcı fonksiyon her CAPTCHA türü için kullanılabilir: görevi in.php uç noktasına gönderir, sonucu res.php üzerinden periyodik olarak sorgular ve token'ı döndürür.

import time
import requests

API_KEY = "YOUR_API_KEY"

def solve_captcha(method, **params):
    """Generic CaptchaAI solver — works for all supported CAPTCHA types."""
    submit_data = {
        "key": API_KEY,
        "method": method,
        "json": 1,
        **params,
    }

    submit = requests.post("https://ocr.captchaai.com/in.php", data=submit_data, timeout=30)
    data = submit.json()

    if data.get("status") != 1:
        raise Exception(f"Submit error: {data.get('request')}")

    task_id = data["request"]

    for _ in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }, timeout=30).json()

        if result.get("status") == 1:
            return result["request"]
        if result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
            raise Exception("CAPTCHA unsolvable")

    raise TimeoutError("Solve timed out")

Selenium ile reCAPTCHA v2 çözme

Dört adım: sitekey'i bulun, çözün, token'ı enjekte edin, formu gönderin

Akışın özü sayfa kaynağından data-sitekey değerini çıkarmak, CaptchaAI'ye göndermek ve dönen token'ı gizli g-recaptcha-response alanına yazmaktır. Somut olarak dört işlem yaparsınız:

  • data-sitekey özniteliğini regex ile yakalayın.
  • userrecaptcha methoduyla CaptchaAI'ye gönderin.
  • Dönen token'ı g-recaptcha-response alanına yazın.
  • Varsa ___grecaptcha_cfg callback'ini tetikleyin.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import re

def solve_recaptcha_v2_selenium(driver, url):
    """Complete reCAPTCHA v2 solve in Selenium."""
    driver.get(url)

    # Wait for page to load
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, "body"))
    )

    # Extract sitekey
    page_source = driver.page_source
    match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', page_source)
    if not match:
        raise ValueError("reCAPTCHA sitekey not found")
    sitekey = match.group(1)
    print(f"Sitekey: {sitekey}")

    # Solve via CaptchaAI
    token = solve_captcha(
        "userrecaptcha",
        googlekey=sitekey,
        pageurl=url,
    )
    print(f"Token received: {token[:50]}...")

    # Inject token into the page
    driver.execute_script(f"""
        document.getElementById('g-recaptcha-response').value = '{token}';
        document.getElementById('g-recaptcha-response').style.display = 'block';
    """)

    # If there's a callback function, call it
    driver.execute_script(f"""
        if (typeof ___grecaptcha_cfg !== 'undefined') {{
            var clients = ___grecaptcha_cfg.clients;
            for (var key in clients) {{
                var client = clients[key];
                if (client.rr && client.rr.l) {{
                    client.rr.l.callback('{token}');
                }}
            }}
        }}
    """)

    # Submit the form
    submit_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit'], input[type='submit']")
    submit_button.click()

    return token

# Usage
driver = create_driver()
try:
    solve_recaptcha_v2_selenium(driver, "https://staging.example.com/qa-login")
    print(f"Current URL: {driver.current_url}")
finally:
    driver.quit()

Birçok form yalnızca token'ı yazmakla yetinmez; ayrıca callback fonksiyonunun çağrılmasını bekler. Yukarıdaki ___grecaptcha_cfg bloğu bunu üstlenir.


Selenium ile Cloudflare Turnstile çözme

reCAPTCHA v2'den tek farkı: alan ve method adları

Turnstile'da mantık aynıdır, yalnızca token gizli cf-turnstile-response alanına yazılır ve method olarak turnstile gönderilir.

def solve_turnstile_selenium(driver, url):
    """Complete Turnstile solve in Selenium."""
    driver.get(url)

    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, "body"))
    )

    # Extract sitekey
    page_source = driver.page_source
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', page_source)
    if not match:
        # Try JavaScript API pattern
        match = re.search(r"sitekey\s*:\s*['\"]([0-9x][A-Za-z0-9_-]+)['\"]", page_source)
    if not match:
        raise ValueError("Turnstile sitekey not found")

    sitekey = match.group(1)
    print(f"Turnstile sitekey: {sitekey}")

    # Solve via CaptchaAI
    token = solve_captcha(
        "turnstile",
        sitekey=sitekey,
        pageurl=url,
    )
    print(f"Turnstile token: {token[:50]}...")

    # Inject token
    driver.execute_script(f"""
        // Set the hidden input value
        var inputs = document.querySelectorAll('[name="cf-turnstile-response"]');
        inputs.forEach(function(input) {{ input.value = '{token}'; }});

        // Also try the callback approach
        if (typeof turnstile !== 'undefined' && turnstile.getResponse) {{
            // Widget already rendered
        }}
    """)

    # Submit form
    submit_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit'], input[type='submit']")
    submit_button.click()

    return token

Yani yalnızca iki şey değişir: token'ın yazıldığı gizli alan cf-turnstile-response olur ve API'ye method olarak turnstile gönderirsiniz. Sitekey çıkarımında önce data-sitekey özniteliği, bulunamazsa JavaScript API kalıbı denenir.


Selenium ile resim (OCR) CAPTCHA çözme

Klasik resim/metin CAPTCHA'ları (gördüğünüz harfleri yazın türü) için öğenin ekran görüntüsünü base64 olarak alıp CaptchaAI'ye gönderirsiniz:

import base64

def solve_image_captcha_selenium(driver, captcha_selector):
    """Solve image CAPTCHA visible in the browser."""
    # Find the CAPTCHA image element
    captcha_img = driver.find_element(By.CSS_SELECTOR, captcha_selector)

    # Get image as base64
    img_base64 = captcha_img.screenshot_as_base64

    # Solve via CaptchaAI
    answer = solve_captcha("base64", body=img_base64)
    print(f"CAPTCHA answer: {answer}")

    # Type the answer into the input field
    captcha_input = driver.find_element(
        By.CSS_SELECTOR, "input[name='captcha'], input[name='code'], input.captcha-input"
    )
    captcha_input.clear()
    captcha_input.send_keys(answer)

    return answer

Ekran görüntüsü boş çıkıyorsa öğe henüz görünür alanda değildir; önce scrollIntoView ile kaydırın, ardından base64 görüntüsünü alıp gönderin. Metin CAPTCHA'larında sonucu doğrudan input alanına yazarsınız — ayrı bir token enjeksiyonu gerekmez.


Selenium ile reCAPTCHA v3 çözme

reCAPTCHA v3'te görünür bir kutu yoktur; skor tabanlı çalışır. Bu yüzden version ve action parametrelerini de göndermeniz gerekir:

def solve_recaptcha_v3_selenium(driver, url, sitekey, action="verify"):
    """Solve reCAPTCHA v3 in Selenium."""
    driver.get(url)

    # Solve via CaptchaAI
    token = solve_captcha(
        "userrecaptcha",
        googlekey=sitekey,
        pageurl=url,
        version="v3",
        action=action,
    )

    # Inject token
    driver.execute_script(f"""
        // Set reCAPTCHA response
        var textarea = document.getElementById('g-recaptcha-response');
        if (textarea) {{
            textarea.value = '{token}';
            textarea.style.display = 'block';
        }}

        // Set any hidden input fields
        var inputs = document.querySelectorAll('input[name="g-recaptcha-response"]');
        inputs.forEach(function(input) {{ input.value = '{token}'; }});
    """)

    return token

reCAPTCHA v3 skor tabanlı çalıştığı için görünür bir kutu yoktur; token'ı enjekte ettikten sonra formu doğrudan gönderebilir, ayrı bir callback beklemezsiniz. Gönderdiğiniz action değerinin sayfadaki beklenen eylemle eşleşmesi, dönen skorun ve dolayısıyla başarı oranının artmasına yardımcı olur.


Uçtan uca otomasyon: tek sınıfta tespit-çöz-gönder

Üretimde tek tek fonksiyon çağırmak yerine türü otomatik tespit eden bir sınıf daha pratiktir. SeleniumCaptchaSolver sayfayı açar, CAPTCHA türünü belirler, uygun çözümü uygular ve formu gönderir:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import re
import time
import requests

API_KEY = "YOUR_API_KEY"

class SeleniumCaptchaSolver:
    """Complete Selenium + CaptchaAI automation class."""

    def __init__(self, api_key):
        self.api_key = api_key
        self.driver = None

    def start(self):
        """Initialize the browser."""
        options = webdriver.ChromeOptions()
        options.add_argument("--no-sandbox")
        options.add_experimental_option("excludeSwitches", ["enable-automation"])
        self.driver = webdriver.Chrome(options=options)
        self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
        })

    def stop(self):
        """Close the browser."""
        if self.driver:
            self.driver.quit()

    def navigate(self, url):
        """Navigate to URL and wait for load."""
        self.driver.get(url)
        WebDriverWait(self.driver, 15).until(
            lambda d: d.execute_script("return document.readyState") == "complete"
        )

    def detect_captcha(self):
        """Detect which CAPTCHA type is on the page."""
        source = self.driver.page_source

        if re.search(r'data-sitekey=["\'][A-Za-z0-9_-]{40}["\']', source):
            if "recaptcha/api.js" in source or "grecaptcha" in source:
                return "recaptcha_v2"

        if "cf-turnstile" in source or "challenges.cloudflare.com/turnstile" in source:
            return "turnstile"

        if re.search(r'recaptcha.*v3|render=[A-Za-z0-9_-]{40}', source):
            return "recaptcha_v3"

        captcha_imgs = self.driver.find_elements(
            By.CSS_SELECTOR, "img.captcha, img[alt*='captcha'], img[src*='captcha']"
        )
        if captcha_imgs:
            return "image"

        return None

    def solve_and_submit(self, url, form_data=None):
        """Navigate, solve CAPTCHA, fill form, and submit."""
        self.navigate(url)
        captcha_type = self.detect_captcha()

        if not captcha_type:
            print("No CAPTCHA detected")
            return self._fill_and_submit(form_data)

        print(f"Detected: {captcha_type}")

        if captcha_type == "recaptcha_v2":
            self._solve_recaptcha_v2()
        elif captcha_type == "turnstile":
            self._solve_turnstile()
        elif captcha_type == "image":
            self._solve_image()

        return self._fill_and_submit(form_data)

    def _solve_recaptcha_v2(self):
        source = self.driver.page_source
        match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', source)
        sitekey = match.group(1)

        token = self._api_solve("userrecaptcha", googlekey=sitekey, pageurl=self.driver.current_url)

        self.driver.execute_script(f"""
            document.getElementById('g-recaptcha-response').value = '{token}';
        """)

    def _solve_turnstile(self):
        source = self.driver.page_source
        match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', source)
        sitekey = match.group(1)

        token = self._api_solve("turnstile", sitekey=sitekey, pageurl=self.driver.current_url)

        self.driver.execute_script(f"""
            document.querySelectorAll('[name="cf-turnstile-response"]')
                .forEach(function(el) {{ el.value = '{token}'; }});
        """)

    def _solve_image(self):
        img = self.driver.find_element(
            By.CSS_SELECTOR, "img.captcha, img[alt*='captcha'], img[src*='captcha']"
        )
        answer = self._api_solve("base64", body=img.screenshot_as_base64)

        captcha_input = self.driver.find_element(
            By.CSS_SELECTOR, "input[name='captcha'], input[name='code']"
        )
        captcha_input.clear()
        captcha_input.send_keys(answer)

    def _fill_and_submit(self, form_data):
        if form_data:
            for name, value in form_data.items():
                try:
                    field = self.driver.find_element(By.NAME, name)
                    field.clear()
                    field.send_keys(value)
                except Exception:
                    pass

        submit = self.driver.find_element(
            By.CSS_SELECTOR, "button[type='submit'], input[type='submit']"
        )
        submit.click()
        time.sleep(3)
        return self.driver.current_url

    def _api_solve(self, method, **params):
        submit = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key, "method": method, "json": 1, **params,
        }, timeout=30)
        data = submit.json()
        if data.get("status") != 1:
            raise Exception(f"Submit error: {data.get('request')}")

        task_id = data["request"]
        for _ in range(30):
            time.sleep(5)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key, "action": "get", "id": task_id, "json": 1,
            }, timeout=30).json()
            if result.get("status") == 1:
                return result["request"]
        raise TimeoutError("Solve timed out")

# Usage
solver = SeleniumCaptchaSolver(API_KEY)
solver.start()
try:
    result_url = solver.solve_and_submit(
        "https://staging.example.com/qa-login",
        form_data={"username": "user@example.com", "password": "pass123"},
    )
    print(f"Result: {result_url}")
finally:
    solver.stop()

Sınıfın iş akışı

SeleniumCaptchaSolver tespit-çöz-gönder döngüsünü tek yerde toplar:

  • navigate — sayfayı açar ve readyState tamamlanana kadar bekler.
  • detect_captcha — sayfa kaynağını tarayıp CAPTCHA türünü döndürür.
  • ilgili _solve_* — token'ı çözer ve gizli alana enjekte eder.
  • _fill_and_submit — form alanlarını doldurup gönderir ve sonuç URL'sini döndürür.

Performans ve maliyet notları

Selenium, tarayıcı başlatma ve sayfa render'ı için istek başına 3–5 saniye ek yük getirir; CAPTCHA çözüm süresi CaptchaAI tarafında sabit kalır. Maliyeti ve gecikmeyi öngörülebilir tutmak için birkaç pratik kural:

  • Paralel çözüm sayınızı plan thread'inizle eşleştirin — tek bir QA senaryosu için BASIC ($15/ay, 5 thread) genellikle yeterlidir.
  • Tarayıcı örneğini yeniden kullanın; her istek için yeni bir sürücü açmayın.
  • Yalnızca token'a ihtiyaç duyduğunuz adımlarda requests'e düşün, Selenium'u yalnızca gerçek render gerektiğinde kullanın.

Sorun giderme

Aşağıdaki tablo, entegrasyonda en sık karşılaşılan beş belirtiyi olası nedeni ve pratik çözümüyle eşleştirir:

Belirti Olası neden Çözüm
CAPTCHA tespit edildi ama token enjeksiyonu başarısız oldu g-recaptcha-response bulunamadı iframe'leri kontrol edin — reCAPTCHA bir iframe içinde olabilir
Token enjekte edildi ama form gönderilmiyor callback tetiklenmedi reCAPTCHA callback fonksiyonunu açıkça çağırın
Site "webdriver algılandı" diyor CDP ayarı uygulanmadı webdriver bayrağını kaldıran CDP komutunu ekleyin
Resim CAPTCHA ekran görüntüsü boş çıkıyor Öğe görünür değil Önce öğeyi görünür alana kaydırın
Turnstile token'ı reddedildi Yanlış sitekey Canlı sayfa kaynağından sitekey'i yeniden çıkarın

Sık sorulan sorular

Selenium mi yoksa yalnızca requests mi kullanmalıyım?

Sayfa JavaScript yürütmesi, dinamik içerik yüklemesi veya çok adımlı bir akış gerektiriyorsa Selenium kullanın. Yalnızca token'a ihtiyaç duyduğunuz basit, API tabanlı form gönderimlerinde requests daha hızlı ve hafiftir.

reCAPTCHA bir iframe içindeyse sitekey'i nasıl çıkarırım?

Önce iframe'e geçin: driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "iframe[src*='recaptcha']")), sitekey'i okuyun, ardından driver.switch_to.default_content() ile ana içeriğe dönün. sitekey genellikle data-sitekey özniteliğinde durur.

Token'ı enjekte ettim ama form gönderilmiyor, sorun ne?

Çoğu reCAPTCHA formu, token yerleştirmenin yanında callback fonksiyonunun da çağrılmasını bekler. Yukarıdaki ___grecaptcha_cfg bloğu bunu yapar; Turnstile için de gizli cf-turnstile-response alanını doldurduktan sonra formu doğrudan gönderin.

CaptchaAI Selenium ile hangi CAPTCHA türlerini çözer?

reCAPTCHA v2/v3 (Enterprise dahil), Cloudflare Turnstile ve Challenge, GeeTest v3, BLS ve resim/grid CAPTCHA'ları desteklenir. hCaptcha ve FunCaptcha desteklenmez; CaptchaFox, Friendly Captcha ve Lemin ise beta aşamasındadır.

Selenium otomasyonu için hangi CaptchaAI planı yeterli?

Faturalama thread başına olduğu için tek seferde kaç CAPTCHA'yı paralel çözdüğünüze bağlıdır. Tek bir QA senaryosu için BASIC ($15/ay, 5 thread) genellikle yeterlidir; paralel iş yükleri büyüdükçe STANDARD ($30/ay, 15 thread) veya ADVANCE ($90/ay, 50 thread) tarafına geçebilirsiniz.


Özet

Selenium tarayıcıyı sürer, CaptchaAI CAPTCHA'yı çözer. Akış her tür için aynıdır: sayfa kaynağından türü tespit edin, CaptchaAI API'si üzerinden çözün, token'ı JavaScript ile enjekte edin ve formu gönderin. SeleniumCaptchaSolver sınıfı bu tespit-çöz-gönder döngüsünü tek yerde toplar. Kişisel veri içeren sayfaları otomatikleştiriyorsanız KVKK kapsamında yetkili bir iş akışında kaldığınızdan emin olun.

İlgili Makaleler

Bu makale için yorumlar devre dışı bırakılmıştır.