Bazı siteler giriş sayfalarında reCAPTCHA'yı ve ödeme sayfalarında Turnstile'yi kullanır. Diğerleri A/B sağlayıcılar arasında test yapıyor — aynı URL, bir ziyaretçi için reCAPTCHA'yı ve diğeri için Turnstile'yi gösteriyor. Tek bir çözücü yöntemini sabit kodlamak, otomasyonunuzun diğer türle karşılaştığında bozulduğu anlamına gelir.
Siteler Neden Birden Fazla CAPTCHA Sağlayıcısı Kullanıyor?
| Senaryo | Nasıl Görünüyor? |
|---|---|
| Farklı sayfalar, farklı sağlayıcılar | Giriş = reCAPTCHA, ödeme = Turnstile |
| A/B test sağlayıcıları | Aynı sayfa her iki türü de rastgele gösterir |
| Taşıma işlemi devam ediyor | Eski sayfalarda reCAPTCHA var, yeni sayfalarda Turnstile var |
| Başarısızlık durumunda geri dönüş | Birincil sağlayıcı başarısız oluyor → ikincil sağlayıcıya geri dönüyor |
| Bölgesel çeşitlilik | ABD'li ziyaretçiler için reCAPTCHA, AB için Turnstile (GDPR) |
Python: Otomatik Algıla ve Çöz
import requests
import time
import re
from dataclasses import dataclass
API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
@dataclass
class CaptchaInfo:
provider: str # "recaptcha" or "turnstile"
method: str # API method name
sitekey: str
pageurl: str
response_field: str # Form field name for the token
def detect_captcha_type(html, pageurl):
"""
Detect which CAPTCHA provider is on the page.
Returns CaptchaInfo or None.
"""
# Check for Turnstile
turnstile_match = re.search(
r'class=["\'][^"\']*cf-turnstile[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
html,
)
if not turnstile_match:
turnstile_match = re.search(
r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*cf-turnstile',
html,
)
if turnstile_match:
return CaptchaInfo(
provider="turnstile",
method="turnstile",
sitekey=turnstile_match.group(1),
pageurl=pageurl,
response_field="cf-turnstile-response",
)
# Check for reCAPTCHA
recaptcha_match = re.search(
r'class=["\'][^"\']*g-recaptcha[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
html,
)
if not recaptcha_match:
recaptcha_match = re.search(
r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*g-recaptcha',
html,
)
# Also check for script-rendered reCAPTCHA
if not recaptcha_match:
recaptcha_match = re.search(
r'grecaptcha\.render\([^,]+,\s*\{[^}]*["\']sitekey["\']\s*:\s*["\']([^"\']+)["\']',
html,
)
if recaptcha_match:
return CaptchaInfo(
provider="recaptcha",
method="userrecaptcha",
sitekey=recaptcha_match.group(1),
pageurl=pageurl,
response_field="g-recaptcha-response",
)
return None
def solve_captcha(info):
"""Solve any detected CAPTCHA type via CaptchaAI."""
params = {
"key": API_KEY,
"method": info.method,
"json": 1,
}
if info.method == "userrecaptcha":
params["googlekey"] = info.sitekey
params["pageurl"] = info.pageurl
elif info.method == "turnstile":
params["sitekey"] = info.sitekey
params["pageurl"] = info.pageurl
resp = requests.post(SUBMIT_URL, data=params, timeout=30).json()
if resp.get("status") != 1:
raise RuntimeError(f"Submit failed: {resp.get('request')}")
task_id = resp["request"]
for _ in range(60):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get",
"id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve failed: {poll.get('request')}")
raise RuntimeError("Timeout")
def process_page(session, url):
"""Fetch page, detect CAPTCHA type, solve, and return form-ready data."""
response = session.get(url)
captcha_info = detect_captcha_type(response.text, url)
if not captcha_info:
print(f"No CAPTCHA detected on {url}")
return None
print(f"Detected {captcha_info.provider} on {url}")
print(f" Sitekey: {captcha_info.sitekey[:30]}...")
token = solve_captcha(captcha_info)
print(f" Solved: {token[:30]}...")
return {
"provider": captcha_info.provider,
"response_field": captcha_info.response_field,
"token": token,
}
# Usage: Handle multiple pages with different providers
session = requests.Session()
pages = [
"https://staging.example.com/qa-login", # Might have reCAPTCHA
"https://example.com/checkout", # Might have Turnstile
]
for url in pages:
result = process_page(session, url)
if result:
form_data = {result["response_field"]: result["token"]}
# Add other form fields...
# session.post(url, data=form_data)
JavaScript: Dinamik CAPTCHA Algılama
const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
function detectCaptchaType(html, pageurl) {
// Turnstile
const turnstileMatch = html.match(/cf-turnstile[^>]*data-sitekey=["']([^"']+)["']/);
if (turnstileMatch) {
return { provider: "turnstile", method: "turnstile", sitekey: turnstileMatch[1], pageurl, field: "cf-turnstile-response" };
}
// reCAPTCHA
const recaptchaMatch = html.match(/g-recaptcha[^>]*data-sitekey=["']([^"']+)["']/);
if (recaptchaMatch) {
return { provider: "recaptcha", method: "userrecaptcha", sitekey: recaptchaMatch[1], pageurl, field: "g-recaptcha-response" };
}
// Script-rendered reCAPTCHA
const scriptMatch = html.match(/sitekey["']\s*:\s*["']([^"']+)["']/);
if (scriptMatch) {
return { provider: "recaptcha", method: "userrecaptcha", sitekey: scriptMatch[1], pageurl, field: "g-recaptcha-response" };
}
return null;
}
async function solveCaptcha(info) {
const body = new URLSearchParams({ key: API_KEY, method: info.method, json: "1" });
if (info.method === "userrecaptcha") { body.set("googlekey", info.sitekey); body.set("pageurl", info.pageurl); }
else if (info.method === "turnstile") { body.set("sitekey", info.sitekey); body.set("pageurl", info.pageurl); }
const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);
const taskId = resp.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
const poll = await (await fetch(url)).json();
if (poll.request === "CAPCHA_NOT_READY") continue;
if (poll.status === 1) return poll.request;
throw new Error(`Solve: ${poll.request}`);
}
throw new Error("Timeout");
}
async function processPage(url) {
const response = await fetch(url);
const html = await response.text();
const info = detectCaptchaType(html, url);
if (!info) { console.log(`No CAPTCHA on ${url}`); return null; }
console.log(`${info.provider} detected on ${url}`);
const token = await solveCaptcha(info);
return { provider: info.provider, field: info.field, token };
}
// Usage
const pages = ["https://staging.example.com/qa-login", "https://example.com/checkout"];
for (const url of pages) {
const result = await processPage(url);
if (result) {
console.log(`Solved ${result.provider}: ${result.token.substring(0, 30)}...`);
}
}
Sağlayıcı Tespit Referansı
| sağlayıcı | HTML İşaretleyici | Komut dosyası URL'si | Yanıt Alanı |
|---|---|---|---|
| reCAPTCHA v2 | class="g-recaptcha" |
google.com/recaptcha/api.js |
g-recaptcha-response |
| Cloudflare Turnstile | class="cf-turnstile" |
challenges.cloudflare.com/turnstile |
cf-turnstile-response |
| hCaptcha | class="h-captcha" |
js.hcaptcha.com/1/api.js |
h-captcha-response |
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Yanlış CAPTCHA türü algılandı | Regex yanlış öğeyle eşleşiyor | Yalnızca data-sitekey'yi değil, öncelikle sağlayıcıya özel sınıf adlarını kontrol edin |
| Doğru çözümden sonra jeton reddedildi | Yanlış yanıt alanı adı kullanıldı | Alan adını sağlayıcıyla eşleştirin: g-recaptcha-response vs cf-turnstile-response |
| Ziyaretler arasında CAPTCHA türü değişiklikleri | A/B testi veya coğrafi tabanlı seçim | Her zaman dinamik olarak tespit edin; sağlayıcıyı hiçbir zaman sabit kodlamayın |
| Her iki sağlayıcı da tek sayfada tespit edildi | Biri gizlenmiş olabilir/inactive | Öğe görünürlüğünü kontrol edin — yalnızca görünür CAPTCHA'yı çözün |
| Komut dosyasıyla oluşturulan CAPTCHA'lar için algılama başarısız oluyor | Kaynakta HTML işaretçisi yok | Komut dosyalarında grecaptcha.render() veya turnstile.render() çağrılarını kontrol edin |
SSS
Bir sayfa hem reCAPTCHA'yı hem de Turnstile'yi aynı anda kullanabilir mi?
Nadiren aynı formda olur ancak sitenin farklı kısımlarında gerçekleşir. Her ikisi de bir sayfada görünüyorsa, genellikle yalnızca biri etkindir; hangi widget'in görünür olduğunu ve boş olmayan bir data-sitekey'ye sahip olduğunu kontrol edin.
CaptchaAI her iki sağlayıcı için de aynı API'yi mi kullanıyor?
Aynı uç noktalar (in.php / res.php) ancak farklı method değerleri. reCAPTCHA, googlekey ile method=userrecaptcha'yi kullanırken Turnstile, sitekey ile method=turnstile'yi kullanır. Otomatik algılama modeli bu eşlemeyi yönetir.
Sağlayıcı yük devretme işlemini nasıl halledebilirim?
Bir site oturumun ortasında reCAPTCHA'dan Turnstile'ye geçerse (örneğin, reCAPTCHA yüklenemezse), sağlayıcıyı ilk ziyaretten itibaren önbelleğe almak yerine her sayfa isteğinde CAPTCHA türünü yeniden tespit edin.
İlgili Makaleler
- Api Kullanarak Recaptcha V2 Geri Arama Sorunu Nasıl Çözülür?
- Cloudflare doğrulama akışı Vs Turnstile Algılama
- Geetest ve Cloudflare Turnstile Karşılaştırması
Sonraki Adımlar
Birden fazla CAPTCHA sağlayıcısına sahip siteleri yönetin —CaptchaAI API anahtarınızı alınve otomatik algılamayı uygulayın.
İlgili kılavuzlar: