reCAPTCHA validation failed:常见原因与修复方法

当网站无法确认表单是否由真人提交时,就可能显示 “reCAPTCHA validation failed”,并拒绝此次提交。无论你勾选了“我不是机器人”,还是 reCAPTCHA 在后台完成了无感验证,都可能出现这种情况。Google 返回了验证失败的结果,表单也就无法继续提交。
如果你只是想注册或登录,原因通常出在本地环境,例如广告拦截器干扰,或页面打开太久。如果是你自己的网站无法通过 reCAPTCHA 验证,则更可能是 reCAPTCHA 配置或表单代码有问题。
要点速览
- 服务器返回的错误码通常能说明原因,先查看错误码。如果没有错误码,依次检查 secret key、域名列表,以及 token 的生成时间。
- token 只有两分钟有效期,而且 Google 只允许验证一次。使用 v3 时,应在访客点击 Submit 时调用 execute(),而不是在页面加载时调用。
- 如果验证组件没有显示,检查广告拦截器、CSP 规则和防火墙。
- “captcha score is not above the threshold” 与网站或插件设置的 threshold 有关,并不是 Google 设置了这个阈值。
- Enterprise assessment 能更详细地解释 token 验证失败的原因。siteverify 将过期和重复使用的 token 统一归为 timeout-or-duplicate,而 Enterprise 分别使用 EXPIRED 和 DUPE。
reCAPTCHA validation failed 是什么意思?
验证流程在某个环节出了问题,可能是访客的浏览器,也可能是你的网站服务器。访客看到的报错可能相同,但排查位置并不一样。
客户端故障:组件未加载,或未通过验证挑战
如果问题出在浏览器,token 就不会生成。可能是组件根本没有加载,这也是用户说 reCAPTCHA 无法使用时最常见的情况;也可能是访客未能通过图片验证。两种情况下,后端都拿不到 token:请求要么没有发出,要么携带的 g-recaptcha-response 字段为空。Invisible reCAPTCHA 更难排查,因为页面上没有复选框,访客不容易察觉验证出了问题。如果没有适当的错误处理,表单看起来就像没有响应。
服务器端故障:success: false 和错误码
如果表单显示笼统的 “Error verifying reCAPTCHA”,token 很可能已经从浏览器发出,但 Google 在服务器提交验证后拒绝了它。具体原因可以从 siteverify 的响应中查看:
{
"success": false,
"error-codes": ["timeout-or-duplicate"]
}基于 score 的密钥也可能返回 success: true,但 score 低于网站设置的 threshold。这时,拒绝请求的是你的网站代码,而不是 Google。

