reCAPTCHA Validation Failed: Causes and Fixes

“reCAPTCHA validation failed” is the error a site shows when it can’t confirm that a human submitted the form, so the submission is rejected. It makes no difference whether you clicked the “I’m not a robot” checkbox, or reCAPTCHA checked you quietly in the background with nothing on screen. Google returned a failed result, and the form went no further.
If you only wanted to sign up or log in, the cause is usually on your end: an ad blocker, for instance, or a page left open too long. If reCAPTCHA verification failed on your own website, the reCAPTCHA settings or the form’s code are the more likely suspects.
Key Takeaways
On the server, the error code names the cause, so read it first. If there’s no code to go on, check the secret key, then the domain list, then the token’s age.
A token lives for only two minutes, and Google verifies it only once. On v3, call execute() when the visitor clicks Submit, not when the page loads.
If the widget doesn’t appear, check for an ad blocker, a CSP rule, or a firewall.
The “captcha score is not above the threshold” message comes from the threshold your site or plugin sets, not from Google.
Enterprise assessments tell you more about why a token failed. Siteverify lumps expired and reused tokens together as timeout-or-duplicate, while Enterprise reports them separately as EXPIRED and DUPE.
What Does reCAPTCHA Validation Failed Mean?
The check broke somewhere, either in the visitor’s browser or on your server. The visitor sees the same error in both cases, but you’ll be looking in different places to fix it.
Client-Side Failure: The Widget Didn't Load, or the Check Didn't Pass
When the problem is in the browser, no token ever gets created. Either the widget didn’t load at all, which is what most people mean when they say reCAPTCHA is not working, or the visitor couldn’t get through the image challenge. In both cases, your backend gets no token, so the request either never arrives or comes with an empty g-recaptcha-response field. Invisible reCAPTCHA is trickier because there’s no checkbox to tell you something went wrong. Without proper error handling, a failed check can leave the form appearing unresponsive.
Server-Side Failure: success: false and error codes
When a form shows a generic “Error verifying reCAPTCHA” message, the token most likely did leave the browser. Google rejected it after your server sent it for verification, and the siteverify response explains why:
{
"success": false,
"error-codes": ["timeout-or-duplicate"]
}Score-based keys can also return success: true with a score below your threshold. Here, the request is rejected by your own code rather than by Google.

