Tutorials

Solving reCAPTCHA v2 with Python Requests and CaptchaAI

Python's requests library is the most common HTTP client for automation. This guide shows you exactly how to solve reCAPTCHA v2 challenges using requests and CaptchaAI's API — from extracting the sitekey to submitting the solved token.


Prerequisites

pip install requests

You need:

  • A CaptchaAI API key from captchaai.com
  • The target page URL
  • The reCAPTCHA sitekey (we'll show how to extract it)

Step 1: Extract the reCAPTCHA sitekey

Every reCAPTCHA v2 widget has a sitekey embedded in the page HTML:

import re
import requests

def extract_recaptcha_sitekey(url):
    """Extract reCAPTCHA v2 sitekey from page HTML."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
    }
    response = requests.get(url, headers=headers, timeout=15)

    # Pattern 1: data-sitekey attribute
    match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', response.text)
    if match:
        return match.group(1)

    # Pattern 2: grecaptcha.render config
    match = re.search(r"sitekey['\"]?\s*:\s*['\"]([A-Za-z0-9_-]{40})['\"]", response.text)
    if match:
        return match.group(1)

    # Pattern 3: reCAPTCHA API URL parameter
    match = re.search(r"google\.com/recaptcha/api\.js\?.*?render=([A-Za-z0-9_-]{40})", response.text)
    if match:
        return match.group(1)

    return None


# Usage
sitekey = extract_recaptcha_sitekey("https://example.com/login")
print(f"Sitekey: {sitekey}")

Step 2: Submit to CaptchaAI

Send the sitekey and page URL to CaptchaAI:

import requests

API_KEY = "YOUR_API_KEY"

def submit_recaptcha(sitekey, page_url):
    """Submit reCAPTCHA v2 solving task to CaptchaAI."""
    response = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": page_url,
        "json": 1,
    })

    data = response.json()

    if data.get("status") != 1:
        raise Exception(f"Submit failed: {data.get('request', 'Unknown error')}")

    return data["request"]  # Task ID


task_id = submit_recaptcha("6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", "https://example.com/login")
print(f"Task ID: {task_id}")

Step 3: Poll for the result

CaptchaAI solves the challenge in the background. Poll every 5 seconds:

import time

def poll_result(task_id, timeout=120):
    """Poll CaptchaAI for the solved token."""
    start = time.time()

    while time.time() - start < timeout:
        time.sleep(5)

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

        data = response.json()

        if data.get("status") == 1:
            return data["request"]  # Solved token

        if data.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
            raise Exception("CAPTCHA could not be solved")

        if data.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Unexpected response: {data}")

    raise TimeoutError(f"Solve timed out after {timeout}s")


token = poll_result(task_id)
print(f"Token: {token[:50]}...")

Complete working example

Full end-to-end code that extracts, solves, and submits:

import re
import time
import requests

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/login"


def extract_sitekey(url, session):
    """Extract reCAPTCHA v2 sitekey from the page."""
    response = session.get(url, timeout=15)
    match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', response.text)
    if not match:
        raise ValueError("reCAPTCHA sitekey not found on page")
    return match.group(1)


def solve_recaptcha(sitekey, page_url):
    """Submit and poll CaptchaAI for reCAPTCHA v2 solution."""
    # Submit
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": page_url,
        "json": 1,
    })

    data = submit.json()
    if data.get("status") != 1:
        raise Exception(f"Submit error: {data.get('request')}")

    task_id = data["request"]
    print(f"Task submitted: {task_id}")

    # Poll
    for attempt in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1,
        }).json()

        if result.get("status") == 1:
            return result["request"]
        if result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
            raise Exception("Unsolvable CAPTCHA")

    raise TimeoutError("Solve timed out")


def submit_form_with_token(session, form_url, token, extra_data=None):
    """Submit the form with the solved reCAPTCHA token."""
    form_data = {
        "g-recaptcha-response": token,
    }
    if extra_data:
        form_data.update(extra_data)

    response = session.post(form_url, data=form_data, timeout=15)
    return response


# --- Main flow ---
session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 Chrome/120.0.0.0",
    "Accept": "text/html,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
})

# 1. Get the page and extract sitekey
sitekey = extract_sitekey(TARGET_URL, session)
print(f"Sitekey: {sitekey}")

# 2. Solve reCAPTCHA
token = solve_recaptcha(sitekey, TARGET_URL)
print(f"Token received: {token[:50]}...")

# 3. Submit form with token
response = submit_form_with_token(session, TARGET_URL, token, {
    "username": "user@example.com",
    "password": "password123",
})
print(f"Form submission status: {response.status_code}")

Error handling patterns

Common API errors

Error Meaning Fix
ERROR_WRONG_USER_KEY Invalid API key Check your API key
ERROR_ZERO_BALANCE Account balance is zero Add funds
ERROR_CAPTCHA_UNSOLVABLE Could not solve this CAPTCHA Retry with new task
ERROR_TOO_MUCH_REQUESTS Sending tasks too fast Add delay between submissions
ERROR_WRONG_GOOGLEKEY Invalid sitekey Re-extract from page
ERROR_PAGEURL Invalid page URL Ensure URL is complete (https://)

Production-ready error handling

import time
import requests

API_KEY = "YOUR_API_KEY"

class RecaptchaSolveError(Exception):
    pass

def solve_recaptcha_v2(sitekey, page_url, max_retries=3):
    """Solve reCAPTCHA v2 with retry logic."""
    for attempt in range(1, max_retries + 1):
        try:
            # Submit
            submit = requests.post(
                "https://ocr.captchaai.com/in.php",
                data={
                    "key": API_KEY,
                    "method": "userrecaptcha",
                    "googlekey": sitekey,
                    "pageurl": page_url,
                    "json": 1,
                },
                timeout=30,
            )
            submit.raise_for_status()
            submit_data = submit.json()

            if submit_data.get("status") != 1:
                error = submit_data.get("request", "Unknown")
                if error in ("ERROR_WRONG_USER_KEY", "ERROR_ZERO_BALANCE"):
                    raise RecaptchaSolveError(f"Fatal error: {error}")
                raise RecaptchaSolveError(f"Submit error: {error}")

            task_id = submit_data["request"]

            # Poll
            for _ in range(30):
                time.sleep(5)
                result = requests.get(
                    "https://ocr.captchaai.com/res.php",
                    params={
                        "key": API_KEY,
                        "action": "get",
                        "id": task_id,
                        "json": 1,
                    },
                    timeout=30,
                ).json()

                if result.get("status") == 1:
                    return result["request"]

                if result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
                    break  # Retry with new task

            print(f"Attempt {attempt} failed, retrying...")

        except requests.RequestException as e:
            print(f"Network error on attempt {attempt}: {e}")
            if attempt == max_retries:
                raise RecaptchaSolveError(f"Network error after {max_retries} attempts")
            time.sleep(10)

    raise RecaptchaSolveError(f"Failed after {max_retries} attempts")

Working with invisible reCAPTCHA v2

Invisible reCAPTCHA v2 works the same way — just add invisible=1:

submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": page_url,
    "invisible": 1,  # Add this for invisible reCAPTCHA v2
    "json": 1,
})

Token submission patterns

Different sites expect the token in different ways:

Pattern 1: Form POST (most common)

response = session.post(form_url, data={
    "g-recaptcha-response": token,
    "email": "user@example.com",
})

Pattern 2: JSON API

response = session.post(api_url, json={
    "captchaToken": token,
    "email": "user@example.com",
})

Pattern 3: Hidden field in HTML form

# Some sites use a different field name — check form HTML
response = session.post(form_url, data={
    "g-recaptcha-response": token,
    "recaptcha_token": token,  # Some sites duplicate the field
    "username": "user",
})

Troubleshooting

Symptom Cause Fix
"Invalid sitekey" error Sitekey extracted incorrectly Verify against page source
Token accepted but form fails Missing form fields Submit all required form fields
Token rejected by server Token expired (>120s) Reduce time between solve and submit
"CAPCHA_NOT_READY" for >2 min High queue load Wait longer or retry
SSL certificate error Corporate proxy or outdated certs Add verify=False (dev only)

Frequently asked questions

How long does solving take?

Typical solve time is 10-30 seconds. Invisible reCAPTCHA v2 is usually faster. Plan for up to 120 seconds in worst case.

Can I use this with reCAPTCHA v3?

No. reCAPTCHA v3 uses method=userrecaptcha but requires additional parameters (version=v3, min_score, action). See the reCAPTCHA v3 guide.

Do I need to maintain a session?

Yes. Using requests.Session() preserves cookies between requests, which is important for sites that validate the reCAPTCHA token against the session.

How fast can I submit tasks?

CaptchaAI has no published rate limit per key, but submitting more than 10 tasks per second may trigger ERROR_TOO_MUCH_REQUESTS. Add a 100ms delay between submissions for safety.


Summary

Solving reCAPTCHA v2 with Python requests and CaptchaAI is a three-step process: extract the sitekey from the page, submit to CaptchaAI's userrecaptcha method, and poll for the token. Use requests.Session() for cookie persistence and submit the token as g-recaptcha-response in your form POST.

Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.