基本概念:site key、secret key、token、score 和 threshold
Site key(站点密钥)。密钥对中的公开部分,可以在页面的 HTML 或 JavaScript 中看到。
Secret key(私密密钥)。密钥对中的私密部分,只应由后端发送给 siteverify。在 Google Cloud 中,它标为 “legacy secret key”。
Token(令牌)。reCAPTCHA 完成验证后返回的字符串,在 v2 中通过 g-recaptcha-response 传递。Google 仅在两分钟内接受该 token,而且只允许验证一次。
Score(评分)。v3 和基于评分的 Enterprise 密钥返回的数值,范围为 0.0 到 1.0。分数越高,风险越低。
Threshold(阈值)。网站接受的最低 score,由你设置,而不是由 Google 替你决定。
reCAPTCHA 错误码速查
错误码来自 Google 的 siteverify 响应或 Enterprise assessment。因 score 过低而拒绝请求,则是你自己的阈值判断逻辑产生的结果。
| 错误码或现象 | 出现位置 | 原因 | 修复方法 |
|---|---|---|---|
| missing-input-secret | siteverify | 未发送 secret 参数 | 检查 secret key 是否正确加载 |
| invalid-input-secret | siteverify | secret key 错误,或误填了 site key | 使用与 site key 配套的 secret key |
| missing-input-response | siteverify | 未发送 token,或防火墙规则移除了该字段 | 确认 g-recaptcha-response 能传到后端 |
| invalid-input-response | siteverify | token 格式错误、被截断,或由其他 site key 生成 | 原样传递 token,不做修改 |
| bad-request | siteverify | Google 无法解析请求 | 通过 POST 请求,以表单字段形式发送 secret 和 response |
| timeout-or-duplicate | siteverify | token 已生成超过两分钟,或已经验证过 | 在提交时获取 token,并且只验证一次 |
| browser-error(Enterprise 中为 BROWSER_ERROR) | 仅出现在 Enterprise 的 invalidReason 中 | 可重试的浏览器错误,例如网络故障 | 再次调用 execute(),然后检查拦截器、CSP 和网络 |
| v3 score 低于网站设置的 threshold | v3 的 score 或 Enterprise 的 riskAnalysis.score | 评分未达到设定阈值 | 根据真实流量调整 threshold |
| success: true,但 hostname 不正确 | siteverify | 域名验证已关闭,token 来自其他网站 | 启用域名验证,或在代码中检查 hostname |
reCAPTCHA 为什么验证失败?常见原因
修复方法取决于具体原因。最常见的有四类:token 过期或重复使用,密钥与域名不匹配,组件无法加载,以及 score 低于网站设置的 threshold。
Token 过期或重复使用:timeout-or-duplicate
timeout-or-duplicate 表示 token 已生成超过两分钟,或已经验证过。根据 Google 的 SiteVerify 文档,每个 reCAPTCHA 用户响应 token 的有效期为两分钟,而且只能验证一次,以防止重放攻击。
- 表单较长时,访客可能先勾选复选框,再花五分钟填写其他内容。在 v2 中,可以添加 data-expired-callback,提示访客重新勾选。
- 如果结账页面在加载时就请求 v3 token,而买家花了三分钟填写银行卡信息,提交的 token 就已经过期。Google 建议在用户提交表单时执行验证,而不是提前生成 token。
- 双击 Submit,或 JavaScript 处理函数与原生 submit 事件同时触发,都可能让表单向服务器提交两次。应在第一次点击后禁用按钮,仅在请求失败时重新启用。
- 重复验证也可能发生在后端:中间件先验证 token,控制器随后又将同一 token 发给 siteverify。每个请求中的 token 只应验证一次。
- 表单报错后,下次提交可能仍携带旧 token。在 v2 中调用 grecaptcha.reset();在 v3 中请求新的 token。
下面的 v3 示例在提交时获取 token,并禁用按钮,防止重复提交。
<form id="signup" action="/signup" method="POST">
<!-- form fields -->
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response">
<button type="submit" id="submit-btn">Sign up</button>
</form>
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
<script>
const form = document.getElementById('signup');
const button = document.getElementById('submit-btn');
form.addEventListener('submit', function (event) {
event.preventDefault();
button.disabled = true; // block double submit
grecaptcha.ready(function () {
grecaptcha.execute('YOUR_SITE_KEY', { action: 'signup' }).then(function (token) {
document.getElementById('g-recaptcha-response').value = token; // fresh token at submit time
form.submit();
});
});
});
</script>Secret key 无效或域名不匹配:invalid-input-secret
笼统的“Error verifying reCAPTCHA”背后,服务器日志中往往记录的是 invalid-input-secret:Google 判定 secret key 无效或格式错误。
- 后端配置与 HTML 中的 site key 和 secret key 被填反。
- 前端代码与密钥类型不一致。每个密钥在创建时都会指定为 Score-based (v3) 或 Challenge (v2)。
- 密钥已重新创建,但后端仍在使用旧的 secret key。当前密钥位于 Key Details → Integration → Use Legacy Key。
- 密钥未关联 Google Cloud 项目。Google 在 2026 年第一季度完成了 Classic 密钥的自动迁移,并限制了未关联 Google Cloud 项目的密钥访问 API。如果今年集成在代码未变的情况下突然失效,先检查这一点。
- 部署时混用了测试密钥和生产密钥。Google 提供始终通过验证的 v2 测试密钥,因此密钥对只复制了一部分的问题,可能直到上线才暴露。
- .env 中多余的换行符被包含在 secret key 中。
如果生成 token 的页面不在密钥允许的域名范围内,Enterprise 会返回 DOMAIN_MISMATCH。在本地环境中,你可能会看到 “Localhost is not in the list of supported domains.” 将对应域名准确添加到密钥配置中。对于 localhost,Google 建议使用单独的开发密钥。
开启 Disable domain verification 后,Google 就不再检查 token 的来源,因此你的代码必须比较 hostname,确认它与网站域名一致。

