一句话结论:扭曲字符图 + 一个输入框 = 文本验证码,走 OCR 接口就能识别;加载了第三方脚本、弹出九宫格点红绿灯 = 图像验证码,需要专门的求解器。 判断错了,你会在一个不存在的 sitekey 上耗掉半天。下面先给对比结论,再讲原理、检测和选型。
先看硬指标:两类验证码的正面对比
| 维度 | 文本验证码 | 图像验证码 |
|---|---|---|
| 安全强度 | 低(OCR 识别率高) | 高(需物体识别) |
| 用户解决时间 | 5–10 秒 | 10–30 秒 |
| 人类失败率 | 15–20% | 8–15% |
| 无障碍 | 视障用户困难 | 视障用户几乎不可用 |
| 移动端 | 一般(字符小) | 较好(点选) |
| 自动化难度 | 低(OCR) | 高(图像分类) |
| 部署成本 | 免费(自建) | 免费到付费(第三方) |
| 自动识别成本 | 每 1,000 次约 $0.50–$1.00 | 每 1,000 次约 $1.50–$3.00 |
| 数据采集 | 无 | 可能训练 ML 模型 |
| 接入工作量 | 小(服务端生成) | 中(JavaScript SDK) |
表中价格是按次计费市场的参考区间,实际报价以各服务商公开页面为准。CaptchaAI 不按次计费,而是按并发线程计价、套餐内不限识别次数:BASIC $15/月(5 线程)、STANDARD $30(15 线程)、ADVANCE $90(50 线程),最高到 VIP-3 $7,500(5,000 线程)。混合负载要估的是并发量。
文本验证码的原理与常见干扰手段
文本验证码把随机字符渲染成图片,用户读出来填进输入框,服务端做一次字符串比对(通常忽略大小写)。整套逻辑服务端就能实现,不依赖外部服务——这也是它在老系统和自建后台里活到今天的原因。常见干扰手段:
| 技术 | 目的 |
|---|---|
| 字符扭曲 | 让简单 OCR 失效 |
| 背景噪点 | 文字后加线条、点或渐变 |
| 字符粘连 | 相邻字母重叠,阻止分割 |
| 字体随机 | 每次换字体和字号 |
| 颜色扰动 | 随机化前景与背景配色 |
生成与校验流程:
Server generates random string (e.g., "X7mK9p")
↓
Applies distortion: warping, noise, overlap
↓
Renders as PNG/JPEG image
↓
User reads characters, types into input field
↓
Server compares input against stored string (case-insensitive usually)
干扰强度和可读性此消彼长:扭曲到 OCR 认不出,真人失败率也会上去。
图像验证码的原理与常见形态
图像验证码给出一组图片和提示语,让用户点出符合类别的那几张,判断依据是选择是否与标注数据一致。
| 形态 | 挑战内容 | 代表提供商 |
|---|---|---|
| 九宫格选择 | “选出所有含红绿灯的方块” | reCAPTCHA v2 |
| 图片标注 | “点击所有包含公交车的图片” | hCaptcha |
| 物体计数 | “图中有几辆自行车” | 自研 |
| 旋转校正 | “把图片转正” | FunCaptcha |
流程:
Server selects images from a labeled dataset
↓
Presents 3×3 or 4×4 grid with a text prompt
↓
User clicks matching images
↓
Server validates selections against ground truth
↓
If fading images: new images load in place of selected ones (multi-round)
国内站点上遇到的“图像验证码”,多半不是 reCAPTCHA。 主流是 GeeTest(极验)的滑块与点选、网易易盾、腾讯防水墙、阿里云验证码;reCAPTCHA 多见于海外站点,脚本托管在 Google 域名下,国内联调常卡在加载这一步。所以动手前先跑一遍检测。
用代码判断页面上是哪一种
规则很简单:先查第三方脚本特征,命中即图像验证码;没命中再看有没有“验证码图片 + 输入框”这对组合。 顺序不能反——接了 reCAPTCHA 的页面同样有带 captcha 的输入框。
Python 检测脚本
import requests
from bs4 import BeautifulSoup
import re
def detect_captcha_type(url):
"""Detect whether page uses text or image CAPTCHA."""
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
html = response.text
result = {"text_captcha": False, "image_captcha": False, "provider": None}
# Check for reCAPTCHA (image-based)
if "google.com/recaptcha" in html or "g-recaptcha" in html:
result["image_captcha"] = True
result["provider"] = "reCAPTCHA"
return result
# Check for hCaptcha (image-based)
if "hcaptcha.com" in html or "h-captcha" in html:
result["image_captcha"] = True
result["provider"] = "hCaptcha"
return result
# Check for text CAPTCHA patterns
captcha_images = soup.find_all("img", attrs={
"src": re.compile(r"captcha", re.I)
})
captcha_inputs = soup.find_all("input", attrs={
"name": re.compile(r"captcha", re.I)
})
if captcha_images and captcha_inputs:
# Image with text input = text CAPTCHA
result["text_captcha"] = True
result["provider"] = "custom text CAPTCHA"
return result
# Check for FunCaptcha (image-based rotation)
if "funcaptcha" in html.lower() or "arkoselabs" in html.lower():
result["image_captcha"] = True
result["provider"] = "FunCaptcha"
return result
return result
captcha = detect_captcha_type("https://staging.example.com/qa-login")
print(captcha)
Node.js 检测脚本
const axios = require("axios");
const cheerio = require("cheerio");
async function detectCaptchaType(url) {
const { data: html } = await axios.get(url, { timeout: 10000 });
const $ = cheerio.load(html);
const result = { textCaptcha: false, imageCaptcha: false, provider: null };
// reCAPTCHA detection
if (html.includes("google.com/recaptcha") || html.includes("g-recaptcha")) {
result.imageCaptcha = true;
result.provider = "reCAPTCHA";
return result;
}
// hCaptcha detection
if (html.includes("hcaptcha.com") || html.includes("h-captcha")) {
result.imageCaptcha = true;
result.provider = "hCaptcha";
return result;
}
// Text CAPTCHA: image + input with "captcha" in name/class
const captchaImgs = $("img[src*='captcha' i]").length;
const captchaInputs = $("input[name*='captcha' i]").length;
if (captchaImgs > 0 && captchaInputs > 0) {
result.textCaptcha = true;
result.provider = "custom text CAPTCHA";
return result;
}
return result;
}
detectCaptchaType("https://staging.example.com/qa-login").then(console.log);
两段代码只做静态 HTML 匹配。页面若由前端框架渲染,骨架里可能没有验证码节点,需改用 Selenium 或 Playwright 取渲染后的 DOM。
用 CaptchaAI 识别文本验证码
文本验证码本质是一张图,走图像 OCR 接口即可:取图、base64 编码、提交 in.php,再轮询 res.php。
import requests
import base64
import time
API_KEY = "YOUR_API_KEY"
# Get the CAPTCHA image
captcha_url = "https://example.com/captcha.png"
image_data = requests.get(captcha_url).content
b64 = base64.b64encode(image_data).decode()
# Submit to CaptchaAI
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "base64",
"body": b64,
"json": 1,
})
task_id = submit.json()["request"]
# Poll for result
for _ in range(30):
time.sleep(3)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if resp.get("status") == 1:
print(f"CAPTCHA text: {resp['request']}")
break
CaptchaAI 的图像 OCR 支持 27,500 多种图片验证码类型,涵盖扭曲文本、数学算式和字符识别。调用方式与快速上手流程一致,method 换成 base64 即可。
图像验证码要按类型走对应求解器。CaptchaAI 正式支持 reCAPTCHA v2(含隐形与 Enterprise 变体)、reCAPTCHA v3、GeeTest v3、Cloudflare Turnstile 与 Challenge、图片/OCR、九宫格图片和 BLS,另有 CaptchaFox(测试版)、Friendly Captcha(测试版)、Lemin(测试版)。hCaptcha 与 FunCaptcha(Arkose Labs)不支持,GeeTest v4 尚未上线(官方口径为即将支持)。 检测脚本仍匹配这两者,是因为识别类型和识别结果是两件事。各类型提交参数不同,接入前按文档核对 method 与必填字段。
站在防护方:这两种还该不该用
如果你是给自己的站点选方案:
- 留着文本验证码:需要零依赖、完全自托管,机器人流量也不大,例如内部后台登录页。
- 换成图像验证码:持续遭遇自动化流量,表单背后是登录、支付等敏感操作。
- 两种都不用:面向普通用户的表单更适合隐形方案——reCAPTCHA v3 和 Cloudflare Turnstile 在后台打分,用户无感知。
合规提醒:数据采集只抓你有权限抓的数据,遵守 robots 协议与 PIPL 等法规要求。
常见问题
国内站点为什么很少见到九宫格点红绿灯?
国内主要用 GeeTest(极验)、网易易盾、腾讯防水墙、阿里云验证码,形态以滑块和点选文字为主;reCAPTCHA 依赖 Google 域名下的脚本,国内访问不稳定。其中 CaptchaAI 支持 GeeTest v3。
文本验证码现在还拦得住机器人吗?
基本拦不住了。现代 OCR 对标准文本验证码识别准确率很高;扭曲到能压低机器识别率的程度,真人失败率也会上升,结果常是挡掉的真实用户比机器人还多。
识别一张图片验证码大概要多久?
图像 OCR 类任务通常几秒内返回,取决于图片复杂度和排队情况。按上面代码轮询即可:提交后隔几秒查一次 res.php,设好重试上限和超时。以上为参考值,建议在自有环境实测。
一个项目里同时有文本和图像验证码,要买两份套餐吗?
不需要。CaptchaAI 按并发线程计价,同一个 API Key 可提交不同类型的任务,套餐内不限次数,也不按类型加价。你只要估峰值并发,挑一档即可。
小结
文本验证码部署成本低,OCR 就能识别;图像验证码自动化难度高得多,代价是用户多花时间点图。写自动化先跑检测判准类型,文本类送 CaptchaAI 的图像 OCR,图像类按类型选求解器。做防护方趋势也很明确:能上隐形验证码,就别再让用户认字点图。