CAPSOLVER
Blog
How to Solve reCAPTCHA v3 in LlamaIndex Agents

How to Solve reCAPTCHA v3 in LlamaIndex Agents

Logo of CapSolver

Lucas Mitchell

How to use CapSolver

28-Aug-2026

TL;DR

  • Wrap a narrow async CapSolver function with LlamaIndex FunctionTool; do not expose API keys, proxy credentials, cookies, or raw browser objects to the model.
  • Read websiteURL, websiteKey, and pageAction from the live authorized workflow. Never let the agent invent them.
  • Use ReCaptchaV3TaskProxyLess for server-proxy token mode or ReCaptchaV3Task when an approved proxy must be supplied.
  • Treat a returned token as short-lived runtime data, submit it immediately through trusted code, and verify the application state before continuing.
  • Limit solving attempts, route repeated failures to operator review, and log only redacted metadata.

Introduction

A reliable LlamaIndex reCAPTCHA v3 solver is a typed recovery tool, not an open-ended browsing capability. The LlamaIndex agent should decide when an approved task is blocked, while trusted code validates the target, reads the exact site key and action from the current page, calls CapSolver, submits the token, and verifies the expected state. This separation matters because reCAPTCHA v3 runs without an interactive checkbox and evaluates an action-specific request. A token created for the wrong URL or pageAction can be rejected even when the API call itself succeeds. This guide shows the official CapSolver task fields, an async LlamaIndex FunctionTool, server-side policy controls, session-mode handling, structured results, bounded retries, browser verification, and production observability.

Understand the LlamaIndex Tool Boundary

LlamaIndex's official tools documentation explains that FunctionTool wraps synchronous or asynchronous Python functions and can infer a function schema. It also notes that tool names, descriptions, and argument descriptions strongly influence how a model selects and calls a tool.

For a LlamaIndex reCAPTCHA v3 solver, keep the tool narrow:

text Copy
LlamaIndex agent
    ↓ chooses a typed tool
FunctionTool wrapper
    ↓ validates trusted references
CapSolver executor
    ↓ returns a short-lived solution
Browser service
    ↓ submits and verifies
LlamaIndex workflow resumes

The CapSolver AI Agents documentation describes the same division of labor: the model decides, the adapter exposes schemas, and the core executes supported challenge work.

Know the Required reCAPTCHA v3 Parameters

CapSolver's reCAPTCHA v3 documentation defines four task types:

Task type Proxy mode Enterprise
ReCaptchaV3TaskProxyLess CapSolver server proxy No
ReCaptchaV3Task Your approved proxy No
ReCaptchaV3EnterpriseTaskProxyLess CapSolver server proxy Yes
ReCaptchaV3EnterpriseTask Your approved proxy Yes

The base fields are:

Field Requirement Trusted source
websiteURL Required Current authorized page URL
websiteKey Required Live page configuration
pageAction Usually required for v3 The page's grecaptcha.execute action
proxy Required for non-proxyless task Server-side approved proxy profile
enterprisePayload Conditional Live Enterprise configuration
isSession Conditional Target-specific approved workflow

Google's reCAPTCHA v3 guide describes action names as part of the integration. The action observed on the page should be preserved exactly.

The CapSolver reCAPTCHA blog contains additional troubleshooting and implementation guides.

Do Not Let the Model Invent Target Parameters

Pass references to server-side state, not arbitrary values.

python Copy
from dataclasses import dataclass
from urllib.parse import urlparse

@dataclass(frozen=True)
class CaptchaContext:
    context_id: str
    website_url: str
    website_key: str
    page_action: str
    enterprise: bool = False
    proxy_profile: str | None = None
    session_mode: bool = False

TRUSTED_CONTEXTS: dict[str, CaptchaContext] = {}
ALLOWED_HOSTS = {"staging.example.com", "portal.example.org"}


def get_trusted_context(context_id: str) -> CaptchaContext:
    context = TRUSTED_CONTEXTS.get(context_id)
    if context is None:
        raise ValueError("Unknown CAPTCHA context")

    host = urlparse(context.website_url).hostname
    if host not in ALLOWED_HOSTS:
        raise PermissionError("Target is outside the approved host policy")

    if not context.website_key or not context.page_action:
        raise ValueError("Trusted context is missing required v3 parameters")

    return context

