Backend Verification with Google reCAPTCHA API
The backend must check a reCAPTCHA token's authenticity after the frontend captures it. This verification step determines if users can proceed with their intended actions.
Your backend needs to send a POST request to Google's verification endpoint to check a token. The request needs two main parameters:
POST Parameters: https://www.google.com/recaptcha/api/siteverify
- secret: Your reCAPTCHA secret key
- response: The token received from frontend
- remoteip: (Optional) User's IP address
The endpoint works with both GET and POST requests, but POST offers better security.
Validating token using secret key
You should never expose your secret key. The best practice is to store it in environment variables instead of your application code:
// Node.js example
const verifyRecaptcha = async (token) => {
const response = await fetch('https://www.google.com/recaptcha/api/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
secret: process.env.RECAPTCHA_SECRET,
response: token
}).toString()
});
return await response.json();
};
Using URLSearchParams ensures that all parameters are properly URL-encoded, preventing errors when handling special characters in the token.
Handling success and failure responses
The API returns a JSON object, the structure of which differs for v2 and v3.
For reCAPTCHA v2:
- success: Boolean value indicating the verification status
- challenge_ts: Verification timestamp
- hostname: Website where reCAPTCHA was solved
- error-codes: Array of error messages (if applicable)
For reCAPTCHA v3 (in addition to the v2 fields):
- score: A value from 0.0 to 1.0 indicating the legitimacy of the interaction (where 1.0 means a high probability of a legitimate user)
- action: Action name specified when generating the token
Example of response processing for v2:
const result = await verifyRecaptcha(token);
if (result.success) {
// Proceed with form processing
} else {
// Handle verification failure
console.error('Verification failed:', result['error-codes']);
}
Example of response processing for v3 with score verifying:
const result = await verifyRecaptcha(token);
if (result.success && result.score > 0.5 && result.action === 'login') {
// Proceed with form processing
} else if (result.success && result.score <= 0.5) {
// Low score - possible bot
console.warn('Low score detected:', result.score);
} else {
// Verification failed
console.error('Verification failed:', result['error-codes']);
}
Error Code Handling:
The error-codes array can contain the following values:
- missing-input-secret: The secret parameter is missing
- invalid-input-secret: The secret parameter is invalid or incorrect
- missing-input-response: The response (token) parameter is missing
- invalid-input-response: The response parameter is invalid or has expired
- bad-request: The request is invalid or malformed
- timeout-or-duplicate: The token has already been used or has expired
Example of full processing with error-codes:
const result = await verifyRecaptcha(token);
if (result.success) {
// Success - proceed with form processing
return { verified: true };
} else {
// Handle specific error codes
const errors = result['error-codes'] || [];
if (errors.includes('timeout-or-duplicate')) {
return { verified: false, message: 'Token expired. Please try again.' };
} else if (errors.includes('invalid-input-response')) {
return { verified: false, message: 'Invalid verification token.' };
} else if (errors.includes('missing-input-secret') || errors.includes('invalid-input-secret')) {
console.error('Server configuration error:', errors);
return { verified: false, message: 'Server error. Please contact support.' };
} else {
return { verified: false, message: 'Verification failed. Please try again.' };
}
}
Token expiration and one-time use constraints
Each reCAPTCHA token lasts two minutes and works just once. The user experience improves with these token refresh strategies:
- Create new tokens right before form submission
- Set up automatic token refresh for longer forms
- Show friendly error messages when tokens expire
Testing reCAPTCHA with CapMonster Cloud
CapMonster Cloud provides automated reCAPTCHA solving for testing, QA, and development environments. The service solves reCAPTCHA v2, v3, and Enterprise versions programmatically via REST API, returning tokens your application accepts like real user tokens.
This enables comprehensive testing of protected forms, CI/CD pipelines, and load testing without manual solving. QA teams can validate implementations across different scenarios and score ranges, while developers test verification logic, error handling, and token expiration behavior.
CapMonster Cloud integrates through simple API calls, supporting popular frameworks like Selenium, Puppeteer, and Playwright. It eliminates constant CAPTCHA friction during development while validating your Google reCAPTCHA integration, accelerating development cycles before production deployment.
Example of reCAPTCHA v3 solving with Playwright and official Node.js library from CapMonster Cloud
▶ Show code
const { chromium } = require('playwright');
const {
CapMonsterCloudClientFactory,
ClientOptions,
RecaptchaV3ProxylessRequest
} = require('@zennolab_com/capmonstercloud-client');
(async () => {
const TARGET_URL = 'https://lessons.zennolab.com/captchas/recaptcha/v3.php?level=beta';
const SITE_KEY = '6Le0xVgUAAAAAIt20XEB4rVhYOODgTl00d8juDob';
const API_KEY = 'your_capmonster_cloud_api_key';
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto(TARGET_URL, { waitUntil: 'domcontentloaded' });
const recaptchaRequest = new RecaptchaV3ProxylessRequest({
websiteURL: TARGET_URL,
websiteKey: SITE_KEY,
minScore: 0.6,
pageAction: 'myverify',
});
const solution = await cmcClient.Solve(recaptchaRequest);
const token = solution.solution?.gRecaptchaResponse;
if (!token) {
console.error('Token is empty, check the sitekey and URL');
await browser.close();
return;
}
console.log('Token received:', token);
await page.evaluate((t) => {
const input = document.querySelector('#v3_token');
if (input) input.value = t;
const form = document.querySelector('#v3_form');
if (form) {
form.submit();
return;
}
if (typeof window.onSubmit === 'function') {
window.onSubmit(t);
return;
}
if (window.___grecaptcha_cfg) {
const clients = window.___grecaptcha_cfg.clients;
for (const clientKey in clients) {
const client = clients[clientKey];
for (const prop in client) {
const cb = client[prop]?.callback;
if (typeof cb === 'function') {
cb(t);
return;
}
}
}
}
console.warn('Form and callback not found');
}, token);
console.log('Token inserted and callback executed (if available)');
await page.waitForTimeout(5000);
await browser.close();
})();
Conclusion
Google reCAPTCHA API protects your websites against automated attacks and creates a better user experience. This piece shows you how to set up and merge this security tool from start to finish.
The key differences between reCAPTCHA v2 and v3 will help you choose the right version. V2 uses a visible checkbox interface for verification, while v3 quietly assigns risk scores without disrupting users.
Your implementation's foundation depends on proper API key setup. Experience shows that environment variables keep your secret keys secure and protect your verification system's integrity. These keys should never appear in your source code or repositories.
React applications need specific components to add reCAPTCHA. The backend verification process then completes the security loop by proving tokens right through Google's verification endpoint.
ReCAPTCHA tokens come with specific limits - they expire after two minutes and work only once. You need proper token management strategies to create a smooth user experience.
You now have everything you need to build a resilient reCAPTCHA solution. This approach will reduce bot traffic and automated abuse on your websites by a lot. Your legitimate users can still interact with your applications easily. This balanced security approach represents the perfect way to implement reCAPTCHA technology in today's bot-filled digital world.
Useful Links