Explainers

How reCAPTCHA Token Lifecycle Works: Expiration, Renewal, Validation

Every reCAPTCHA interaction produces a token — a long base64-encoded string that proves the challenge was completed. This token has a strict lifecycle: it is generated once, expires quickly, and can only be validated once by Google's server. Misunderstanding this lifecycle is the #1 cause of "token expired" and "invalid token" errors in automation workflows. This guide covers every stage of the token lifecycle with practical timing recommendations.


Token lifecycle overview

User completes CAPTCHA challenge (or invisible JS runs)
    ↓
Client receives g-recaptcha-response token (~500-4000 characters)
    ↓
Token placed in hidden form field or JavaScript variable
    ↓
Form submitted to your server with token included
    ↓
Server sends token to Google siteverify API
    ↓
Google validates: Is token valid? Expired? Already used? Correct domain?
    ↓
Google returns: { success: true/false, score: 0.0-1.0 (v3), error-codes: [] }
    ↓
Token is now consumed — cannot be reused

Stage 1: Token generation

reCAPTCHA v2 (checkbox)

Token is generated when the user completes the checkbox challenge:

// Token appears in a hidden textarea
// <textarea id="g-recaptcha-response" name="g-recaptcha-response">TOKEN_HERE</textarea>

// Or programmatically:
const token = grecaptcha.getResponse();

reCAPTCHA v2 Invisible

Token is generated when execute() is called and the risk check passes:

grecaptcha.execute();

function onCallback(token) {
    // token is the g-recaptcha-response value
    document.getElementById('captcha-field').value = token;
    document.getElementById('form').submit();
}

reCAPTCHA v3

Token is generated for every execute() call with an action name:

grecaptcha.execute('SITE_KEY', { action: 'login' }).then(function(token) {
    // token generated based on behavioral analysis
    // No visible challenge — token always generated
});

Token format

A reCAPTCHA token looks like this (truncated):

03AGdBq26...long_base64_string...xYz_4kRw
  • Length: 500-4000 characters
  • Format: URL-safe base64
  • Encoding: Contains encrypted challenge result, timestamp, site key, action (v3)
  • One-time use: Each token can only be verified once

Stage 2: Token expiration

This is the most critical stage for automation. reCAPTCHA tokens expire, and the expiration window differs by version.

Expiration windows

Version Expiration time Notes
reCAPTCHA v2 120 seconds (2 minutes) Timer starts when checkbox is checked
reCAPTCHA v2 Invisible 120 seconds Timer starts when execute() callback fires
reCAPTCHA v3 120 seconds Timer starts when execute() resolves
reCAPTCHA Enterprise 120 seconds Same window, stricter validation

What happens when a token expires

# Expired token validation response from Google
{
    "success": False,
    "error-codes": ["timeout-or-duplicate"]
}

The timeout-or-duplicate error code covers both expiration and reuse attempts. Google intentionally does not distinguish between the two cases.

Timing implications for API solvers

When using an API solver like CaptchaAI, the timeline becomes:

Your code extracts site key and page URL
    ↓ ~0 seconds
Submit to CaptchaAI API (in.php)
    ↓ ~15-45 seconds (solver working)
Receive token from CaptchaAI API (res.php)
    ↓
⏱ 120-SECOND COUNTDOWN STARTS HERE
    ↓
Your code submits token to target website
    ↓ Must happen within remaining time
Target website validates token with Google

Critical insight: The 120-second timer does NOT start when you submit to CaptchaAI. It starts when CaptchaAI generates the token. You have the remaining time (120 seconds minus any delay in polling) to submit the token.

Safe timing strategy

import time

# Record when you receive the token
token_received_at = time.time()

# ... prepare form submission ...

# Check if token is still valid (leave 10-second safety margin)
elapsed = time.time() - token_received_at
if elapsed > 110:  # 120 - 10 second margin
    print("Token too old, requesting new one")
    # Re-submit to CaptchaAI for a fresh token
else:
    print(f"Token age: {elapsed:.1f}s — submitting")
    # Submit form with token

Stage 3: Server-side validation

Google siteverify API

