CAPSOLVER
Blog
How to Solve reCAPTCHA v3 in CrewAI Agents with CapSolver

How to Solve reCAPTCHA v3 in CrewAI Agents with CapSolver

Logo of CapSolver

Lucas Mitchell

How to use CapSolver

01-Sep-2026

TL;DR

  • A CrewAI reCAPTCHA v3 solver should be a narrow typed tool, not a general-purpose browser or arbitrary-URL function.
  • Resolve the target URL, site key, expected pageAction, and score policy from a server-side registry rather than from model-generated text.
  • Use CapSolver's documented reCAPTCHA v3 task parameters and keep Enterprise, proxy, and session settings explicit.
  • Submit the returned token inside trusted application code; return only a redacted status object to the CrewAI agent.
  • Treat the solver result as an intermediate step and verify that the intended page state changed before the crew continues.

Introduction

The safest way to solve reCAPTCHA v3 in CrewAI is to expose CapSolver through a typed, policy-controlled tool. CrewAI should decide when the task needs verification, but trusted application code should resolve the approved target, site key, page action, proxy mode, and score policy. CapSolver's reCAPTCHA v3 documentation defines the supported task types and parameters, while the user-provided Agent SDK maps structured tool calls to capsolver-core. The tool should submit the token server-side, verify the resulting page state, and give the crew a small result such as verified, review_required, or stopped. This design prevents URL drift, action guessing, secret leakage, duplicate solves, and false success signals.

Why reCAPTCHA v3 Needs a Different CrewAI Tool

reCAPTCHA v3 is score-based and usually runs without a visible checkbox. The target application invokes an action, receives a token, and evaluates that token on the server. A CrewAI workflow can therefore fail even when it never sees a visual challenge.

The common causes are operational rather than conversational:

  • the tool used the wrong site key;
  • the pageAction did not match the page's runtime action;
  • the token was submitted to a different route or browser state;
  • the task type did not match Standard or Enterprise;
  • the crew treated task completion as application verification;
  • the same step created several tokens without a state change.

The CapSolver reCAPTCHA blog contains supporting implementation guides, while the AI and automation FAQ helps define safe agent boundaries.

Separate Crew Roles from Solver Authority

A multi-agent crew works best when responsibility is explicit.

Role Allowed responsibility Must not control
Navigator Observe the approved application state API key, proxy credential, raw token
Verification planner Decide whether the approved step needs the tool Arbitrary URL or site key
CapSolver tool Resolve policy, create one task, submit token Unbounded retries or unrelated browsing
State validator Confirm expected route and semantic markers Business approval decisions
Reviewer Inspect redacted evidence on failure Secret session material

The model can choose a registered target ID. It should not construct the target URL or challenge parameters.

Use the Official CrewAI Tool Pattern

CrewAI's custom-tool documentation supports BaseTool with a Pydantic args_schema, the @tool decorator, typed results, and asynchronous tools for I/O-bound operations.

The user-provided CapSolver Agent documentation explains that capsolver-agent wraps capsolver-core: create_executor() creates the executor, and executor.execute("solve_captcha", args) dispatches the typed request to the core engine.

Install the documented packages:

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 crewai

export CAPSOLVER_API_KEY="CAP-..."

Keep keys in the runtime secret store. Do not place them in crew prompts, task descriptions, or tool results.

Define a Trusted Target Registry

python Copy
from dataclasses import dataclass

@dataclass(frozen=True)
class RecaptchaV3Policy:
    target_id: str
    website_url: str
    website_key: str
    page_action: str
    minimum_score: float
    enterprise: bool
    proxy_profile: str | None
    allowed_crew_role: str
    max_attempts: int = 1

TARGETS = {
    "approved_login_test": RecaptchaV3Policy(
        target_id="approved_login_test",
        website_url="https://approved.example.com/login",
        website_key="PUBLIC_SITE_KEY",
        page_action="login",
        minimum_score=0.7,
        enterprise=False,
        proxy_profile=None,
        allowed_crew_role="verification_specialist",
    )
}

The public site key is not an account secret, but it should still come from a trusted configuration so the model cannot redirect the tool.

Observe pageAction Instead of Guessing It

CapSolver's reCAPTCHA v3 documentation lists pageAction as an optional task field and explains that the value can be found in the page's grecaptcha.execute call.

