Token elinizde, çözüm başarılı görünüyor, ama hedef site isteği yine de reddediyor. Bunun neredeyse tek bir nedeni var: çözücüye verdiğiniz pageurl, token'ı gönderdiğiniz alan adıyla birebir aynı değil.
reCAPTCHA her token'ın içine üretildiği ana makine adını gömer. Sunucu siteverify yanıtındaki hostname değerini beklediğiyle karşılaştırır ve tutmuyorsa reddeder.
Önce şu dört şeyi kontrol edin
Kod açmadan önce bu listeyi geçin:
- Tarayıcıdaki nihai URL nedir? Adres çubuğundakini kopyalayın;
pageurlo olmalı. - www var mı yok mu?
example.comilewww.example.comayrı ana makine adı olabilir. - Token'ı hangi hosta gönderiyorsunuz? Çözüm isteğiyle gönderim adresi ayrışmışsa uyuşmazlık kaçınılmazdır.
- Araya CDN veya reverse proxy giriyor mu?
Hostbaşlığını değiştiren katmanhostnamedeğerini de değiştirir.
Bu hatalar sessizdir: ne konsolda uyarı ne de 5xx yanıtı görürsünüz.
reCAPTCHA alan adı doğrulaması zincirin neresinde çalışır?
Site owner registers reCAPTCHA → adds allowed domains (example.com, www.example.com)
↓
reCAPTCHA widget loads on example.com → matches allowed domain ✓
↓
Token generated with embedded hostname
↓
Server validates token via siteverify API
↓
Google checks: Does token hostname match allowed domains?
├─ YES → { "success": true, "hostname": "example.com" }
└─ NO → { "success": false, error or hostname mismatch }
Alan adı üç ayrı noktada denetlenir
| Kontrol noktası | Ne doğrulanır |
|---|---|
| İstemci tarafı | Widget yalnızca izin verilen alan adlarında yüklenir (kapatılabilir) |
| Token üretimi | Token'ın içine gömülen ana makine adı, sayfanın kökeniyle eşleşir |
| Sunucu doğrulaması | siteverify ana makine adını döndürür; kararı site sahibinin sunucusu verir |
Kritik nokta: ret kararını Google değil, hedef sitenin doğrulama kodu verir.
Sık görülen üç alan adı hatası
Hata 1: siteverify yanıtındaki hostname tutmuyor
{
"success": true,
"hostname": "subdomain.example.com",
"challenge_ts": "2025-01-15T10:30:00Z"
}
Token geçerli (success: true) ama hostname beklenenden farklı; katı sunucular reddeder:
# Server-side validation that checks hostname
def validate_token(token, secret_key, expected_hostname):
result = requests.post(
"https://www.google.com/recaptcha/api/siteverify",
data={"secret": secret_key, "response": token},
).json()
if not result.get("success"):
return False
# This check causes failures when hostnames don't match
if result.get("hostname") != expected_hostname:
return False # Domain mismatch!
return True
Uyuşmazlık genelde şu üç kalıptan biridir:
| Token nerede üretildi | Doğrulama nerede yapıldı |
|---|---|
www.example.com |
example.com |
staging.example.com |
üretim alan adı |
| CDN arkasındaki gerçek host | proxy'nin değiştirdiği Host |
Düzeltme:
pageurlile gönderim adresi karakter karakter aynı olmalı — şema ve alt alan adı dahil.
Hata 2: Widget "Invalid domain for site key" hatası veriyor
Widget hiç görünmüyor ya da konsola şu satırı düşüyor:
ERROR: Invalid domain for site key
| Yapılandırma durumu | Sonuç |
|---|---|
sitekey izinli listesinde o alan adı yok |
Widget hiç yüklenmez |
Sayfa localhost ya da file:// üzerinden açık |
Köken doğrulanamaz |
| Alan adı yerine IP adresi kullanılmış | Kayıtla eşleşmez |
Otomasyon tarafındaki karşılığı: Bu, site sahibinin konsol ayarıdır; dışarıdan düzeltilmez. İzinli listeyle örtüşen
pageurlgönderin.
Hata 3: Çözüm doğru ama token reddediliyor
{
"success": false,
"error-codes": ["invalid-input-response"]
}
Token başka bir alan adı için üretilmiş demektir; en sık görülen hâli, çözücüye giden pageurl ile isteğin gittiği adresin ayrışmasıdır:
# WRONG: pageurl doesn't match actual target
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": "https://staging.example.com/qa-login", # ← Must match actual domain
"json": 1,
})
# But submitting token to:
requests.post("https://app.staging.example.com/qa-login", ...) # Different subdomain!
Belirtiden nedene: hızlı eşleme tablosu
Hata mesajı yoksa belirtiden geriye yürüyün:
| Belirti | Muhtemel neden | Düzeltme |
|---|---|---|
| Token her seferinde reddediliyor | pageurl hedef alan adıyla eşleşmiyor |
pageurl değerini gerçek hedefle eşitleyin |
| www'de çalışıyor, www'siz sürümde düşüyor | Alan adı varyantı uyuşmazlığı | Sitenin fiilen kullandığı varyantı kullanın |
| Bazen geçiyor, bazen geçmiyor | CDN farklı alan adları sunuyor | Zincirin sonundaki tek URL'de sabitleyin |
| Tarayıcıda sorun yok, betikte var | Betik farklı bir kökenden gönderiyor | Tarayıcının nihai URL'sini birebir kopyalayın |
| Enterprise token'ı reddediliyor | Yanlış proje veya alan adı bağlama | Enterprise konsolundaki alan adı ayarlarını gözden geçirin |
Pratikte nasıl görünüyor: bir e-ticaret QA senaryosu
Türkiye'de otomasyon işi ağırlıkla e-ticaret ve fintek tarafında; regresyon testleri staging'de koşar, üretim ayrı alan adındadır. Haftalardır sorunsuz çalışan senaryo, üretime alındığı gün token reddedilmeye başlar:
| Ortam | Testin gönderdiği pageurl |
Sonuç |
|---|---|---|
| Staging | https://staging.example.com/qa-login |
Token kabul edilir |
| Üretim | https://staging.example.com/qa-login |
hostname uyuşmazlığı |
Çözüm basit: adresi koda gömmeyin, ortam değişkeninden okuyun (CAPTCHA_PAGE_URL).
- KVKK. Gerçek kullanıcı verisi KVKK yükümlülüğü doğurur; testleri sentetik veriyle (
+90formatında numaralar,tr-TRlocale,Europe/Istanbul) yürütün. - Maliyet. CaptchaAI planları thread üzerinden faturalanır, fiyatlar USD:
BASIC ($15/ay, 5 thread)küçük bir QA paketine yeter, paralel koşan ekiplerADVANCE ($90/ay, 50 thread)kullanır.
Alan adı eşleşme kuralları: tam eşleşme, joker ve alt alan adları
reCAPTCHA varsayılan olarak katı alt alan adı eşleştirmesi yapmaz; davranışı konsoldaki liste belirler:
| Kayıtlı alan adı | Kabul edilen kökenler |
|---|---|
example.com |
example.com, www.example.com, sub.example.com (joker etkinse) |
www.example.com |
Yalnızca www.example.com (katı yapılandırmada) |
*.example.com |
example.com altındaki tüm alt alan adları |
localhost |
Yalnızca localhost (geliştirme ortamı için) |
Kabul kararını sunucu verir
siteverify yanıtındaki hostname token'ın üretildiği sayfayı yansıtır.
Kabul kararı sunucuya kalmıştır; aşağıdaki iki uygulamanın farkı, aynı token'ın neden bir yerde geçip başka yerde düştüğünü açıklar:
# Permissive validation (accepts any subdomain)
def validate_permissive(token, secret, base_domain):
result = requests.post(
"https://www.google.com/recaptcha/api/siteverify",
data={"secret": secret, "response": token},
).json()
if not result.get("success"):
return False
hostname = result.get("hostname", "")
return hostname == base_domain or hostname.endswith(f".{base_domain}")
# Strict validation (exact match only)
def validate_strict(token, secret, expected_hostname):
result = requests.post(
"https://www.google.com/recaptcha/api/siteverify",
data={"secret": secret, "response": token},
).json()
return result.get("success") and result.get("hostname") == expected_hostname
Otomasyon tarafında dört düzeltme
Düzeltme 1: pageurl'yi hedefle birebir eşitleyin
pageurl, token'ı göndereceğiniz adresin aynısı olmalı.
Şema, alt alan adı ve www varyantı dahil:
# Correct: pageurl matches where you'll submit the token
target_url = "https://www.staging.example.com/qa-login"
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
"pageurl": target_url, # Must match the actual domain
"json": 1,
})
Düzeltme 2: www ve www'siz varyantı tek kurala bağlayın
Kanonik varyantı tahmin etmeyin; tek istek gerçek adresi verir:
from urllib.parse import urlparse
def normalize_url(url):
"""Normalize URL for consistent domain matching."""
parsed = urlparse(url)
# Use exactly what the target site uses
# Check if the site redirects www → non-www or vice versa
return f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
# Test which variant the site uses
response = requests.get("https://staging.example.com/qa-login", allow_redirects=True)
actual_url = response.url # May be https://www.staging.example.com/qa-login after redirect
Düzeltme 3: Yönlendirme zincirinin sonundaki alan adını kullanın
Bazı akışlar oturum açma adımını ayrı bir alan adına taşır:
def get_final_url(url):
"""Follow redirects to find the actual CAPTCHA page domain."""
response = requests.get(url, allow_redirects=True, timeout=15)
return response.url
# Login URL might redirect:
# https://staging.example.com/qa-login → https://auth.staging.example.com/qa-login
final_url = get_final_url("https://staging.example.com/qa-login")
# Use final_url as pageurl for solver
Düzeltme 4: Alan adını widget'ın kendisinden okuyun
Sayfa kaynağındaki reCAPTCHA iframe'i en doğrudan ipucudur:
from bs4 import BeautifulSoup
from urllib.parse import urlparse
def extract_recaptcha_domain(html, page_url):
"""Extract the domain reCAPTCHA uses for token binding."""
soup = BeautifulSoup(html, "html.parser")
# Check for reCAPTCHA iframe
iframe = soup.find("iframe", src=lambda s: s and "recaptcha" in s)
if iframe:
src = iframe.get("src", "")
# The iframe URL may contain the domain parameter
if "domain=" in src:
# Extract domain from iframe URL
pass
# Default: use the page URL's domain
return urlparse(page_url).netloc
Hazır teşhis betiği
Dört kontrolü tek sınıfta toplayın. Betik sırayla:
- Yönlendirme zincirini sonuna kadar izler.
- www ve www'siz varyantı ayrı ayrı dener.
- Kullanmanız gereken
pageurldeğerini yazdırır.
import requests
from urllib.parse import urlparse
class DomainDiagnostic:
"""Diagnose domain verification issues for reCAPTCHA solving."""
def __init__(self, target_url):
self.target_url = target_url
self.issues = []
def check_redirects(self):
"""Check if the URL redirects to a different domain."""
try:
response = requests.get(
self.target_url, allow_redirects=True, timeout=15,
headers={"User-Agent": "Mozilla/5.0 Chrome/120.0.0.0"},
)
final_url = response.url
original_domain = urlparse(self.target_url).netloc
final_domain = urlparse(final_url).netloc
if original_domain != final_domain:
self.issues.append({
"type": "redirect",
"message": f"Redirects from {original_domain} to {final_domain}",
"fix": f"Use pageurl: {final_url}",
})
return final_url
except Exception as e:
self.issues.append({"type": "error", "message": str(e)})
return self.target_url
def check_www_variant(self):
"""Check if www and non-www point to the same content."""
parsed = urlparse(self.target_url)
domain = parsed.netloc
if domain.startswith("www."):
alt_domain = domain[4:]
else:
alt_domain = f"www.{domain}"
alt_url = self.target_url.replace(domain, alt_domain)
try:
alt_response = requests.get(alt_url, allow_redirects=True, timeout=10)
alt_final = urlparse(alt_response.url).netloc
if alt_final != domain and alt_final != alt_domain:
self.issues.append({
"type": "www_redirect",
"message": f"{alt_domain} redirects to {alt_final}",
})
except Exception:
pass
def report(self):
"""Generate diagnostic report."""
final_url = self.check_redirects()
self.check_www_variant()
print(f"Target URL: {self.target_url}")
print(f"Final URL: {final_url}")
print(f"Use as pageurl: {final_url}")
if self.issues:
print("\nIssues found:")
for issue in self.issues:
print(f" [{issue['type']}] {issue['message']}")
if "fix" in issue:
print(f" Fix: {issue['fix']}")
else:
print("\nNo domain issues detected.")
# Usage
diag = DomainDiagnostic("https://staging.example.com/qa-login")
diag.report()
Sık sorulan sorular
pageurl alanına tam URL mi yoksa yalnızca alan adı mı yazmalıyım?
Tam URL yazın. Doğrulanan yalnızca ana makine adıdır, ama tam adres sayfanın doğru yüklenmesini kolaylaştırır.
Sayfa yönlendirme yapıyorsa hangi adresi kullanmalıyım?
Zincirin sonundakini: requests.get(url, allow_redirects=True) çağrısının döndürdüğü response.url doğru sayfadır.
www'li ve www'siz sürümler için ayrı token gerekir mi?
Site katı doğrulama yapıyorsa evet; bunlar iki ayrı ana makine adıdır. Kanonik varyantı bir kez tespit edip akışı ona sabitleyin.
Aynı token'ı ikinci bir istekte yeniden kullanabilir miyim?
Hayır; token'lar tek kullanımlık ve kısa ömürlüdür. Yeniden denemede aynı token'ı göndermeyin, yeni bir çözüm isteği açın.
CaptchaAI hCaptcha alan adı hatalarını da çözüyor mu?
Hayır, hCaptcha desteklenmiyor. Desteklenen türler reCAPTCHA v2/v3, reCAPTCHA Enterprise, Cloudflare Turnstile ve GeeTest v3'tür; CaptchaFox (beta), Friendly Captcha (beta) ve Lemin (beta) beta aşamasındadır.
Özet
Alan adı hatalarının kaynağı hep aynıdır: pageurl ile token'ın gönderildiği adres tutmaz. Üç alışkanlık bu hatayı kapatır:
- Yönlendirme zincirinin sonundaki adresi kullanın.
- www varyantını bir kez netleştirip sabitleyin.
pageurldeğerini ortam değişkeninden okuyun.
CaptchaAI tarafında ek yapılandırma yoktur; token verdiğiniz pageurl'ye bağlanır.