The model receives only context_id. The browser service owns the current page, site key, action, and proxy binding.

Install the Supported Packages

The user-provided CapSolver Agent documentation specifies installing the core package before the agent package:

bash Copy
pip install git+https://github.com/capsolver-ai/capsolver-core.git
pip install git+https://github.com/capsolver-ai/capsolver-agent.git
pip install llama-index-core

Set the API key in the runtime environment:

bash Copy
export CAPSOLVER_API_KEY="your-capsolver-api-key"

Do not paste the key into prompts, notebooks, scenario datasets, or traces. The CapSolver AI and automation FAQ explains the integration model.

Create the Server-Side CapSolver Executor

capsolver-agent provides create_executor() for the model–adapter–core boundary.

python Copy
import os
from capsolver_agent.schema import create_executor

executor = create_executor(
    api_key=os.environ["CAPSOLVER_API_KEY"],
    default_timeout=120,
)

The executor dispatches solve_captcha to CapSolver Core and returns a structured result. Keep it in trusted application code.

Write a Narrow Async Solve Function

The function resolves the trusted context, selects the official task type, and invokes the executor.

python Copy
from typing import Annotated

async def solve_recaptcha_v3(
    context_id: Annotated[
        str,
        "Opaque ID for a trusted, current browser CAPTCHA context"
    ],
) -> dict:
    """Solve reCAPTCHA v3 for an approved browser context.

    Use only when the current workflow reports a supported reCAPTCHA v3
    checkpoint. Never guess or modify the target URL, site key, or action.
    """
    context = get_trusted_context(context_id)

    captcha_type = (
        "reCaptchaV3Enterprise"
        if context.enterprise
        else "reCaptchaV3"
    )

    args = {
        "captcha_type": captcha_type,
        "website_url": context.website_url,
        "website_key": context.website_key,
        "page_action": context.page_action,
    }

    if context.proxy_profile:
        args["proxy"] = resolve_proxy(context.proxy_profile)

    result = await executor.execute("solve_captcha", args)
    if not result.get("success"):
        return {
            "success": False,
            "context_id": context_id,
            "error": normalize_error(result.get("error")),
        }

    solution = result.get("solution") or {}
    token = solution.get("token")
    if not token:
        return {
            "success": False,
            "context_id": context_id,
            "error": "solution did not contain a token",
        }

    receipt = await submit_solution_and_verify(
        context_id=context_id,
        token=token,
        session_cookie=extract_session_cookie(solution),
    )

    return {
        "success": receipt["verified"],
        "context_id": context_id,
        "verified": receipt["verified"],
        "next_state": receipt["next_state"],
    }

resolve_proxy, normalize_error, and submit_solution_and_verify are application-owned policy adapters. They should not be visible to the model.

Wrap the Function with LlamaIndex FunctionTool

python Copy
from llama_index.core.tools import FunctionTool

tool = FunctionTool.from_defaults(
    async_fn=solve_recaptcha_v3,
    name="solve_recaptcha_v3",
    description=(
        "Solve reCAPTCHA v3 for an approved current browser context. "
        "Input must be an opaque context_id supplied by the browser service. "
        "Do not call for unsupported pages or unapproved hosts."
    ),
)

Inspect the schema during development:

python Copy
schema = tool.metadata.get_parameters_dict()
print(schema)

This follows LlamaIndex's documented FunctionTool pattern while reducing the model's argument surface to one opaque identifier.

Attach the Tool to a LlamaIndex Agent

python Copy
from llama_index.core.agent.workflow import FunctionAgent

agent = FunctionAgent(
    llm=llm,
    tools=[tool],
    system_prompt=(
        "Operate only approved browser workflows. When the browser service "
        "reports a supported reCAPTCHA v3 checkpoint, call "
        "solve_recaptcha_v3 with the supplied context_id. Call once. "
        "Continue only when verified=true; otherwise request review."
    ),
)

Run the workflow with a trusted browser observation:

python Copy
response = await agent.run(
    "The approved staging workflow is waiting at a reCAPTCHA v3 "
    "checkpoint. Use context_id ctx_7f19 and continue only if verified."
)

The agent never sees the API key, raw proxy, token, or cookie.