浏览器中 reCAPTCHA 无法加载:browser-error
browser-error 指发生在服务器参与验证之前的故障,通常是脚本或 iframe 没有完成加载。Enterprise API 将 BROWSER_ERROR 归类为可重试错误,例如网络故障。因此,第一步是再次调用 execute()。
- 广告或脚本拦截器可能阻止脚本加载。Google 的帮助页面建议停用可能与 reCAPTCHA 冲突的插件。
严格的 Content Security Policy 可能拦截脚本,此时浏览器控制台会显示脚本或 frame 被阻止的消息。Google 的 FAQ 列出了需要加入相应指令的来源:
script-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/
frame-src https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/
connect-src https://www.google.com/recaptcha/- 如果防火墙、代理或 VPN 阻止访问 Google 域名,验证组件也会失效。请在访客所在网络中允许访问 *.google.com、*.gstatic.com 和 *.recaptcha.net。当 www.google.com 无法访问时,Google 建议从 www.recaptcha.net 加载脚本,并相应替换其他 www.google.com/recaptcha/ 引用。
- 在 api.js 加载完成之前调用 grecaptcha 会失败。将相关调用放在 grecaptcha.ready() 内,或使用 onload 回调。
- 页面上有多个组件时,如果不传入 ID,grecaptcha.getResponse() 和 grecaptcha.reset() 只会作用于第一个组件。应显式渲染每个组件,并保存 grecaptcha.render() 返回的各个 ID。
对于 v2 checkbox,添加 data-error-callback。按照 Google 的说明,实现这个回调后,你还需要负责提示用户重试。
reCAPTCHA v3 提示“Captcha score is not above the threshold”
这条消息表示 Google 接受了 v3 token,但返回的 score 低于网站或插件设置的 threshold。集成本身在正常运行,需要检查的是阈值设置。
在 Google 的评分体系中,0.0 表示高风险,1.0 表示低风险。Google 在验证挑战策略示例中使用 0.5 作为 threshold,但建议根据真实流量选择阈值。预发布环境的 score 可能与生产环境不同。
- 先记录 score,不要立即拦截请求。再按照 Google 的建议,结合控制台中的流量数据选择 threshold。
- 为每个操作分别设置 threshold。控制台会提供最常见的十个操作的统计信息。
- 对于低 score,优先增加验证步骤,而不是直接拒绝请求。Google 的 Enterprise 文档建议,对低评分的登录尝试使用邮件验证或 MFA。
- 检查响应中的 action 是否与你发送的值一致。
例如,邮件订阅表单可以接受 0.3 及以上的 score;登录请求低于 0.7 时,则要求输入邮件验证码,而不是直接拦截。
移动应用需要单独评估。Google 的版本说明提到,2026 年的移动 SDK 调整了评分校准方式。如果升级 SDK 后误报增加,就有必要重新检查应用的 threshold。
在 Enterprise 中,未启用结算的项目只能获得四档 score:0.1、0.3、0.7 和 0.9,而不是 11 档。