python Copy
@dataclass(frozen=True)
class PageObservation:
    target_id: str
    current_url: str
    observed_action: str
    observed_site_key: str
    form_state: str
    observed_at: str


def validate_observation(
    observation: PageObservation,
    policy: RecaptchaV3Policy,
) -> None:
    if observation.current_url != policy.website_url:
        raise PermissionError("Observed URL does not match policy")
    if observation.observed_site_key != policy.website_key:
        raise ValueError("Observed site key does not match policy")
    if observation.observed_action != policy.page_action:
        raise ValueError("Observed page action does not match policy")
    if observation.form_state != "READY_FOR_VERIFICATION":
        raise ValueError("Application state is not ready")

The tool should reject mismatches rather than create a token for uncertain parameters.

Understand the CapSolver v3 Parameters

Parameter Purpose Policy rule
captcha_type Selects reCAPTCHA v3 in the Agent SDK Fixed to reCaptchaV3
website_url Page hosting the challenge Loaded from registry
website_key Public site key Loaded from registry and checked against page
page_action Runtime v3 action Must match observation
min_score Requested minimum score Set by target policy
enterprise Standard or Enterprise path Fixed by integration configuration
proxy Optional network identity Resolved from a secret profile if required

CapSolver documents Standard, Enterprise, proxy, and proxyless task variants. Its result can contain gRecaptchaResponse, user-agent data, and session values when the relevant mode is enabled.

The CapSolver products page helps confirm the supported task family before implementation.

Create a Typed CrewAI Tool

python Copy
import os
from typing import Literal

from crewai.tools import tool
from pydantic import BaseModel, Field
from capsolver_agent.schema import create_executor

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

class SolveRequest(BaseModel):
    target_id: str = Field(description="Registered target identifier")
    crew_role: str = Field(description="Role requesting verification")
    observed_action: str = Field(description="Action observed on the live page")
    observed_site_key: str = Field(description="Site key observed on the live page")
    state_id: str = Field(description="Opaque server-side application state identifier")

class SolveResult(BaseModel):
    status: Literal["verified", "review_required", "stopped"]
    target_id: str
    state_id: str
    reason: str
    task_attempted: bool

The result model deliberately excludes the token, API key, proxy, cookies, and raw provider response.

Resolve Secrets and Submit the Token Server-Side

python Copy
PROXY_VAULT = {
    "approved_proxy": os.environ.get("APPROVED_PROXY")
}

async def submit_token_and_verify(
    *,
    state_id: str,
    token: str,
    policy: RecaptchaV3Policy,
) -> bool:
    """Application-owned submit-and-check function."""
    response = await application_sessions.submit_recaptcha_v3(
        state_id=state_id,
        token=token,
        expected_action=policy.page_action,
    )
    return (
        response.current_url.startswith("https://approved.example.com/account")
        and response.semantic_marker == "AUTHENTICATED_ACCOUNT_PAGE"
        and response.challenge_present is False
    )

application_sessions represents your authorized browser or HTTP session service. The solver tool uses it, but the model does not receive its credentials.

Implement the Async Tool

python Copy
@tool("Solve approved reCAPTCHA v3", result_schema=SolveResult)
async def solve_approved_recaptcha_v3(
    target_id: str,
    crew_role: str,
    observed_action: str,
    observed_site_key: str,
    state_id: str,
) -> dict:
    """Solve one registered reCAPTCHA v3 step and verify application state."""
    policy = TARGETS.get(target_id)
    if policy is None:
        return SolveResult(
            status="stopped",
            target_id=target_id,
            state_id=state_id,
            reason="Unknown target",
            task_attempted=False,
        ).model_dump()

    if crew_role != policy.allowed_crew_role:
        return SolveResult(
            status="stopped",
            target_id=target_id,
            state_id=state_id,
            reason="Role is not permitted to call this tool",
            task_attempted=False,
        ).model_dump()

    if observed_action != policy.page_action:
        return SolveResult(
            status="review_required",
            target_id=target_id,
            state_id=state_id,
            reason="Observed action does not match target policy",
            task_attempted=False,
        ).model_dump()

    if observed_site_key != policy.website_key:
        return SolveResult(
            status="review_required",
            target_id=target_id,
            state_id=state_id,
            reason="Observed site key does not match target policy",
            task_attempted=False,
        ).model_dump()

    args = {
        "captcha_type": "reCaptchaV3",
        "website_url": policy.website_url,
        "website_key": policy.website_key,
        "page_action": policy.page_action,
        "min_score": policy.minimum_score,
        "enterprise": policy.enterprise,
    }
    if policy.proxy_profile:
        args["proxy"] = PROXY_VAULT[policy.proxy_profile]

    result = await executor.execute("solve_captcha", args)
    if not result.get("success"):
        return SolveResult(
            status="review_required",
            target_id=target_id,
            state_id=state_id,
            reason="CapSolver task did not complete",
            task_attempted=True,
        ).model_dump()

    solution = result.get("solution") or {}
    token = solution.get("token")
    if not token:
        return SolveResult(
            status="review_required",
            target_id=target_id,
            state_id=state_id,
            reason="Task result did not contain a token",
            task_attempted=True,
        ).model_dump()

    verified = await submit_token_and_verify(
        state_id=state_id,
        token=token,
        policy=policy,
    )
    return SolveResult(
        status="verified" if verified else "review_required",
        target_id=target_id,
        state_id=state_id,
        reason="Application state verified" if verified else "Application state not verified",
        task_attempted=True,
    ).model_dump()