Read pageAction from the Live Page

A reliable LlamaIndex reCAPTCHA v3 solver should not reuse a generic action such as login across every target. The browser service should read the target's current integration.

python Copy
async def collect_v3_context(page, context_id: str) -> CaptchaContext:
    website_url = page.url
    host = urlparse(website_url).hostname
    if host not in ALLOWED_HOSTS:
        raise PermissionError("Unapproved target")

    values = await page.evaluate("""
    () => {
      const scripts = Array.from(document.scripts)
        .map(s => s.textContent || '')
        .join('\n');

      const siteKey =
        document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')
        || null;

      const actionMatch = scripts.match(
        /grecaptcha(?:\.enterprise)?\.execute\([^,]+,\s*\{\s*action:\s*['\"]([^'\"]+)/
      );

      return {
        siteKey,
        pageAction: actionMatch ? actionMatch[1] : null,
        enterprise: scripts.includes('grecaptcha.enterprise')
      };
    }
    """)

    if not values["siteKey"] or not values["pageAction"]:
        raise RuntimeError("Could not read required v3 parameters")

    return CaptchaContext(
        context_id=context_id,
        website_url=website_url,
        website_key=values["siteKey"],
        page_action=values["pageAction"],
        enterprise=values["enterprise"],
    )

For complex integrations, use the CapSolver extension guide to inspect page parameters during approved development and testing.

Handle Session Mode Carefully

CapSolver's official v3 documentation notes that some targets can return recaptcha-ca-t when isSession is enabled. Treat it as sensitive, short-lived session material.

python Copy
SESSION_KEYS = {
    "recaptcha-ca-t",
    "recaptcha_ca_t",
}


def extract_session_cookie(solution: dict) -> str | None:
    raw = solution.get("raw") or {}
    for key in SESSION_KEYS:
        value = solution.get(key) or raw.get(key)
        if value:
            return value
    return None

Only enable session mode when the target integration requires it and the workflow is authorized. Store the value in process memory or short-lived encrypted storage; never place it in the LlamaIndex context.

Submit and Verify in Trusted Browser Code

Google's server-side verification documentation explains that a site validates the token on its backend. Your automation should submit the token through the same approved application flow, then verify the resulting page state.

python Copy
async def submit_solution_and_verify(
    context_id: str,
    token: str,
    session_cookie: str | None,
) -> dict:
    browser_state = BROWSER_CONTEXTS[context_id]
    page = browser_state.page

    if session_cookie:
        await browser_state.context.add_cookies([{
            "name": "recaptcha-ca-t",
            "value": session_cookie,
            "domain": urlparse(page.url).hostname,
            "path": "/",
            "secure": True,
        }])

    await page.evaluate(
        """({ token }) => {
          let input = document.querySelector(
            'textarea[name="g-recaptcha-response"]'
          );
          if (!input) {
            input = document.createElement('textarea');
            input.name = 'g-recaptcha-response';
            input.style.display = 'none';
            document.body.appendChild(input);
          }
          input.value = token;
          input.dispatchEvent(new Event('change', { bubbles: true }));
        }""",
        {"token": token},
    )

    await trigger_trusted_callback(page, browser_state.callback_name)

    try:
        await page.locator(browser_state.success_selector).wait_for(
            state="visible",
            timeout=15000,
        )
        return {"verified": True, "next_state": "continue"}
    except Exception:
        return {"verified": False, "next_state": "operator_review"}

Callback discovery is target-specific. Capture it in the trusted browser context rather than asking the model to generate JavaScript.

The CapSolver reCAPTCHA response API guide explains common response handling patterns.

Enforce One Attempt and Explicit States

python Copy
from enum import Enum

class RecoveryState(str, Enum):
    DETECTED = "detected"
    SOLVING = "solving"
    VERIFIED = "verified"
    REVIEW_REQUIRED = "review_required"

ATTEMPTS: dict[str, int] = {}

async def guarded_solve(context_id: str) -> dict:
    attempts = ATTEMPTS.get(context_id, 0)
    if attempts >= 1:
        return {
            "success": False,
            "context_id": context_id,
            "next_state": RecoveryState.REVIEW_REQUIRED,
            "error": "recovery budget exhausted",
        }

    ATTEMPTS[context_id] = attempts + 1
    return await solve_recaptcha_v3(context_id)

