Doğru sitekey ve doğru pageurl ile gönderdiğiniz Google Arama CAPTCHA'sı hâlâ geçersiz token döndürüyorsa, eksik olan neredeyse her zaman tek bir alandır: data-s. Bu, reCAPTCHA widget'ının HTML'ine gömülü, sunucu tarafından üretilen bir oturum token'ıdır ve yalnızca Google'ın kendi mülklerinde karşınıza çıkar. Varsa çözücü isteğinize aynen eklenmeli, yoksa hiç gönderilmemelidir. Öznitelik adı olduğu için data-s Türkçe metinde de çevrilmez.
Kısa karar listesi:
- Sayfa Google'a ait değilse
sitekeyvepageurlyeterlidir. - Widget'ta
data-svarsain.phpisteğine ham hâliyle eklemek zorunludur. - Yoksa alanı hiç koymayın; fazladan alan da çözümü bozar.
data-s hangi sayfalarda çıkar, hangilerinde çıkmaz?
Geliştiricilerin çoğu bu parametreyle hiç karşılaşmaz:
| Yüzey | Var mı? | Notlar |
|---|---|---|
| Google Arama ("olağandışı trafik" sayfası) | Her zaman | Google Arama CAPTCHA'sı için zorunlu |
| YouTube | Bazen | Belirli doğrulama akışlarında |
| Google Play | Bazen | Uygulama listeleme doğrulaması |
| Google Formları | Nadiren | Sınırlı sayıda uygulama |
| reCAPTCHA kullanan diğer siteler | Neredeyse hiç | Standart entegrasyonlar data-s göndermez |
Google'a ait bir mülkle çalışmıyorsanız data-s sizin sorununuz değil: standart üçüncü taraf formlarında sitekey ve pageurl yeterlidir.
Widget içindeki görünümü
<!-- reCAPTCHA widget with data-s parameter -->
<div class="g-recaptcha"
data-sitekey="6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp"
data-s="AB2grfE8_kyMp3XYRuJo5c..."
data-callback="onCaptchaSolved">
</div>
data-s özniteliği, standart data-sitekey'in hemen yanında, aynı <div> üzerinde durur.
| Özellik | Değer |
|---|---|
| Biçim | Base64 kodlu dize, 200–500 karakter |
| Ömür | Tek kullanımlık, o sayfa yüklemesine bağlı |
| Kapsam | Oturuma özel, başka bir yüklemede geçerli değil |
| Zorunluluk | Varsa evet — olmadan çözüm tutmaz |
| Yenilenme | Her sayfa yüklemesinde ve yenilemede yeni değer |
Neden token'ı bozuyor: oturum bağlama mantığı
data-s pratikte bir nonce gibi davranır: doğrulamayı belirli bir sunucu tarafı oturumuna bağlar. Çözücü token'ı üretirken bu değeri kullanmazsa ortaya çıkan g-recaptcha-response beklenen oturumla eşleşmez ve Google isteği "invalid-input-response" ile reddeder. Akış şöyle işler:
User triggers CAPTCHA (e.g., Google flags unusual search traffic)
↓
Google serves a CAPTCHA page with:
- data-sitekey (site key, same for all Google search CAPTCHAs)
- data-s (session token, unique per page load)
↓
reCAPTCHA widget initializes with both parameters
↓
Challenge completion generates a g-recaptcha-response token
↓
Token is submitted alongside the session reference
↓
Google validates token + session binding
↓
If data-s was not used during solving: "invalid-input-response" or silent failure
Asıl tuzak sessiz başarısızlıktır: HTTP tarafında 200 alırsınız, token geçerli görünür, ama form onu reddeder. Süre aşımı hatasıyla oturum uyuşmazlığını karıştırmamak için ikisini loglarda ayrı etiketleyin.
Adım 1: Parametreyi sayfadan çıkarın
Statik olarak sunulan CAPTCHA sayfalarında requests ve BeautifulSoup yeterlidir:
import requests
from bs4 import BeautifulSoup
import re
def extract_recaptcha_params(url):
"""Extract reCAPTCHA parameters including data-s from a page."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
}
response = requests.get(url, headers=headers, timeout=15)
soup = BeautifulSoup(response.text, "html.parser")
# Find reCAPTCHA widget div
widget = soup.find("div", class_="g-recaptcha")
if not widget:
# Try finding by data-sitekey attribute
widget = soup.find(attrs={"data-sitekey": True})
if not widget:
return {"error": "No reCAPTCHA widget found"}
params = {
"sitekey": widget.get("data-sitekey"),
"data_s": widget.get("data-s"),
"callback": widget.get("data-callback"),
"size": widget.get("data-size"),
"has_data_s": widget.get("data-s") is not None,
}
return params
# Example: Google "unusual traffic" page
params = extract_recaptcha_params("https://www.google.com/sorry/index")
print(params)
# {
# "sitekey": "6LfwuyUT...",
# "data_s": "AB2grfE8_kyMp3...",
# "has_data_s": True
# }
Node.js tarafında aynı işi cheerio ile yaparsınız:
const axios = require("axios");
const cheerio = require("cheerio");
async function extractRecaptchaParams(url) {
const { data: html } = await axios.get(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/120.0.0.0 Safari/537.36",
},
timeout: 15000,
});
const $ = cheerio.load(html);
const widget = $(".g-recaptcha, [data-sitekey]").first();
if (widget.length === 0) {
return { error: "No reCAPTCHA widget found" };
}
return {
sitekey: widget.attr("data-sitekey"),
dataS: widget.attr("data-s") || null,
callback: widget.attr("data-callback") || null,
hasDataS: !!widget.attr("data-s"),
};
}
extractRecaptchaParams("https://www.google.com/sorry/index")
.then(console.log);
Widget JavaScript ile sonradan basılıyorsa HTML kaynağında data-s görünmez. Bu durumda Selenium ile canlı DOM'dan okuyun:
from selenium import webdriver
from selenium.webdriver.common.by import By
def extract_data_s_selenium(driver, url):
"""Extract data-s from a dynamically loaded reCAPTCHA page."""
driver.get(url)
# Wait for reCAPTCHA widget to load
import time
time.sleep(3)
try:
widget = driver.find_element(By.CSS_SELECTOR, ".g-recaptcha, [data-sitekey]")
return {
"sitekey": widget.get_attribute("data-sitekey"),
"data_s": widget.get_attribute("data-s"),
}
except Exception:
return {"error": "Widget not found"}
Adım 2: data-s'yi CaptchaAI isteğine ekleyin
Parametre elinizdeyse in.php gövdesine data-s alanı olarak, ham base64 değeriyle koyun. Üzerine ek bir kodlama uygulamayın.
import requests
import time
API_KEY = "YOUR_API_KEY"
# Step 1: Extract parameters from the CAPTCHA page
sitekey = "6LfwuyUTAAAAAOAmoS0fdqijC2PbbdH4kjq62Y1b"
data_s = "AB2grfE8_kyMp3XYRuJo5c..." # Extracted from data-s attribute
page_url = "https://www.google.com/sorry/index?continue=..."
# Step 2: Submit to CaptchaAI WITH data-s
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"data-s": data_s, # Include data-s parameter
"json": 1,
})
task_id = submit.json()["request"]
# Step 3: Poll for result
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
token = result["request"]
print(f"Token: {token[:60]}...")
# Submit this token to the Google CAPTCHA form
break
Node.js karşılığı, res.php'yi periyodik sorgulayan aynı yapıyı kurar:
const axios = require("axios");
async function solveWithDataS(sitekey, dataS, pageUrl) {
const API_KEY = "YOUR_API_KEY";
// Submit with data-s
const { data: submit } = await axios.post(
"https://ocr.captchaai.com/in.php",
new URLSearchParams({
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
"data-s": dataS,
json: 1,
})
);
const taskId = submit.request;
// Poll
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const { data: result } = await axios.get(
"https://ocr.captchaai.com/res.php",
{
params: {
key: API_KEY,
action: "get",
id: taskId,
json: 1,
},
}
);
if (result.status === 1) {
return result.request;
}
}
throw new Error("Timeout");
}
method her zaman userrecaptcha kalır; data-s yeni bir yöntem değil, aynı isteğe eklenen tek bir alandır. Mevcut reCAPTCHA v2 entegrasyonunuzu baştan yazmazsınız.
Adım 3: Koşullu ekleme mantığını tek yerde toplayın
Aynı kod hem data-s'li hem data-s'siz sayfalarla çalışacaksa "varsa ekle, yoksa ekleme" kararını tek bir yardımcı sınıfta toplayın:
import requests
from bs4 import BeautifulSoup
class RecaptchaExtractor:
"""Extract reCAPTCHA parameters from any page."""
def __init__(self, url, session=None):
self.url = url
self.session = session or requests.Session()
self.params = None
def extract(self):
"""Extract sitekey, data-s, and other parameters."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
}
response = self.session.get(self.url, headers=headers, timeout=15)
soup = BeautifulSoup(response.text, "html.parser")
widget = soup.find(attrs={"data-sitekey": True})
if not widget:
raise ValueError("No reCAPTCHA widget found on page")
self.params = {
"sitekey": widget["data-sitekey"],
"pageurl": self.url,
}
# Include data-s only if present
data_s = widget.get("data-s")
if data_s:
self.params["data-s"] = data_s
return self.params
def build_solver_payload(self, api_key):
"""Build CaptchaAI submission payload with correct parameters."""
if not self.params:
self.extract()
payload = {
"key": api_key,
"method": "userrecaptcha",
"googlekey": self.params["sitekey"],
"pageurl": self.params["pageurl"],
"json": 1,
}
# Only include data-s when it exists
if "data-s" in self.params:
payload["data-s"] = self.params["data-s"]
return payload
# Usage
extractor = RecaptchaExtractor("https://www.google.com/sorry/index?continue=...")
payload = extractor.build_solver_payload("YOUR_API_KEY")
# payload includes data-s only when present on the page
Üretimde en sık görülen beş hata
| Hata | Belirti | Düzeltme |
|---|---|---|
Var olduğu hâlde data-s gönderilmiyor |
Token sessizce reddediliyor | Göndermeden önce özniteliği her seferinde kontrol edin |
Yokken data-s ekleniyor |
Çözüm hatası veya reddedilen istek | Yalnızca widget'ta gerçekten varsa ekleyin |
Aynı data-s birden çok sayfada kullanılıyor |
Geçersiz token | Her sayfa yüklemesinde yeniden çıkarın |
| Değer URL kodlamasından geçiriliyor | Bozuk parametre | Ham base64 değerini olduğu gibi iletin |
Sayfa dakikalar önce yüklenmiş, data-s bayat |
Token uyuşmazlığı | Çıkarma ile gönderme arasını kısa tutun |
Somut bir senaryo: Europe/Istanbul saatiyle gece çalışan bir e-ticaret QA kuyruğu Google Arama sonuçlarını doğruluyor ve "olağandışı trafik" sayfasına düşüyor. Görevi kuyruğa alıp beş dakika sonra çözücüye yollarsanız data-s çoktan bayatlar — kuyruğa yalnızca hedef URL'yi koyun, sayfayı worker'ın kendisi çeksin. Eşzamanlılık arttıkça planlar thread sayısına göre ölçeklenir: BASIC ($15/ay, 5 thread) tekil işler, ADVANCE ($90/ay, 50 thread) paralel kuyruklar için. Fiyatlar USD'dir, aylık maliyetiniz kurdan bağımsızdır.
Sık sorulan sorular
data-s ile sitekey arasındaki fark nedir?
sitekey sitenin sabit genel anahtarıdır ve tüm Google Arama CAPTCHA'larında aynıdır; yapılandırmanıza sabit yazabilirsiniz. data-s ise her yüklemede değişen, oturuma bağlı geçici bir değerdir. Biri siteyi, diğeri o anki oturumu temsil eder.
Sayfa kaynağında data-s göremiyorum, hata mı yaptım?
Muhtemelen hayır. Widget JavaScript ile basılıyorsa ham HTML data-s içermez. Selenium ya da Playwright ile canlı DOM'dan get_attribute("data-s") çağırın; yine boşsa o sayfada gerçekten yoktur.
data-s'yi Turnstile veya GeeTest isteklerinde kullanabilir miyim?
Hayır, data-s yalnızca reCAPTCHA ailesine özgüdür. Cloudflare Turnstile ve GeeTest v3 kendi method değerleri ve parametre setleriyle çalışır; bu isteklere data-s eklemek gönderiyi bozar.
Aynı sayfada birden fazla widget varsa hangi data-s'yi almalıyım?
Token'ı göndereceğiniz widget'ın kendi <div> öğesinden okuyun; data-s widget başına bağlanır, ilk eşleşmeyi körlemesine almak yanlış değeri seçtirir. Seçiciyi data-sitekey değerine göre daraltın.
Değeri loglara yazmak sakıncalı mı?
Sorun giderirken ilk 20 karakter yeterlidir. Değer kısa ömürlü olsa da bir oturuma bağlıdır; KVKK kapsamındaki akışlarda tam değeri kalıcı loglara yazmayın.
Özet
data-s, reCAPTCHA widget'ına gömülü bir oturum bağlama token'ıdır ve pratikte yalnızca Google'a ait mülklerde görünür. Entegrasyonunuzda uygulayacağınız kural dört satıra sığar:
- Göndermeden önce widget'ta
data-sözniteliği var mı, her seferinde bakın. - Varsa ham base64 değerini olduğu gibi CaptchaAI isteğine ekleyin.
- Yoksa alanı hiç göndermeyin.
- Değeri önbelleğe almayın; her sayfa yüklemesinde yeniden çıkarın.