Definitions: Site Key, Secret Key, Token, Score, Threshold
Site key. The public half of your key pair. It’s visible in your page’s HTML or JavaScript.
Secret key. The private half, which only your backend should send to siteverify. In Google Cloud, it’s labelled the “legacy secret key.”
Token. The string reCAPTCHA returns after a check (g-recaptcha-response in v2). Google accepts it for two minutes and verifies it only once.
Score. A number from 0.0 to 1.0 returned by v3 and score-based Enterprise keys. The higher the score, the lower the risk.
Threshold. The minimum score your site accepts. You choose it; Google doesn’t choose it for you.
reCAPTCHA Error Codes: Quick Reference
Codes come from Google's siteverify response or an Enterprise assessment, while score rejections come from your own threshold check.
| Code or symptom | Where it appears | Cause | Fix |
|---|---|---|---|
| missing-input-secret | siteverify | No secret parameter was sent | Check that the secret key is loaded |
| invalid-input-secret | siteverify | Wrong secret key, or the site key pasted by mistake | Use the secret key paired with your site key |
| missing-input-response | siteverify | No token was sent, or a firewall rule removed the field | Make sure g-recaptcha-response reaches the backend |
| invalid-input-response | siteverify | Token malformed, cut off, or from another site key | Pass the token unchanged |
| bad-request | siteverify | Google couldn't read the request | POST secret and response as form fields |
| timeout-or-duplicate | siteverify | The token is older than two minutes or was already verified | Get the token at submit time and verify it once |
| browser-error (Enterprise BROWSER_ERROR) | Enterprise invalidReason only | A retryable browser error, such as a network failure | Retry execute(), then check blockers, CSP, and network |
| Low v3 score (below your threshold) | v3 score or Enterprise riskAnalysis.score | Score under your threshold | Tune the threshold on real traffic |
| success: true but wrong hostname | siteverify | Domain verification is off, token came from another site | Turn verification on, or check hostname |
Why Does reCAPTCHA Verification Fail? Common Causes
How to fix reCAPTCHA verification failed errors depends on which of the four most common causes you’re dealing with. It could be an expired or reused token or a key and domain mismatch. Sometimes the widget won’t load, or the score falls below your threshold.
timeout-or-duplicate means the token was older than two minutes or had already been verified. Per Google’s SiteVerify docs: “Each reCAPTCHA user response token is valid for two minutes, and you can verify each token only once to prevent replay attacks.”
On a long form, the visitor ticks the checkbox first, then spends five minutes on the rest. In v2, add data-expired-callback to prompt a new tick.
A checkout page that requests a v3 token on load sends an expired one if the buyer spends three minutes on card details. Google recommends running verification when the user submits the form, rather than generating the token in advance.
A double click on Submit, or a JS handler running on top of the native submit event, sends the form to the server twice. The button should be disabled after the first click and re-enabled only when the request fails.
Duplicate checks can also happen on the backend, when middleware verifies the token and the controller sends it to siteverify again. A token should be verified only once per request.
After a form error, the next attempt still carries the old token. Call grecaptcha.reset() in v2, or request a new token in v3.
The v3 example below requests the token at submit time and turns off the button to block double submits.
<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>Invalid Secret Key and Domain Mismatch: invalid-input-secret
A vague “Error verifying reCAPTCHA” often hides invalid-input-secret in the server logs: Google rejected your secret key as “invalid or malformed.”
The site key and secret key got swapped between the backend config and the HTML.
The front-end code doesn’t match the key type: every key is created as either Score-based (v3) or Challenge (v2).
The key was recreated, but the backend still holds the old secret. The current one is under Key Details → Integration → Use Legacy Key.
The key has no Google Cloud project. Google completed the automatic migration of Classic keys in Q1 2026 and locked API access for keys without a Google Cloud project. If your integration broke this year without code changes, check this first.
A deploy mixed test and production keys. Google supports v2 testing keys configured to always pass, so a half-copied pair can stay hidden until release.
A stray .env newline slipped into the secret.
Enterprise returns DOMAIN_MISMATCH when the token’s page is outside the key’s allowed domains. Locally, you’ll see “Localhost is not in the list of supported domains.” Add the exact domain to the key. For localhost, Google recommends a separate development key.
With Disable domain verification on, Google stops checking token origins, so your code must compare hostname against your domain.

reCAPTCHA Not Loading in the Browser: browser-error
browser-error covers failures before your server is involved, usually a script or iframe that never finished loading. The Enterprise API calls BROWSER_ERROR “a retriable error (such as network failure),” so the first step is to call execute() again.
Ad or script blockers can stop the script from loading. Google’s help page advises “disabling plugins that might conflict with reCAPTCHA.”
A strict Content Security Policy blocks the script, and the browser console shows a refused script or frame. Google’s FAQ lists the values to add to your directives:
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/A firewall, proxy or VPN that blocks Google’s domains stops the widget as well. Allow *.google.com, *.gstatic.com, and *.recaptcha.net on the visitor’s network. Where www.google.com isn’t accessible, Google recommends loading the script from www.recaptcha.net and updating other www.google.com/recaptcha/ references to match.
Any grecaptcha call made before api.js has loaded will fail. Wrap such calls in grecaptcha.ready() or use the onload callback.
On a page with several widgets, grecaptcha.getResponse() and grecaptcha.reset() apply to the first widget unless an ID is passed. Render widgets explicitly, keeping each ID that grecaptcha.render() returns.
On a v2 checkbox, add data-error-callback. Google notes that once you do, “you are responsible for informing the user that they should retry.”
"Captcha Score Is Not Above the Threshold" (reCAPTCHA v3)
This message appears when Google accepts the v3 token but returns a score lower than the threshold set by your site or plugin. Since the integration itself is working, the threshold is the setting to review.
On Google’s scale, 0.0 means high risk, and 1.0 means low risk. Google uses 0.5 as a threshold in its example challenge policies, but recommends choosing thresholds based on actual traffic. Scores on staging may differ from production.
Log scores before blocking anything, then pick thresholds from console traffic, as Google suggests.
Set a separate threshold per action; the console breaks down your top ten actions.
Challenge low scores instead of refusing: Google’s Enterprise docs suggest email verification or MFA for low-scoring logins.
Check that the response’s action matches the one you sent.
A newsletter form might accept 0.3 or higher, while a login under 0.7 gets an email code, not a block.
Mobile apps need a separate review. Google’s release notes describe a score recalibration in the 2026 mobile SDK, so a rise in false positives after an SDK upgrade is a reason to revisit app thresholds.
On Enterprise, projects without billing get four score levels (0.1, 0.3, 0.7, 0.9) instead of 11.

