移动端浏览器自动化处理验证码,接口逻辑和桌面端一样:拿 sitekey、提交给 CaptchaAI、轮询拿 token、写回表单。真正的难点在移动端特有的坑——响应式布局让组件渲染方式不同,触屏事件替代鼠标事件,部分网站还按 User-Agent 下发不同配置。典型场景是某跨境电商或出海 SaaS 的移动端页面用 reCAPTCHA v2 保护表单提交,网站按 User-Agent 单独渲染验证码布局,你需要在移动浏览器上下文里完成识别并提交表单。
国内团队做这类自动化常多一层麻烦:reCAPTCHA 依赖的脚本国内网络不一定稳定,组件可能渲染很慢甚至渲染不出来——这和 CaptchaAI 能不能识别是两回事,CaptchaAI 只需要 sitekey 和 pageurl 即可完成识别;组件没渲染出来则无从提取 sitekey,建议把脚本部署在网络稳定的环境里跑。国内站点多用 GeeTest(极验)等本土方案,reCAPTCHA 更常见于面向海外用户的产品。本文用 Playwright 移动模拟和 Selenium + Chrome for Android 两种方案,演示如何拿到 reCAPTCHA v2 识别结果并完成表单提交。
方法一:Playwright 移动模拟(Python)
Playwright 自带 iPhone、Pixel 设备预设,能模拟真机视口、User-Agent 和触屏事件,不用连接真实设备:
# playwright_mobile_captcha.py
import asyncio
import httpx
from playwright.async_api import async_playwright
API_KEY = "YOUR_API_KEY"
async def solve_recaptcha(sitekey: str, pageurl: str) -> str:
"""Submit reCAPTCHA v2 to CaptchaAI and poll for result."""
async with httpx.AsyncClient(timeout=180) as client:
# Submit task
resp = await client.get(
"https://ocr.captchaai.com/in.php",
params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": "1",
},
)
result = resp.json()
if result["status"] != 1:
raise Exception(f"Submit failed: {result['request']}")
task_id = result["request"]
# Poll for result
for _ in range(30):
await asyncio.sleep(5)
poll = await client.get(
"https://ocr.captchaai.com/res.php",
params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": "1",
},
)
poll_result = poll.json()
if poll_result["status"] == 1:
return poll_result["request"]
if poll_result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Solve failed: {poll_result['request']}")
raise Exception("Polling timeout")
async def main():
async with async_playwright() as p:
# Launch with iPhone 13 emulation
iphone = p.devices["iPhone 13"]
browser = await p.chromium.launch(headless=False)
context = await browser.new_context(**iphone)
page = await context.new_page()
await page.goto("https://example.com/mobile-form")
await page.wait_for_selector(".g-recaptcha", timeout=10000)
# Extract sitekey
sitekey = await page.get_attribute(".g-recaptcha", "data-sitekey")
pageurl = page.url
print(f"Found sitekey: {sitekey}")
# Solve via CaptchaAI
token = await solve_recaptcha(sitekey, pageurl)
print(f"Token received: {token[:50]}...")
# Inject token
await page.evaluate(f"""
document.getElementById('g-recaptcha-response').value = '{token}';
document.getElementById('g-recaptcha-response').style.display = '';
""")
# Trigger callback if it exists
await page.evaluate(f"""
try {{
const clients = ___grecaptcha_cfg.clients;
Object.keys(clients).forEach(k => {{
Object.keys(clients[k]).forEach(j => {{
if (clients[k][j] && clients[k][j].callback) {{
clients[k][j].callback('{token}');
}}
}});
}});
}} catch(e) {{}}
""")
# Submit form
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
print("Form submitted successfully")
await browser.close()
asyncio.run(main())
脚本用 iPhone 13 预设打开页面、读出 sitekey 并提交给 CaptchaAI;拿到 token 后写回 g-recaptcha-response 字段、触发回调,再提交表单。
方法二:Selenium 移动模拟(Node.js)
Node.js 技术栈可用 Selenium 配合 Chrome DevTools Protocol 的移动模拟,设置好设备参数后页面会按移动端渲染:
// selenium_mobile_captcha.js
const { Builder, By, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
async function solveCaptcha(sitekey, pageurl) {
// Submit task
const submitResp = await axios.get('https://ocr.captchaai.com/in.php', {
params: {
key: API_KEY,
method: 'userrecaptcha',
googlekey: sitekey,
pageurl: pageurl,
json: '1',
},
});
if (submitResp.data.status !== 1) {
throw new Error(`Submit failed: ${submitResp.data.request}`);
}
const taskId = submitResp.data.request;
// Poll for result
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 5000));
const pollResp = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: API_KEY, action: 'get', id: taskId, json: '1' },
});
if (pollResp.data.status === 1) return pollResp.data.request;
if (pollResp.data.request !== 'CAPCHA_NOT_READY') {
throw new Error(`Solve failed: ${pollResp.data.request}`);
}
}
throw new Error('Polling timeout');
}
async function main() {
// Configure mobile emulation
const mobileEmulation = {
deviceMetrics: { width: 390, height: 844, pixelRatio: 3.0 },
userAgent:
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) ' +
'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
};
const options = new chrome.Options();
options.setMobileEmulation(mobileEmulation);
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
try {
await driver.get('https://example.com/mobile-form');
await driver.wait(until.elementLocated(By.css('.g-recaptcha')), 10000);
// Extract sitekey
const captchaEl = await driver.findElement(By.css('.g-recaptcha'));
const sitekey = await captchaEl.getAttribute('data-sitekey');
const pageurl = await driver.getCurrentUrl();
console.log(`Sitekey: ${sitekey}`);
// Solve CAPTCHA
const token = await solveCaptcha(sitekey, pageurl);
console.log(`Token: ${token.substring(0, 50)}...`);
// Inject token
await driver.executeScript(`
document.getElementById('g-recaptcha-response').value = arguments[0];
`, token);
// Submit form
await driver.findElement(By.css('button[type="submit"]')).click();
console.log('Form submitted');
} finally {
await driver.quit();
}
}
main().catch(console.error);
逻辑和 Playwright 版本一致:提取 sitekey、提交、拿 token 写回 g-recaptcha-response 文本域,再提交表单。
常见问题
移动端和桌面端相比,验证码要多留意哪些差异?
主要是四点:User-Agent(部分站点按设备下发不同配置)、视口尺寸(组件渲染方式可能不同)、交互事件(触屏代替鼠标,部分验证码会校验交互类型)、网络质量(4G/5G 建议把超时设置得更宽松)。
移动模拟环境下验证码组件为什么渲染不出来?
多数是站点通过 navigator.platform、屏幕特征识别出模拟环境。先确认设备预设是否完整,再检查页面是否有额外检测逻辑。
CaptchaAI 需要知道这是移动端验证码吗?
不需要。CaptchaAI 根据 sitekey 和 pageurl 完成识别,移动端还是桌面端不影响识别流程。
移动端场景下,识别耗时会不会变长?
不会,识别耗时取决于验证码类型和站点难度,和请求来自移动模拟还是桌面环境无关。移动网络较慢时建议把超时设置得更宽松,这属于网络层面,和识别耗时是两回事。
遇到具体报错,可以对照下面排查:
- 验证码组件不渲染——站点通过 navigator.platform 识别出模拟环境,在 DevTools Protocol 里设置 platform 覆盖值。
- 找不到
g-recaptcha-response文本域——移动端布局渲染方式不同,按 name 属性查找而不是按 id。 - token 提交成功,表单还是失败——服务端在校验 User-Agent 一致性,确保识别请求和表单提交用同一个 User-Agent。
- 模拟环境下页面加载很慢——页面资源较重,用
--disable-images一类参数加速加载。
把移动端验证码识别接入你的自动化流程,可以从这几篇继续读:如何通过 API 处理 reCAPTCHA v2 回调、Zapier 验证码无代码自动化、reCAPTCHA v2 与 Turnstile 同站点处理、Appium 移动 App 自动化中的验证码处理、React Native WebView 验证码识别,以及从页面源码中提取 reCAPTCHA 参数。
获取 CaptchaAI API Key,开始把这套流程接入你现有的移动自动化技术栈。