This implementation keeps the credential inside trusted code and gives the crew only a policy-safe status.

Attach the Tool to One Agent

python Copy
from crewai import Agent, Crew, Process, Task

verification_agent = Agent(
    role="verification_specialist",
    goal="Complete only registered verification steps and report verified state",
    backstory=(
        "You operate approved verification tools. You never invent target IDs, "
        "site keys, actions, credentials, or success states."
    ),
    tools=[solve_approved_recaptcha_v3],
    allow_delegation=False,
    verbose=True,
)

verification_task = Task(
    description=(
        "For the registered target in the supplied observation, call the tool once "
        "only if the URL, site key, action, and state are confirmed. Return the "
        "structured status without secrets."
    ),
    expected_output="A structured verified, review_required, or stopped result.",
    agent=verification_agent,
)

crew = Crew(
    agents=[verification_agent],
    tasks=[verification_task],
    process=Process.sequential,
    verbose=True,
)

Do not attach the solver tool to every agent. Limiting it to one role makes authorization and auditing clearer.

Prevent Duplicate Tool Calls

python Copy
from datetime import datetime, timedelta, timezone

ATTEMPTS: dict[tuple[str, str], datetime] = {}


def claim_attempt(target_id: str, state_id: str) -> bool:
    key = (target_id, state_id)
    now = datetime.now(timezone.utc)
    prior = ATTEMPTS.get(key)
    if prior and now - prior < timedelta(minutes=2):
        return False
    ATTEMPTS[key] = now
    return True

Call claim_attempt() before executor.execute(). A repeated crew message should not create a second token for the same application state.

Keep the Token Out of Crew Memory

CrewAI memory, traces, and verbose logs may preserve tool output. Return only:

json Copy
{
  "status": "verified",
  "target_id": "approved_login_test",
  "state_id": "state_7c19",
  "reason": "Application state verified",
  "task_attempted": true
}

Never return the token, CapSolver API key, proxy value, browser cookie, raw HTML, password, or personal form data.

The CapSolver errors and troubleshooting FAQ can support provider-error classification without exposing the raw response to the crew.

Validate the Page After Submission

The validator should require several independent signals:

python Copy
@dataclass(frozen=True)
class StateCheck:
    expected_path_prefix: str
    required_marker: str
    forbidden_markers: tuple[str, ...]


def is_verified(page, check: StateCheck) -> bool:
    return (
        page.url.path.startswith(check.expected_path_prefix)
        and page.has_semantic_marker(check.required_marker)
        and not any(page.contains(marker) for marker in check.forbidden_markers)
        and page.http_status == 200
    )

A changed URL alone is not enough. Require the expected route, semantic marker, status, and absence of known challenge or error states.

Handle Enterprise and Session Modes Explicitly

CapSolver documents Enterprise variants and optional session mode. Do not let the crew infer these options.

python Copy
@dataclass(frozen=True)
class RecaptchaV3Policy:
    target_id: str
    website_url: str
    website_key: str
    page_action: str
    minimum_score: float
    enterprise: bool
    is_session: bool
    proxy_profile: str | None
    allowed_crew_role: str
    max_attempts: int = 1