If a project without an active billing account exceeds the free quota of 10,000 assessments per month, siteverify returns success: true with a fixed score of 0.9 and an “Over free quota.” message. If every score suddenly reads 0.9, check the quota first.
Same Error on Firebase, Adobe AEM, and Zoho Forms
These platforms wrap a reCAPTCHA failure in their own error messages. The table maps each message to its cause and fix.
| Platform | Message | Cause | Fix |
|---|---|---|---|
| Firebase phone auth (Identity Platform) | CAPTCHA_CHECK_FAILED : Recaptcha verification failed - SITE_MISMATCH | The token came from a site that isn't on the key's allowed domains (Google staff answer) | Add the domain to the site key |
| Adobe AEM Forms | CAPTCHA_VALIDATION, HTTP 400 | The form still uses outdated v2 keys after migration (Adobe KB) | Update the keys in the Adaptive Forms reCAPTCHA configuration |
| Zoho Forms | The same error, word for word | A wrong secret key in Settings, a failed spam check, or a problem on Google's side (Zoho help) | Check the secret key in Settings |
reCAPTCHA Server-Side Verification Example (PHP)
If reCAPTCHA failed on the server, log the error code first. A rejection from Google and a failed request to Google need separate handling. In the PHP below, the two cases get separate responses. hostname is checked on every key, with score and action checked on v3.
<?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';The v2 checkbox markup uses the data-expired-callback and data-error-callback attributes from the earlier sections.
<!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 vs v2 Checkbox: What Breaks and Why
Google verifies Enterprise tokens differently from v2 checkbox tokens. On v2, siteverify returns pass or fail with a short error code, while an Enterprise assessment explains in more detail why a token was rejected. Design and pricing differences are covered separately: how reCAPTCHA v2, v3, and Enterprise compare in features and cost.
How Verification Works and What Comes Back
With a v2 checkbox, the token appears after the visitor clicks “I’m not a robot.” Your backend posts the token and the secret key to siteverify. The response contains success, challenge_ts, hostname and, if present, an error-codes array. A v2 response never includes a score.
Enterprise tokens come from grecaptcha.enterprise.execute() or from an Enterprise checkbox rendered on the page. To check one, your backend creates an assessment by sending a POST request to:
https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessmentsThe request body carries the token, site key and expected action. Google also recommends sending the user agent and IP address.
{
"event": {
"token": "TOKEN",
"siteKey": "KEY_ID",
"expectedAction": "login",
"userAgent": "USER_AGENT",
"userIpAddress": "USER_IP"
}
}The response includes tokenProperties (valid, invalidReason, hostname, action) and riskAnalysis (score, reasons).
Where to See Why Verification Failed
A v2 reCAPTCHA error comes as one of six codes, without further detail. Since a failed image challenge creates no token, there's nothing to read on the server.
Enterprise is more specific. When a token is rejected, invalidReason names the problem, including MALFORMED, EXPIRED, DUPE, MISSING, BROWSER_ERROR, UNEXPECTED_ACTION, KEY_MISMATCH, and DOMAIN_MISMATCH. A valid token with a low score comes back with riskAnalysis.reasons instead, such as AUTOMATION, TOO_MUCH_TRAFFIC, or LOW_CONFIDENCE_SCORE, which signals too little traffic for a reliable analysis. Reason codes need a billing account.
How Token Verification Differs
The siteverify endpoint authenticates with the secret key. Assessments use an API key or a service account with the reCAPTCHA Enterprise Agent role. A v2 backend only checks success. An Enterprise backend should confirm that tokenProperties.valid is true, that the action matches, and that the score clears your threshold. siteverify still works with Enterprise keys via the legacy secret key, but Google recommends CreateAssessment for new work.
What the Console Settings Look Like
The standalone reCAPTCHA Admin console keeps key creation on a single form. It asks for a Label, a key type (Score based (v3) or Challenge (v2)) and your domains, and the key is created when you click Submit.
The Google Cloud console (Google Cloud Fraud Defense) splits it into two steps. Key creation starts on the Keys tab with Create key. The form that opens has fields for Display name, Application type and Domain list, with the Disable domain verification toggle beside them.
Since April 2026, reCAPTCHA has been part of Google Cloud Fraud Defense. According to Google, the change doesn’t affect existing functionality.

