Script của bạn gửi đúng sitekey và pageurl tới CaptchaAI, nhưng reCAPTCHA trên trang "lưu lượng truy cập bất thường" của Google Tìm kiếm vẫn trả về token không hợp lệ? Rất có thể trang đó còn thêm một thuộc tính nữa trên widget — data-s — và request của bạn đang thiếu nó. data-s là token gắn với phiên, chỉ xuất hiện trên một số triển khai reCAPTCHA nhất định (chủ yếu là sản phẩm của Google), nhưng khi nó có mặt thì bắt buộc phải trích xuất và đưa vào request giải, nếu không sẽ luôn nhận lỗi hoặc token vô hiệu. Bài này đi thẳng vào việc data-s là gì, xuất hiện ở đâu, cách lấy nó từ trang đích và cách truyền đúng cho CaptchaAI.
Kiểm tra nhanh: mở DevTools trên trang CAPTCHA, tìm
<div class="g-recaptcha">— nếu thấy thuộc tínhdata-sbên cạnhdata-sitekey, request giải của bạn bắt buộc phải mang theo nó.
data-s là tham số gì trong reCAPTCHA?
data-s là token phiên do server của Google tạo ra và nhúng thẳng vào HTML của widget reCAPTCHA. Nó gắn thử thách CAPTCHA hiện tại với một phiên cụ thể phía server, để token giải xong không thể tái sử dụng cho một phiên khác. Ba điều cần nhớ về nó:
- Định dạng: chuỗi mã hóa Base64, dài 200–500 ký tự.
- Vòng đời: dùng một lần, gắn với đúng lần tải trang hiện tại — không tái sử dụng được ở lần tải khác.
- Bắt buộc theo điều kiện: chỉ bắt buộc khi widget thực sự có thuộc tính này; thiếu nó thì giải thất bại, nhưng phần lớn widget reCAPTCHA không có nó.
Vị trí của data-s trong HTML
<!-- reCAPTCHA widget with data-s parameter -->
<div class="g-recaptcha"
data-sitekey="6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp"
data-s="AB2grfE8_kyMp3XYRuJo5c..."
data-callback="onCaptchaSolved">
</div>
Thuộc tính data-s nằm ngay cạnh data-sitekey quen thuộc, trên cùng phần tử <div> của widget. Giá trị này được sinh mới mỗi lần trang được tải hoặc refresh, nên không thể lưu lại dùng cho lần sau.
Cơ chế hoạt động của data-s
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
Về bản chất, data-s hoạt động như một nonce: nó buộc thử thách CAPTCHA phải khớp với đúng một phiên phía server. Solver phải dùng giá trị này khi tạo token, để token trả về khớp đúng phiên mà Google đang mong đợi — sai hoặc thiếu là bị từ chối.
Những lỗi thường gặp khi xử lý data-s
- Bỏ qua data-s khi widget có sẵn → xác thực token thất bại âm thầm. Luôn kiểm tra thuộc tính này trước khi gửi request.
- Vẫn gửi data-s dù widget không có → lỗi giải hoặc request bị từ chối. Chỉ đưa vào khi thuộc tính thực sự tồn tại trên widget.
- Dùng lại data-s cũ ở lần tải trang mới → token không hợp lệ. Trích xuất giá trị mới cho từng lần tải trang.
- URL-encode giá trị data-s không đúng cách → tham số sai định dạng. Truyền nguyên giá trị base64, không encode thêm.
- Dùng data-s đã "nguội" (trang tải từ vài phút trước) → token không khớp phiên. Trích xuất ngay trước khi gửi cho solver.
data-s xuất hiện trên những trang nào?
data-s KHÔNG có mặt trên đa số triển khai reCAPTCHA. Xếp theo mức độ xuất hiện:
- Luôn luôn — Google Tìm kiếm, trên trang cảnh báo lưu lượng bất thường. Bắt buộc để giải CAPTCHA của Google Tìm kiếm.
- Thỉnh thoảng — YouTube (một số luồng xác minh) và Google Play (xác minh khi đăng ứng dụng).
- Hiếm khi — Google Forms, chỉ ở một số triển khai giới hạn.
- Gần như không bao giờ — website bên thứ ba dùng reCAPTCHA; tích hợp chuẩn không dùng
data-s.
Nếu bạn không làm việc trực tiếp với các sản phẩm của Google, gần như không cần bận tâm đến data-s. Nhưng nếu solver liên tục trả token không hợp lệ trên CAPTCHA của Google Tìm kiếm, thiếu data-s là nguyên nhân phổ biến nhất.
Đây cũng là tình huống hay gặp ở các đội QA và outsourcing tại TP.HCM, Hà Nội khi chạy script rank-tracking hoặc theo dõi kết quả tìm kiếm Google theo lịch: khối lượng request lớn dễ khiến Google gắn cờ "unusual traffic" và bật CAPTCHA có data-s, trong khi các CAPTCHA reCAPTCHA khác trong cùng hệ thống (form đăng ký, checkout nội bộ...) vẫn hoạt động bình thường vì không dùng thuộc tính này.
Cách trích xuất data-s từ trang đích
Bằng Python (requests + BeautifulSoup)
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
# }
Bằng Node.js (axios + cheerio) hoặc Selenium khi trang render động
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);
Nếu widget được JavaScript inject sau khi trang tải xong, requests thuần sẽ không thấy nó — cần một trình duyệt thật, ví dụ Selenium:
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"}
Gửi data-s tới CaptchaAI để giải reCAPTCHA
Khi widget có data-s, đưa nó vào request gửi tới CaptchaAI như một field bổ sung — phần còn lại của flow (gửi task, nhận ID, polling, lấy token) không đổi:
Python
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
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");
}
Class trích xuất data-s dùng lại được
Đóng gói logic trích xuất thành một class giúp pipeline gọn hơn khi cần chạy trên nhiều loại trang cùng lúc:
- Dùng chung một class cho cả trang có
data-s(Google Tìm kiếm) và trang không có (đa số site bên thứ ba). - Tự động bỏ qua field
data-strong payload nếu widget không có thuộc tính này, tránh lỗi request bị từ chối. - Dễ tái sử dụng trong script rank-tracking hoặc job automation chạy theo lịch.
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
Câu hỏi thường gặp
Puppeteer hoặc Playwright có tự lấy data-s giúp mình không, hay phải parse thủ công?
Có, đọc trực tiếp thuộc tính DOM, không cần parse HTML thô như requests:
- Puppeteer:
page.$eval(".g-recaptcha", el => el.getAttribute("data-s")) - Playwright:
locator.getAttribute("data-s")
Gọn hơn khi widget được JavaScript render sau khi trang tải, tương tự Selenium ở trên nhưng hợp với pipeline đã dùng sẵn hai tool này.
data-s có bắt buộc phải gửi trong mọi request reCAPTCHA tới CaptchaAI không?
Không. data-s chỉ tồn tại trên một nhóm nhỏ triển khai reCAPTCHA, chủ yếu là các sản phẩm của Google. Với hầu hết website bên thứ ba dùng reCAPTCHA, bạn chỉ cần sitekey và pageurl như bình thường. Luôn kiểm tra widget có thuộc tính data-s hay không trước khi quyết định thêm nó vào request.
data-s có phải thông tin nhạy cảm cần che khi ghi log hoặc debug không?
Bản thân data-s không phải bí mật tài khoản hay credential, nhưng nó gắn với một phiên cụ thể của Google nên không nên log tràn lan hoặc lưu lâu dài trong hệ thống theo dõi — coi nó như dữ liệu tạm thời, chỉ tồn tại đủ lâu để dùng cho một lần giải rồi bỏ đi.
Có thể tái sử dụng data-s cho lần giải tiếp theo để tiết kiệm một lượt trích xuất không?
Không. Giá trị data-s gắn chặt với đúng một lần tải trang. Mỗi lần trang CAPTCHA được tải lại, Google sinh ra một data-s mới hoàn toàn khác. Bắt buộc phải trích xuất giá trị mới ngay trước mỗi lần gửi request giải, không thể cache để dùng lại.
Ngoài Google Tìm kiếm, nên chủ động kiểm tra data-s ở những tình huống nào?
Bất cứ khi nào solver báo lỗi token trên một trang thuộc hệ sinh thái Google, trong khi cùng code chạy tốt trên site bên thứ ba khác:
- YouTube, ở một số luồng xác minh.
- Google Play, khi xác minh đăng ứng dụng.
- Một số luồng của Google Forms.
Đó là dấu hiệu widget đang có data-s mà code chưa xử lý, chứ không phải lỗi ở sitekey hay pageurl.
Tóm tắt
data-s là token gắn với phiên, chỉ xuất hiện trên một số triển khai reCAPTCHA nhất định — chủ yếu là sản phẩm của Google. Quy trình xử lý gói gọn trong ba bước:
- Kiểm tra widget có thuộc tính
data-shay không trước khi build request. - Nếu có, trích xuất giá trị mới nhất và đưa vào request gửi tới CaptchaAI cùng
sitekey,pageurl. - Nếu không có, bỏ qua field này — đa số site bên thứ ba không cần đến nó, riêng CAPTCHA "lưu lượng truy cập bất thường" của Google Tìm kiếm thì luôn bắt buộc.
Bài viết liên quan
- Cách giải callback của reCAPTCHA v2 bằng API
- Xử lý reCAPTCHA v2 và Turnstile trên cùng một site
- Vòng đời của token reCAPTCHA giải thích chi tiết