A repeated call often signals stale parameters, wrong action, expired browser state, or an unsupported path. Stop the loop and collect diagnostics.

Record Redacted Observability

Log operational metadata, not secrets.

python Copy
from datetime import datetime, timezone


def recovery_event(context: CaptchaContext, result: dict) -> dict:
    return {
        "event": "recaptcha_v3_recovery",
        "context_id": context.context_id,
        "host": urlparse(context.website_url).hostname,
        "page_action": context.page_action,
        "enterprise": context.enterprise,
        "session_mode": context.session_mode,
        "success": result.get("success", False),
        "next_state": str(result.get("next_state")),
        "observed_at": datetime.now(timezone.utc).isoformat(),
    }

Do not log websiteKey if your policy treats it as configuration, and never log solution tokens, session cookies, API keys, raw proxies, or full private page HTML.

The CapSolver errors FAQ can help normalize error categories.

Bonus Code: Use code WEBS at CapSolver Dashboard to get an extra 5% bonus on every recharge.

Comparison Summary

Integration pattern Model input Secret exposure risk Best use
Model supplies all task fields URL, key, action, proxy High Avoid in production
Typed FunctionTool with validated fields Explicit fields Medium Controlled prototypes
Opaque context ID plus server validation Context reference only Low Production LlamaIndex workflows
Browser-only core solve_on_page No model parameters Lowest Deterministic Playwright recovery

The opaque-context pattern gives the LlamaIndex agent enough control to request recovery without letting it rewrite sensitive or target-specific parameters.

Production Checklist

  • Keep the API key and proxy profiles in a secret manager.
  • Allow only approved hosts and exact workflow purposes.
  • Read websiteKey and pageAction from the current live page.
  • Match Enterprise and session settings to the target integration.
  • Submit the token immediately through trusted browser code.
  • Verify the expected application state before continuing.
  • Permit one solve attempt, then route to operator review.
  • Redact tokens, cookies, proxies, and credentials from traces.
  • Re-test the tool schema whenever the SDK or prompt changes.

The CapSolver products page lists supported solution categories, while the CapSolver AI blog covers related agent integration patterns.

Responsible Use

Use this workflow only on applications you own, test, or have explicit permission to automate. Technical capability does not grant access rights. Respect target terms, rate limits, privacy requirements, and authentication boundaries. Do not use an agent tool to access private accounts, restricted records, or third-party workflows without authorization. Keep high-impact actions such as submission, payment, booking, and account changes behind a separate policy and confirmation step.

Conclusion

A production LlamaIndex reCAPTCHA v3 solver should expose one narrow, typed recovery function. The browser service supplies a trusted context ID, server-side code preserves the exact URL, site key, action, Enterprise mode, and proxy policy, CapSolver returns a short-lived solution, and the browser verifies the expected state before the agent continues.

Start an approved LlamaIndex integration with CapSolver, test it on a controlled staging workflow, and add parameter-grounding and retry assertions before production.

FAQ

Does reCAPTCHA v3 require a checkbox click?

No. reCAPTCHA v3 is score-based and usually runs in the background. The workflow must preserve the target's site key, URL, and action.

Why is pageAction important?

The action identifies the operation being evaluated, such as login or submit. Use the exact action read from the live integration rather than a generic value.

Should the LlamaIndex agent receive the token?

Prefer server-side submission and return only a verified status. A token is short-lived runtime data and should not enter model context or logs.

When should session mode be enabled?

Enable it only when the authorized target requires the returned session value. Keep that value in short-lived encrypted runtime storage.

What should happen after a failed attempt?

Stop after the configured attempt budget, record a redacted diagnostic event, refresh trusted page parameters if appropriate, and route the workflow to operator review.

Compliance Disclaimer: The information provided on this blog is for informational purposes only. CapSolver is committed to compliance with all applicable laws and regulations. The use of the CapSolver network for illegal, fraudulent, or abusive activities is strictly prohibited and will be investigated. Our captcha-solving solutions enhance user experience while ensuring 100% compliance in helping solve captcha difficulties during public data crawling. We encourage responsible use of our services. For more information, please visit our Terms of Service and Privacy Policy.

More