Bir formu Selenium ile doldurmak kolaydır; asıl duvar, gönder düğmesinden hemen önce çıkan CAPTCHA'dır. Çözüm nettir: sayfadaki CAPTCHA türünü algılayın, CaptchaAI API ile çözün, dönen token'ı ilgili alana enjekte edin ve formu gönderin. Aşağıdaki Python iskeleti reCAPTCHA v2, Cloudflare Turnstile ve görüntü tabanlı CAPTCHA'yı tek bir akışta bu sırayla yönetir; kodun tamamı Python, Node.js, PHP ve daha fazlası için örnek pakette hazır.
Neden CAPTCHA'lı formlar otomasyonu durdurur?
CAPTCHA ile korunan formlar otomasyon betiklerini kasıtlı olarak engeller: alanları eksiksiz doldursanız bile, doğrulama tamamlanmadan sunucu gönderiminizi reddeder. İster iletişim formu test edin, ister bir e-ticaret ödeme akışını her sürümde regresyondan geçirin, sonuç aynıdır — CAPTCHA çözülmeden form ilerlemez.
Türkiye'deki geliştirici ekiplerin en sık karşılaştığı senaryo, kayıt ve ödeme akışlarının sürekli regresyon testidir. Böyle bir otomasyonu yalnızca yetkiniz olan sistemlerde ve kendi ortamlarınızda çalıştırın; topladığınız kişisel veriler KVKK kapsamına girer ve yalnızca izinli QA iş akışlarında işlenmelidir.
Tarayıcı mı, yoksa yalnızca API mi?
İki yaklaşım vardır. reCAPTCHA v2 ve Turnstile token'larını bir tarayıcı açmadan, doğrudan CaptchaAI API'sine sitekey ve pageurl göndererek çözebilir, sonucu HTTP POST ile iletebilirsiniz — bu yol daha hızlı ve daha hafiftir.
Ancak form, gönderimi çalışma zamanında JavaScript ile doğruluyor ya da token'ı bir callback üzerinden enjekte ediyorsa gerçek bir tarayıcıya ihtiyaç duyarsınız. Bu rehberdeki FormAutomator, çoğu üretim formu JavaScript doğrulaması içerdiği için Selenium tabanlı yaklaşımı kullanır. Karar kuralı basittir: sayfa token olmadan da gönderimi kabul ediyorsa API yeterlidir; kabul etmiyorsa tarayıcı gerekir.
Otomasyon akışının mimarisi
Akış dört adımdan oluşur: Selenium formu yükler, alanları doldurur, sayfadaki CAPTCHA'yı algılayıp çözer ve formu gönderir. Çözüm adımı gönderimden hemen önce gelir; token kısa ömürlü olduğu için bu sıralama başarının anahtarıdır.
┌────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐
│ Load Form │────▶│ Fill Fields │────▶│ Detect & │────▶│ Submit Form │
│ (Selenium) │ │ │ │ Solve │ │ │
│ │ │ │ │ CAPTCHA │ │ │
└────────────┘ └──────────────┘ └────────────┘ └──────────────┘
Çözücü sınıfı: görevi gönder, sonucu sorgula
Çözücü iki uç noktayla çalışır: görevi in.php'ye gönderir, ardından res.php'yi CAPCHA_NOT_READY yanıtı gelmeyene kadar periyodik olarak sorgular. initial_wait, ilk sorgulamadan önce beklenen saniye sayısını; döngü ise en fazla kaç kez sorgulanacağını belirler. Token hazır olduğunda solve() değeri döndürür, süre aşılırsa TimeoutError fırlatır. Bu tasarım, sabit bir sleep yerine sonucu hazır olur olmaz almanızı sağlar.
import time
import requests
class FormCaptchaSolver:
BASE = "https://ocr.captchaai.com"
def __init__(self, api_key):
self.api_key = api_key
def solve(self, params, initial_wait=10):
params["key"] = self.api_key
params["json"] = 1
resp = requests.post(f"{self.BASE}/in.php", data=params).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
time.sleep(initial_wait)
for _ in range(60):
result = requests.get(
f"{self.BASE}/res.php",
params={"key": self.api_key, "action": "get", "id": task_id, "json": 1},
).json()
if result["request"] == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result["status"] == 1:
return result["request"]
raise Exception(f"Solve error: {result['request']}")
raise TimeoutError("CAPTCHA solve timed out")
Algılayıcı sınıfı: hangi CAPTCHA türü?
Algılayıcı, sayfa kaynağına ve DOM seçicilerine bakarak türü belirler. Sıra önemlidir: önce Turnstile (.cf-turnstile), sonra data-sitekey taşıyan reCAPTCHA öğesi, en son img[src*='captcha'] görüntü CAPTCHA'sı kontrol edilir. Yanlış sıra, sayfada birden fazla doğrulama öğesi varsa hatalı türe yol açabilir. Algılayıcı türle birlikte çözüm için gereken sitekey değerini veya görsel kaynağını da döndürür.
import re
from selenium.webdriver.common.by import By
class CaptchaDetector:
def __init__(self, driver):
self.driver = driver
def detect(self):
"""Detect CAPTCHA type on current page."""
html = self.driver.page_source
# Turnstile
turnstile = self.driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile, [data-sitekey]")
for el in turnstile:
if "cf-turnstile" in (el.get_attribute("class") or ""):
return "turnstile", el.get_attribute("data-sitekey")
# reCAPTCHA
recaptcha = self.driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
if recaptcha:
sitekey = recaptcha[0].get_attribute("data-sitekey")
if "recaptcha" in html.lower():
return "recaptcha_v2", sitekey
# Image CAPTCHA
img = self.driver.find_elements(By.CSS_SELECTOR, "img[src*='captcha'], img.captcha")
if img:
return "image", img[0].get_attribute("src")
return "none", None
Otomatikleştirici sınıfı: hepsini bir araya getir
Otomatikleştirici üç parçayı birleştirir. fill_field her alanı açık beklemeyle (explicit wait) doldurur; solve_captcha algılanan türe göre doğru token alanını — reCAPTCHA için g-recaptcha-response, Turnstile için cf-turnstile-response — JavaScript ile yazar ya da görüntü CAPTCHA'sında çözülen metni giriş kutusuna girer. submit_form bütün sırayı yönetir: sayfayı açar, alanları doldurur, CAPTCHA'yı çözer ve gönder düğmesine basar.
import base64
import requests as req
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
class FormAutomator:
def __init__(self, api_key):
self.solver = FormCaptchaSolver(api_key)
self.driver = webdriver.Chrome()
self.detector = CaptchaDetector(self.driver)
def fill_field(self, selector, value):
field = WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, selector))
)
field.clear()
field.send_keys(value)
def select_option(self, selector, value):
from selenium.webdriver.support.ui import Select
select = Select(self.driver.find_element(By.CSS_SELECTOR, selector))
select.select_by_value(value)
def solve_captcha(self):
captcha_type, data = self.detector.detect()
page_url = self.driver.current_url
if captcha_type == "recaptcha_v2":
token = self.solver.solve({
"method": "userrecaptcha",
"googlekey": data,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
)
return True
if captcha_type == "turnstile":
token = self.solver.solve({
"method": "turnstile",
"sitekey": data,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
)
return True
if captcha_type == "image":
img_data = req.get(data).content
img_b64 = base64.b64encode(img_data).decode()
text = self.solver.solve({"method": "base64", "body": img_b64})
captcha_input = self.driver.find_element(
By.CSS_SELECTOR, "input[name*='captcha']"
)
captcha_input.clear()
captcha_input.send_keys(text)
return True
return False # No CAPTCHA detected
def submit_form(self, url, fields, submit_selector="button[type='submit']"):
"""
fields: list of (selector, value) tuples
"""
self.driver.get(url)
for selector, value in fields:
self.fill_field(selector, value)
self.solve_captcha()
submit = self.driver.find_element(By.CSS_SELECTOR, submit_selector)
submit.click()
return self.driver.current_url
def close(self):
self.driver.quit()
Uçtan uca örnek: iletişim formu
Aşağıdaki örnek tüm parçaları bir araya getirir. submit_form, seçici–değer çiftlerini alır, arada CAPTCHA'yı çözer ve gönderim sonrası yönlendirilen URL'yi döndürür; try/finally bloğu, hata olsa bile tarayıcının her durumda kapatılmasını sağlar. Bir e-ticaret ekibinin ödeme öncesi iletişim formunu her yeni sürümde otomatik doğrulaması tam olarak bu kalıba oturur.
automator = FormAutomator("YOUR_API_KEY")
try:
result_url = automator.submit_form(
url="https://example.com/contact",
fields=[
("#name", "John Doe"),
("#email", "john@example.com"),
("#subject", "Sales inquiry"),
("#message", "I'd like to learn more about your services."),
],
submit_selector="#submit-btn",
)
print(f"Form submitted. Redirected to: {result_url}")
finally:
automator.close()
Farklı form türlerini tek akışla yönetmek
Aynı FormAutomator, yalnızca seçici ve değer listesini değiştirerek giriş, kayıt ve arama formlarında da çalışır. Giriş testlerini üretim yerine bir staging ortamında çalıştırmak, gerçek kullanıcı verisine dokunmadan güvenle test etmenizi sağlar.
Giriş formu
result = automator.submit_form(
url="https://staging.example.com/qa-login",
fields=[
("#username", "testuser"),
("#password", "testpass123"),
],
submit_selector="#login-btn",
)
Kayıt formu
result = automator.submit_form(
url="https://example.com/register",
fields=[
("#first-name", "Jane"),
("#last-name", "Smith"),
("#email", "jane@example.com"),
("#password", "SecurePass!123"),
("#confirm-password", "SecurePass!123"),
],
submit_selector="#register-btn",
)
CAPTCHA'lı arama formu
result = automator.submit_form(
url="https://example.com/search",
fields=[
("#query", "python developer"),
("#location", "San Francisco"),
],
submit_selector="#search-btn",
)
Üretime alırken dikkat edilecekler
Birkaç kural, kırılgan bir betiği güvenilir bir iş akışına dönüştürür:
- CAPTCHA'yı en son çözün. Token yalnızca birkaç dakika geçerlidir; alanları doldurduktan sonra çözün ve token'ı hemen gönderin.
- Sabit
sleepyerine açık bekleme kullanın. Dinamik yüklenen sayfalardaWebDriverWait, hem daha hızlı hem daha kararlı sonuç verir. - Yeniden deneme ve geri çekilme ekleyin. Ağ veya çözüm hatalarında üstel geri çekilme (exponential backoff) ile yeniden deneyin; her hatada baştan başlamayın.
- Eşzamanlılığı plan thread sayınıza göre ayarlayın. CaptchaAI thread bazlı faturalandırır: thread başına sınırsız çözüm, CAPTCHA türüne göre ek ücret yok. BASIC ($15/ay, 5 thread) çoğu QA iş yükü için yeterlidir; yüksek hacim için ADVANCE ($90/ay, 50 thread) kullanın. Ücretlendirme USD bazlı ve öngörülebilir olduğundan, TL kuru oynasa da aylık maliyetiniz sabit kalır.
- Sunucunun hız sınırına (rate limiting) saygı gösterin. İstekler arasına makul gecikme koyun; agresif toplu gönderim, formun sizi engellemesine yol açabilir.
Sık karşılaşılan sorunlar ve çözümleri
| Sorun | Olası neden | Çözüm |
|---|---|---|
| Token reddedildi | Token gönderilmeden önce süresi doldu | CAPTCHA'yı en son çözün, token'ı hemen gönderin |
| Alan bulunamadı | Sayfa dinamik yükleniyor | Açık bekleme (explicit wait) ekleyin |
| Yanlış CAPTCHA türü algılandı | Sayfada birden fazla CAPTCHA öğesi var | Algılama sırasını gözden geçirin |
| Form gönderimden sonra yeniden yükleniyor | Sunucu tarafı doğrulaması başarısız | Zorunlu alanların tümünü kontrol edin |
| reCAPTCHA callback'i tetiklenmedi | callback fonksiyonunu çağırmanız gerekiyor | Enjeksiyondan sonra grecaptcha.execute() çağırın |
Sık sorulan sorular
Bu akış hangi CAPTCHA türlerini çözer?
reCAPTCHA v2, Cloudflare Turnstile ve görüntü tabanlı CAPTCHA. hCaptcha ve FunCaptcha CaptchaAI tarafından desteklenmiyor; formunuz bunlardan birini kullanıyorsa bu akış çalışmaz.
CaptchaAI'yi kullanmak için hangi planla başlamalıyım?
Çoğu form otomasyonu ve QA iş yükü için BASIC ($15/ay, 5 thread) yeterlidir. CaptchaAI thread bazlı faturalandırır: thread başına sınırsız çözüm ve türe göre ek ücret yoktur. Daha yüksek eşzamanlılık gerekiyorsa ADVANCE ($90/ay, 50 thread) tercih edin.
Aynı formda birden fazla CAPTCHA çıkarsa ne yapmalıyım?
Bazı formlar CAPTCHA'yı yalnızca ilk doğrulama başarısız olunca gösterir. Her gönderim denemesinden sonra solve_captcha()'yı yeniden çalıştırın.
"Token reddedildi" hatasını nasıl önlerim?
Token kısa ömürlüdür; alanları doldurduktan sonra CAPTCHA'yı en son adımda çözün ve token'ı saniyeler içinde gönderin. Araya uzun bekleme koymayın.
Form otomasyonu KVKK açısından uygun mu?
Yalnızca yetkili olduğunuz sistemlerde ve test ortamlarında çalıştırın; topladığınız kişisel veriler KVKK kapsamına girer ve amaç dışı işlenmemelidir.
İlgili kılavuzlar
Herhangi bir formu tek akışta otomatikleştirin — CAPTCHA'ları CaptchaAI ile çözün.