If the approved target uses Enterprise, store that fact in policy. If session mode is needed, handle returned session values inside the application session service and keep them out of crew output.

Comparison Summary

Design Parameter integrity Secret safety Page-state assurance Recommendation
Model supplies URL, key, and action Low Low Low Avoid
Tool returns token to crew Medium Low Low Avoid
Registry-resolved tool submits and verifies High High High Preferred
Human-only verification step High High High Use for sensitive or uncertain states

The preferred design gives the model decision authority but keeps execution authority inside trusted code.

Add Operational Metrics

Track redacted fields such as:

  • target ID;
  • crew role;
  • observed action match;
  • task attempted;
  • provider status category;
  • submission duration;
  • page verified;
  • manual-review reason.
python Copy
SAFE_FIELDS = {
    "target_id",
    "crew_role",
    "action_match",
    "task_attempted",
    "provider_category",
    "duration_ms",
    "verified",
    "review_reason",
}


def safe_event(event: dict) -> dict:
    return {key: event[key] for key in SAFE_FIELDS if key in event}

The CapSolver status page can help distinguish provider availability from application-specific failures.

Test the Tool Before Production

python Copy
import pytest

@pytest.mark.asyncio
async def test_unknown_target_stops_before_task():
    result = await solve_approved_recaptcha_v3.run(
        target_id="unknown",
        crew_role="verification_specialist",
        observed_action="login",
        observed_site_key="x",
        state_id="state-1",
    )
    assert result["status"] == "stopped"
    assert result["task_attempted"] is False

@pytest.mark.asyncio
async def test_action_mismatch_requests_review():
    result = await solve_approved_recaptcha_v3.run(
        target_id="approved_login_test",
        crew_role="verification_specialist",
        observed_action="checkout",
        observed_site_key="PUBLIC_SITE_KEY",
        state_id="state-2",
    )
    assert result["status"] == "review_required"
    assert result["task_attempted"] is False

Also test duplicate-attempt blocking, secret redaction, missing token handling, Enterprise policy, and page-verification failure.

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

Production Checklist

  • Register every target URL, site key, action, score, and Enterprise setting server-side.
  • Let one CrewAI role call the solver tool.
  • Validate the observed URL, site key, action, and state before task creation.
  • Use CapSolver's documented reCAPTCHA v3 parameters.
  • Submit the token inside trusted application code.
  • Return only a redacted structured result to the crew.
  • Permit one attempt per observed application state.
  • Verify route, semantic marker, status, and challenge absence.
  • Keep keys, tokens, proxy data, cookies, and form data out of memory and traces.
  • Route uncertain or sensitive states to a human reviewer.

The CapSolver CAPTCHA-solving FAQ provides additional task-lifecycle guidance.

Responsible Use

Use a CrewAI reCAPTCHA v3 solver only on sites you own, test, or have explicit permission to automate. Respect terms, rate limits, authentication boundaries, privacy obligations, and internal access policies. A public site key does not grant permission to access a protected workflow. Keep consequential submissions, payments, account changes, and sensitive data decisions behind separate approval controls.

Conclusion

A production CrewAI reCAPTCHA v3 solver should be narrow, typed, and policy-controlled. CrewAI can identify the need for verification, but trusted code must resolve the target, site key, page action, score, Enterprise mode, and network settings. CapSolver should run once for a validated state, the token should be submitted server-side, and the crew should receive only a redacted result after the intended page is verified.

Start an authorized implementation with CapSolver, test it on a controlled page, and add parameter, duplicate-call, redaction, and page-state tests before production use.

FAQ

Can CrewAI call CapSolver directly?

CrewAI can call a typed tool that delegates to the documented CapSolver Agent executor. Keep target resolution, secrets, token submission, and verification inside trusted application code.

Which reCAPTCHA v3 parameters are required?

The target URL and site key are required. The page action, minimum score, Enterprise setting, session mode, and proxy depend on the approved target configuration.

Should the model choose the page action?

No. Observe the action from the live approved page and compare it with a server-side policy value.

Should the CapSolver token be returned to the crew?

No. Submit it inside trusted code and return only a redacted verified, review-required, or stopped status.

How many attempts should one CrewAI task make?

Use one attempt per observed application state by default. A second attempt should require a new observation and an explicit policy decision.

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