logo
bars
///
reCAPTCHA Validation Failed: Causes and Fixes (2026)
Vladlen Vlasov
Vladlen Vlasov
Technical Writer
November 3, 2026
13 min
Please review the terms of use for the materials on this website.

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.

robots
Get started now and automate your solution reCAPTCHA v2

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.

reCAPTCHA validation failed error in a server log or on the page 2026
reCAPTCHA SiteVerify API error response in Terminal

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 symptomWhere it appearsCauseFix
missing-input-secretsiteverifyNo secret parameter was sentCheck that the secret key is loaded
invalid-input-secretsiteverifyWrong secret key, or the site key pasted by mistakeUse the secret key paired with your site key
missing-input-responsesiteverifyNo token was sent, or a firewall rule removed the fieldMake sure g-recaptcha-response reaches the backend
invalid-input-responsesiteverifyToken malformed, cut off, or from another site keyPass the token unchanged
bad-requestsiteverifyGoogle couldn't read the requestPOST secret and response as form fields
timeout-or-duplicatesiteverifyThe token is older than two minutes or was already verifiedGet the token at submit time and verify it once
browser-error (Enterprise BROWSER_ERROR)Enterprise invalidReason onlyA retryable browser error, such as a network failureRetry execute(), then check blockers, CSP, and network
Low v3 score (below your threshold)v3 score or Enterprise riskAnalysis.scoreScore under your thresholdTune the threshold on real traffic
success: true but wrong hostnamesiteverifyDomain verification is off, token came from another siteTurn 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.

Admin Console 2026, reCAPTCHA keys list with domains
reCAPTCHA keys and associated domains in Google Cloud Console (2026)

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.

  1. Log scores before blocking anything, then pick thresholds from console traffic, as Google suggests.

  2. Set a separate threshold per action; the console breaks down your top ten actions.

  3. Challenge low scores instead of refusing: Google’s Enterprise docs suggest email verification or MFA for low-scoring logins.

  4. 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.

reCAPTCHA v2 checkbox challenge settings in Google Cloud Console
reCAPTCHA Enterprise score analytics in Google Cloud Console (illustrative data)

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.

PlatformMessageCauseFix
Firebase phone auth (Identity Platform)CAPTCHA_CHECK_FAILED : Recaptcha verification failed - SITE_MISMATCHThe 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 FormsCAPTCHA_VALIDATION, HTTP 400The form still uses outdated v2 keys after migration (Adobe KB)Update the keys in the Adaptive Forms reCAPTCHA configuration
Zoho FormsThe same error, word for wordA 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/assessments

The 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.

Enterprise key and score analytics 2026
reCAPTCHA checkbox challenge settings in Google Cloud Console (2026)

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

SymptomWhere to lookWhat to change
timeout-or-duplicate (v2) or EXPIRED / DUPE (Enterprise)Server logs, invalidReasonGet the token at submit time and verify it once
invalid-input-secret with an Enterprise keyKey Details → IntegrationUse the legacy secret key, or switch to assessments
DOMAIN_MISMATCH or "Localhost is not in the list of supported domains"The key's domain listAdd the exact domain, with a separate key for localhost
Low scores with LOW_CONFIDENCE_SCOREriskAnalysis.reasonsCollect 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.
     
robots
Get started now and automate your solution reCAPTCHA v2

It means Google’s risk analysis treats the interaction as suspicious. On the 0.0–1.0 scale, lower values point to automated or fraudulent activity, and 1.0 marks a very likely legitimate visit. A low score doesn’t invalidate the token, so the response is up to the site. Some forms block such requests outright. A login form might ask for an email code instead, and a newsletter signup might only flag the entry for review.

Google's example challenge policies use 0.5. From there, the threshold should follow your own traffic. Log scores without blocking anyone, review the distribution, and set a separate threshold for each action. Staging scores can differ from production, so the numbers need a second look after launch.

This error means the token is older than two minutes or your server has already verified it. It usually comes from a long form, a v3 token generated on page load, or a double submit. Request the token right before submit and disable the button after one click. Each token should be verified only once.

Yes. On v2, a failed check returns success: false from siteverify with one of six error codes. Enterprise returns an assessment instead, with tokenProperties.valid, a specific invalidReason such as EXPIRED or DOMAIN_MISMATCH, and, for valid tokens, a score with reason codes. Authentication differs as well: an API key or service account replaces the secret key.

No. In many cases, the cause is on the visitor’s side, such as an ad blocker, a VPN, a firewall, or a page left open too long. A low v3 score isn’t a misconfiguration either. The server logs are the first place to look. Codes related to the secret key, the domain, or the request format point to reCAPTCHA problems in the setup itself.

Related Reading

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.


NB: Please note that the product is intended for automating tests on your own websites and sites you have legal access to.
ItGuy
geear
Affiliate program for software developers
Earn up to 30% from your users’ spending on captcha bypass
✅ Request sent
Thank you for your interest in our partnership program! We will contact you within 7 working days.
Request to Join
Fill out the form to submit an application for the affiliate program.