After receiving the token, your server (or the target website's server) validates it with Google:

import requests

def validate_recaptcha_token(token, secret_key, remote_ip=None):
    """Validate a reCAPTCHA token with Google's siteverify API."""
    payload = {
        "secret": secret_key,
        "response": token,
    }
    if remote_ip:
        payload["remoteip"] = remote_ip

    result = requests.post(
        "https://www.google.com/recaptcha/api/siteverify",
        data=payload,
        timeout=10,
    ).json()

    return result

Validation response (v2)

{
    "success": true,
    "challenge_ts": "2025-01-15T10:30:00Z",
    "hostname": "example.com"
}

Validation response (v3)

{
    "success": true,
    "score": 0.9,
    "action": "login",
    "challenge_ts": "2025-01-15T10:30:00Z",
    "hostname": "example.com"
}

Error codes

Error code Meaning Common cause
missing-input-secret Secret key not provided Server-side configuration error
invalid-input-secret Secret key is wrong Wrong key for this site
missing-input-response Token not provided Form field not submitted
invalid-input-response Token is malformed Corruption during transmission
bad-request Request invalid Malformed POST data
timeout-or-duplicate Token expired or already used Too slow to submit, or double-submit

Stage 4: Token consumption (one-time use)

A reCAPTCHA token can be verified exactly once. After Google's siteverify API validates it, the token is consumed and cannot be reused.

# First validation — succeeds
result1 = validate_recaptcha_token(token, secret)
# { "success": true, "score": 0.9, ... }

# Second validation — fails (same token)
result2 = validate_recaptcha_token(token, secret)
# { "success": false, "error-codes": ["timeout-or-duplicate"] }

Implications for automation

  • You cannot reuse a token across multiple form submissions
  • Each form submission needs a fresh token
  • If a submission fails for non-CAPTCHA reasons (network error, validation error), you need a new token to retry
  • Parallelizing form submissions requires parallel token generation

Complete token management in Python

import requests
import time

class RecaptchaTokenManager:
    """Manage reCAPTCHA token lifecycle for automation workflows."""

    API_KEY = "YOUR_API_KEY"
    MAX_TOKEN_AGE = 110  # seconds (120 minus 10-second safety margin)

    def __init__(self, site_key, page_url, version="v2"):
        self.site_key = site_key
        self.page_url = page_url
        self.version = version

    def request_token(self):
        """Request a new token from CaptchaAI."""
        params = {
            "key": self.API_KEY,
            "method": "userrecaptcha",
            "googlekey": self.site_key,
            "pageurl": self.page_url,
            "json": 1,
        }

        if self.version == "v3":
            params["version"] = "v3"
            params["action"] = "submit"
            params["min_score"] = "0.9"

        submit = requests.post(
            "https://ocr.captchaai.com/in.php",
            data=params,
        ).json()

        if submit.get("status") != 1:
            raise Exception(f"Submit failed: {submit}")

        return submit["request"]

    def poll_token(self, task_id, timeout=180):
        """Poll for token result with timestamp tracking."""
        start = time.time()

        for _ in range(60):
            time.sleep(5)

            if time.time() - start > timeout:
                raise TimeoutError("Token solve timeout")

            result = requests.get(
                "https://ocr.captchaai.com/res.php",
                params={
                    "key": self.API_KEY,
                    "action": "get",
                    "id": task_id,
                    "json": 1,
                },
            ).json()

            if result.get("status") == 1:
                return {
                    "token": result["request"],
                    "received_at": time.time(),
                }

        raise TimeoutError("Token solve timeout")

    def get_fresh_token(self):
        """Get a fresh, immediately usable token."""
        task_id = self.request_token()
        result = self.poll_token(task_id)
        return result

    def is_token_valid(self, token_data):
        """Check if a token is still within the valid time window."""
        age = time.time() - token_data["received_at"]
        return age < self.MAX_TOKEN_AGE

    def submit_with_token(self, submit_fn):
        """
        Get a token and submit immediately.
        submit_fn receives the token string and returns True/False.
        """
        token_data = self.get_fresh_token()

        if not self.is_token_valid(token_data):
            raise Exception("Token expired before submission")

        success = submit_fn(token_data["token"])

        if not success:
            # Token is consumed even on failed submission — get a new one
            print("Submission failed, requesting new token...")
            token_data = self.get_fresh_token()
            success = submit_fn(token_data["token"])

        return success


# Usage
manager = RecaptchaTokenManager(
    site_key="6LcR_RsTAAAAAN_r0GEkGBfq3L7KmU5JbPHJtwNp",
    page_url="https://example.com/login",
    version="v2",
)

def my_form_submit(token):
    response = requests.post("https://example.com/login", data={
        "username": "user",
        "password": "pass",
        "g-recaptcha-response": token,
    })
    return response.status_code == 200

result = manager.submit_with_token(my_form_submit)
print(f"Submission {'succeeded' if result else 'failed'}")

Token troubleshooting

Symptom Likely cause Fix
timeout-or-duplicate every time Token taking too long to submit Reduce time between receive and submit
timeout-or-duplicate intermittently Token reuse or race condition Ensure each submission gets a fresh token
invalid-input-response Token corrupted in transit Check URL encoding, form field name
Score always 0.1 (v3) Mismatched action parameter Match the action value to what the page expects
hostname mismatch Token for wrong domain Ensure pageurl matches the target domain exactly

Frequently asked questions

How long do reCAPTCHA tokens last?

All reCAPTCHA token versions expire after 120 seconds (2 minutes). In practice, submit within 90 seconds to account for clock differences and network latency.

Can I extend a reCAPTCHA token's lifetime?

No. The expiration is enforced server-side by Google and cannot be extended. If your workflow takes longer than 120 seconds between token generation and form submission, you must request a new token.

Why does Google return "timeout-or-duplicate" for both expired and reused tokens?

Google intentionally uses a single error code for both cases to prevent attackers from distinguishing between an expired token (timing issue) and a consumed token (reuse attempt). From a security perspective, both should be treated the same way: request a new token.

Does CaptchaAI's solve time eat into the 120-second window?

The 120-second countdown starts when the token is generated by the solver, not when you submit the request to CaptchaAI. Typically, CaptchaAI solves within 15-45 seconds, leaving 75-105 seconds for your code to submit the token. This is sufficient for most workflows.


Summary

The reCAPTCHA token lifecycle has four stages: generation (challenge completion), expiration (120-second window), server validation (Google siteverify API), and consumption (one-time use). For automation workflows using CaptchaAI, the critical factor is submitting the token within the 120-second window. Use the token manager pattern above to track token age and automatically request fresh tokens when needed.

Discussions (0)

No comments yet.

Related Posts

Reference CAPTCHA Token Injection Methods Reference
Complete reference for injecting solved CAPTCHA tokens into web pages.

Complete reference for injecting solved CAPTCHA tokens into web pages. Covers re CAPTCHA, Turnstile, and Cloud...

Automation Python reCAPTCHA v2
Apr 08, 2026
Tutorials Pytest Fixtures for CaptchaAI API Testing
Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI.

Build reusable pytest fixtures to test CAPTCHA-solving workflows with Captcha AI. Covers mocking, live integra...

Automation Python reCAPTCHA v2
Apr 08, 2026
API Tutorials How to Solve reCAPTCHA v2 Callback Using API
how to solve re CAPTCHA v 2 callback implementations using Captcha AI API.

Learn how to solve re CAPTCHA v 2 callback implementations using Captcha AI API. Detect the callback function,...

Automation reCAPTCHA v2 Webhooks
Mar 01, 2026
Reference Browser Session Persistence for CAPTCHA Workflows
Manage browser sessions, cookies, and storage across CAPTCHA-solving runs to reduce repeat challenges and maintain authenticated state.

Manage browser sessions, cookies, and storage across CAPTCHA-solving runs to reduce repeat challenges and main...

Automation Python reCAPTCHA v2
Feb 24, 2026
Integrations Browser Profile Isolation + CaptchaAI Integration
Browser profile isolation tools create distinct browser environments with unique fingerprints per session.

Browser profile isolation tools create distinct browser environments with unique fingerprints per session. Com...

Automation Python reCAPTCHA v2
Feb 21, 2026
Comparisons WebDriver vs Chrome DevTools Protocol for CAPTCHA Automation
Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabilities, and when to use each with Captcha AI.

Compare Web Driver and Chrome Dev Tools Protocol (CDP) for CAPTCHA automation — detection, performance, capabi...

Automation Python reCAPTCHA v2
Mar 27, 2026
Tutorials Securing CaptchaAI Credentials in Environment Variables
Store Captcha AI API keys securely using environment variables, .env files, Docker secrets, and cloud secret managers instead of hardcoding.

Store Captcha AI API keys securely using environment variables, .env files, Docker secrets, and cloud secret m...

Automation Python reCAPTCHA v2
Feb 12, 2026
Use Cases Event Ticket Monitoring with CAPTCHA Handling
Build an event ticket availability monitor that handles CAPTCHAs using Captcha AI.

Build an event ticket availability monitor that handles CAPTCHAs using Captcha AI. Python workflow for checkin...

Automation Python reCAPTCHA v2
Jan 17, 2026
Explainers reCAPTCHA v2 Invisible: Trigger Detection and Solving
Detect and solve re CAPTCHA v 2 Invisible challenges with Captcha AI — identify triggers, extract parameters, and handle auto-invoked CAPTCHAs.

Detect and solve re CAPTCHA v 2 Invisible challenges with Captcha AI — identify triggers, extract parameters,...

Automation Python reCAPTCHA v2
Apr 07, 2026
Use Cases CAPTCHA Solving in Ticket Purchase Automation
How to handle CAPTCHAs on ticketing platforms Ticketmaster, AXS, and event sites using Captcha AI for automated purchasing workflows.

How to handle CAPTCHAs on ticketing platforms Ticketmaster, AXS, and event sites using Captcha AI for automate...

Automation Python reCAPTCHA v2
Feb 25, 2026
Explainers How BLS CAPTCHA Works: Grid Logic and Image Selection
Deep dive into BLS CAPTCHA grid logic — how images are arranged, how instructions map to selections, and how Captcha AI processes BLS challenges.

Deep dive into BLS CAPTCHA grid logic — how images are arranged, how instructions map to selections, and how C...

Automation BLS CAPTCHA
Apr 09, 2026
Explainers Browser Fingerprinting and CAPTCHA: How Detection Works
How browser fingerprinting affects CAPTCHA challenges, what signals trigger CAPTCHAs, and how to reduce detection with Captcha AI.

How browser fingerprinting affects CAPTCHA challenges, what signals trigger CAPTCHAs, and how to reduce detect...

reCAPTCHA v2 Cloudflare Turnstile reCAPTCHA v3
Mar 23, 2026
Explainers GeeTest v3 Challenge-Response Workflow: Technical Deep Dive
A technical deep dive into Gee Test v 3's challenge-response workflow — the registration API, challenge token exchange, slider verification, and how Captcha AI...

A technical deep dive into Gee Test v 3's challenge-response workflow — the registration API, challenge token...

Automation Testing GeeTest v3
Mar 02, 2026