On policy-based challenge keys, generally available since October 2025, visitors get a challenge when the score drops below a threshold you set. In the Policy Engine (Preview since July 2026), you can set rules based on score, IP, user agent, or ASN.
Enterprise vs v2 Errors: Symptom, Where to Look, What to Change
| Symptom | Where to look | What to change |
|---|---|---|
| timeout-or-duplicate (v2) or EXPIRED / DUPE (Enterprise) | Server logs, invalidReason | Get the token at submit time and verify it once |
| invalid-input-secret with an Enterprise key | Key Details → Integration | Use the legacy secret key, or switch to assessments |
| DOMAIN_MISMATCH or "Localhost is not in the list of supported domains" | The key's domain list | Add the exact domain, with a separate key for localhost |
| Low scores with LOW_CONFIDENCE_SCORE | riskAnalysis.reasons | Collect more traffic before blocking anything |
Enterprise vs v2 Errors: Symptom, Where to Look, What to Change
For Users
The usual answer to “what does reCAPTCHA failed mean” on a site you are visiting is a browser or network issue, which can be resolved on your side.
- Reload the page before resubmitting the form. A token older than two minutes is no longer accepted.
- Update your browser. Google supports the two latest major versions of the main browsers.
- Turn on JavaScript.
- Pause your ad blocker for the site.
- Turn off your VPN, or try another network.
- If you're still stuck, contact the site owner.
For Site Owners
If reCAPTCHA problems show up on your server, go through the points below one by one.
- The site key and secret key come from the same key pair, with no stray spaces or line breaks.
- Every production domain is on the key.
- The key belongs to a Google Cloud project.
- Tokens are requested at submit time.
- Submit is disabled after the first click.
- No token gets verified twice.
- A form error triggers a widget reset or a new token.
- The backend checks hostname on every key, along with score and action on v3.
- CSP allows Google's reCAPTCHA sources.
- The v3 threshold is based on logged scores.
- Logs keep error codes and hostname, never the secret key or a full token.
- Visitors keep their form input after a failed check.
Related Reading
Fixing generic "invalid captcha" messages across CAPTCHA providers
How reCAPTCHA v2, v3, and Enterprise differ in features, scoring, and cost
Automated Testing of reCAPTCHA Forms with CapMonster Cloud
For automated tests of your own forms, CapMonster Cloud’s API supports reCAPTCHA v2, reCAPTCHA v3, and reCAPTCHA Enterprise, including the following task types: RecaptchaV2Task, RecaptchaV3TaskProxyless, RecaptchaV2EnterpriseTask, and RecaptchaV3EnterpriseTask. Setup instructions and parameters for each task are available in the CapMonster Cloud reCAPTCHA documentation.
NB: Please note that the product is intended for automating tests on your own websites and sites you have legal access to.