如果项目没有有效的结算账号,并且超过每月 10,000 次 assessment 的免费配额,siteverify 会返回 success: true、固定的 0.9 score,以及“Over free quota.”消息。如果所有 score 突然都变成 0.9,先检查配额。
Firebase、Adobe AEM 和 Zoho Forms 中的同类错误
这些平台会用各自的错误消息表示 reCAPTCHA 验证失败。下表列出了对应的原因和修复方法。
| 平台 | 错误消息 | 原因 | 修复方法 |
|---|---|---|---|
| Firebase 手机号认证(Identity Platform) | CAPTCHA_CHECK_FAILED : Recaptcha verification failed - SITE_MISMATCH | token 来自不在密钥允许列表中的域名(Google 员工的答复) | 将域名添加到 site key 的配置中 |
| Adobe AEM Forms | CAPTCHA_VALIDATION, HTTP 400 | 迁移后,表单仍在使用旧的 v2 密钥(Adobe 知识库) | 更新 Adaptive Forms 的 reCAPTCHA 配置中的密钥 |
| Zoho Forms | 相同的 reCAPTCHA validation failed 消息 | Settings 中的 secret key 错误、未通过垃圾信息检查,或 Google 端发生故障(Zoho 帮助文档) | 检查 Settings 中的 secret key |
reCAPTCHA 服务器端验证示例:PHP
如果 reCAPTCHA 在服务器端验证失败,先记录错误码。Google 返回验证不通过,与服务器未能成功请求 Google,是两种需要分别处理的情况。下面的 PHP 示例为这两种情况返回不同的响应。所有密钥都检查 hostname,v3 还会检查 score 和 action。
<?php
$secretKey = getenv('RECAPTCHA_SECRET'); // legacy secret key, server-side only
$expectedHost = 'www.example.com'; // your domain
$expectedAction = 'signup'; // v3 only: action name set on the client
$threshold = 0.5; // v3 only: tune using your own traffic data
$token = $_POST['g-recaptcha-response'] ?? '';
if ($token === '') {
http_response_code(400);
exit('Please complete the CAPTCHA.');
}
$ch = curl_init('https://www.google.com/recaptcha/api/siteverify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => $secretKey,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
$raw = curl_exec($ch);
if ($raw === false) {
// Network problem between your server and Google, not a reCAPTCHA failure
error_log('siteverify request failed: ' . curl_error($ch));
curl_close($ch);
http_response_code(503);
exit('Verification service unavailable. Please try again.');
}
curl_close($ch);
$result = json_decode($raw, true);
if (empty($result['success'])) {
$codes = $result['error-codes'] ?? ['unknown-error'];
error_log('reCAPTCHA failed: ' . implode(', ', $codes));
http_response_code(400);
exit('Verification failed. Please try again.');
}
if (($result['hostname'] ?? '') !== $expectedHost) {
http_response_code(400);
exit('Verification failed: unexpected hostname.');
}
// v3 only: score and action checks
if (isset($result['score'])) {
if (($result['action'] ?? '') !== $expectedAction || $result['score'] < $threshold) {
http_response_code(403);
exit('Additional verification required.');
}
}
echo 'Verification successful';下面的 v2 checkbox 标记使用了前文提到的 data-expired-callback 和 data-error-callback 属性。
<!DOCTYPE html>
<html>
<head>
<title>reCAPTCHA v2 checkbox</title>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form action="verify.php" method="POST">
<div class="g-recaptcha"
data-sitekey="YOUR_SITE_KEY"
data-expired-callback="onCaptchaExpired"
data-error-callback="onCaptchaError"></div>
<br>
<input type="submit" value="Submit">
</form>
<script>
function onCaptchaExpired() { alert('The CAPTCHA expired. Please check the box again.'); }
function onCaptchaError() { alert('reCAPTCHA could not load. Check your connection and try again.'); }
</script>
</body>
</html>reCAPTCHA Enterprise 与 v2 checkbox:故障位置和原因有何不同
Google 对 Enterprise token 和 v2 checkbox token 采用不同的验证方式。v2 的 siteverify 返回通过或失败的结果,以及简短的错误码;Enterprise assessment 则会更详细地解释 token 被拒绝的原因。产品设计和价格方面的区别,可参阅《reCAPTCHA v2、v3 与 Enterprise:功能与成本对比》。
验证流程与响应内容
使用 v2 checkbox 时,访客点击“我不是机器人”后会获得 token。后端将 token 和 secret key 通过 POST 请求发送给 siteverify。响应包含 success、challenge_ts、hostname,以及存在错误时返回的 error-codes 数组。v2 响应不会包含 score。
Enterprise token 通过 grecaptcha.enterprise.execute() 或页面中渲染的 Enterprise checkbox 获取。验证时,后端需要向以下地址发送 POST 请求,创建 assessment:
https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments
请求体包含 token、site key 和预期操作。Google 还建议发送用户的 User-Agent 和 IP 地址。
{
"event": {
"token": "TOKEN",
"siteKey": "KEY_ID",
"expectedAction": "login",
"userAgent": "USER_AGENT",
"userIpAddress": "USER_IP"
}
}响应包含 tokenProperties(valid、invalidReason、hostname、action)和 riskAnalysis(score、reasons)。
在哪里查看验证失败的原因
v2 reCAPTCHA 的错误会以六种错误码之一返回,没有更多细节。如果访客未通过图片挑战,token 就不会生成,服务器端也就没有可分析的内容。
Enterprise 提供的信息更具体。token 被拒绝时,invalidReason 会指出原因,例如 MALFORMED、EXPIRED、DUPE、MISSING、BROWSER_ERROR、UNEXPECTED_ACTION、KEY_MISMATCH 或 DOMAIN_MISMATCH。如果 token 有效但 score 较低,相关原因则通过 riskAnalysis.reasons 返回,例如 AUTOMATION、TOO_MUCH_TRAFFIC 或 LOW_CONFIDENCE_SCORE。其中,LOW_CONFIDENCE_SCORE 表示流量不足,无法进行可靠分析。获取原因代码需要结算账号。
Token 验证方式的区别
siteverify 接口使用 secret key 进行身份验证。assessment 则使用 API key,或具有 reCAPTCHA Enterprise Agent 角色的服务账号。v2 后端只检查 success。Enterprise 后端需要确认 tokenProperties.valid 为 true、操作与预期一致,并且 score 达到设定的 threshold。Enterprise 密钥仍可通过 legacy secret key 使用 siteverify,但 Google 建议新集成使用 CreateAssessment。
控制台中的配置方式
独立的 reCAPTCHA Admin 控制台将密钥创建放在一个表单中。填写 Label,选择密钥类型——Score based (v3) 或 Challenge (v2)——并添加域名,然后点击 Submit 即可创建密钥。
Google Cloud 控制台(Google Cloud Fraud Defense)则分为两步:先在 Keys 标签页点击 Create key,再在打开的表单中填写 Display name、Application type 和 Domain list,旁边还有 Disable domain verification 开关。
自 2026 年 4 月起,reCAPTCHA 已归入 Google Cloud Fraud Defense。Google 表示,这一变化不影响现有功能。

使用 policy-based challenge keys 时,如果 score 低于你设置的 threshold,访客就会收到验证挑战。这类密钥自 2025 年 10 月起正式可用。Policy Engine 自 2026 年 7 月起进入 Preview 阶段,支持按 score、IP、User-Agent 或 ASN 设置规则。
Enterprise 与 v2 错误:现象、排查位置和处理方法
| 现象 | 排查位置 | 处理方法 |
|---|---|---|
| timeout-or-duplicate(v2)或 EXPIRED / DUPE(Enterprise) | 服务器日志、invalidReason | 在提交时获取 token,并且只验证一次 |
| Enterprise 密钥返回 invalid-input-secret | Key Details → Integration | 使用 legacy secret key,或改用 assessment |
| DOMAIN_MISMATCH 或“Localhost is not in the list of supported domains” | 密钥的域名列表 | 准确添加对应域名,并为 localhost 使用单独的密钥 |
| score 较低,并返回 LOW_CONFIDENCE_SCORE | riskAnalysis.reasons | 先收集更多流量数据,再决定是否拦截请求 |
如何修复 reCAPTCHA 验证失败:排查清单
用户排查清单
如果你访问的网站无法通过 reCAPTCHA,通常是浏览器或网络问题,可以先从本地环境排查。
重新加载页面后再提交表单。生成超过两分钟的 token 不再有效。
更新浏览器。Google 支持主流浏览器最新的两个主要版本。
启用 JavaScript。
暂停广告拦截器对当前网站的拦截。
关闭 VPN,或换一个网络重试。
如果问题仍未解决,联系网站管理员。
网站管理员排查清单
如果 reCAPTCHA 问题出现在服务器端,请依次检查以下项目。
确认 site key 和 secret key 属于同一密钥对,且不含多余的空格或换行符。
确认密钥配置包含所有生产环境域名。
确认密钥已关联 Google Cloud 项目。
在表单提交时请求 token。
首次点击后禁用 Submit 按钮。
确保同一 token 不会被验证两次。
表单报错后重置组件,或请求新的 token。
后端对所有密钥检查 hostname,对 v3 额外检查 score 和 action。
在 CSP 中允许 Google 指定的 reCAPTCHA 来源。
根据日志中记录的 score 设置 v3 threshold。
日志只记录错误码和 hostname,不记录 secret key 或完整 token。
验证失败后保留访客已填写的表单内容。
相关阅读
- 不同 CAPTCHA 服务中的“invalid captcha”错误及修复方法
- reCAPTCHA v2、v3 与 Enterprise:功能、评分和成本对比
- 为什么 CAPTCHA 无法正常工作:常见原因与修复方法
使用 CapMonster Cloud 自动化测试 reCAPTCHA 表单
测试自己的表单时,CapMonster Cloud API 支持 reCAPTCHA v2、reCAPTCHA v3 和 reCAPTCHA Enterprise,包括 RecaptchaV2Task、RecaptchaV3TaskProxyless、RecaptchaV2EnterpriseTask 和 RecaptchaV3EnterpriseTask 等任务类型。各任务的配置方法和参数说明见 CapMonster Cloud reCAPTCHA 文档。





