LangChain, CrewAI and OpenAI Agents

AI agents

Give LangChain, CrewAI, the OpenAI Agents SDK or LlamaIndex agents a captcha tool, either as ready tool code or through the Solvecha MCP server.

On this page

Every framework below can use Solvecha in two ways: through the MCP server, or with a small tool that calls the REST API. The MCP way needs no tool code.

#Through MCP

OpenAI Agents SDK

OpenAI Agents SDK
import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async with MCPServerStreamableHttp(
    name="solvecha",
    params={
        "url": "https://api.solvecha.com/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['SOLVECHA_API_KEY']}"},
        "timeout": 100,
    },
    client_session_timeout_seconds=100,
) as server:
    agent = Agent(name="Browser agent", instructions="Use solvecha tools for captcha images.", mcp_servers=[server])
    result = await Runner.run(agent, "Solve the captcha in this screenshot: ...")

LangChain

LangChain
import os
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "solvecha": {
        "transport": "streamable_http",
        "url": "https://api.solvecha.com/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['SOLVECHA_API_KEY']}"},
    }
})
tools = await client.get_tools()  # pass these tools to your agent

Google ADK

Google ADK
import os
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams

agent = LlmAgent(
    model="gemini-flash-latest",
    name="browser_agent",
    instruction="Use the solvecha tools for captcha images.",
    tools=[McpToolset(connection_params=StreamableHTTPConnectionParams(
        url="https://api.solvecha.com/mcp",
        headers={"Authorization": f"Bearer {os.environ['SOLVECHA_API_KEY']}"},
    ))],
)

#As a plain tool

This function solves a reCAPTCHA grid from a PNG file or base64 text. It uses only requests. Wrap it with the decorator of your framework.

solvecha_tool.py
import base64
import os
import time

import requests

API = "https://api.solvecha.com"


def solve_recaptcha_grid(task: str, grid: str, image_base64: str) -> list[int]:
    """Solve a reCAPTCHA v2 image challenge.

    Args:
        task: The instruction text, for example 'Select all images with buses'.
        grid: '3x3' or '4x4'.
        image_base64: One base64 picture of the whole grid.

    Returns the tile numbers to click, counted from 1, left to right, top to bottom.
    """
    headers = {"Authorization": f"Bearer {os.environ['SOLVECHA_API_KEY']}"}
    job = requests.post(f"{API}/v1/recognition/recaptcha", headers=headers, timeout=30,
                        json={"task": task, "grid": grid, "image_data": [image_base64]}).json()
    if "data" not in job:
        raise RuntimeError(f"Solvecha error {job.get('error')}: {job.get('message')}")
    for _ in range(40):
        time.sleep(1)
        answer = requests.get(f"{API}/v1/recognition/recaptcha", headers=headers, timeout=30,
                              params={"id": job["data"]}).json()
        if answer.get("error") == 14:  # still working
            continue
        if "data" in answer:
            return [i + 1 for i, picked in enumerate(answer["data"]) if picked]
        raise RuntimeError(f"Solvecha error {answer.get('error')}: {answer.get('message')}")
    raise TimeoutError("No answer in 40 seconds")

LangChain

LangChain
from langchain_core.tools import tool

solve_tool = tool(solve_recaptcha_grid)  # the docstring becomes the tool description

CrewAI

CrewAI
from crewai.tools import tool

@tool("Solve reCAPTCHA grid")
def solve_tool(task: str, grid: str, image_base64: str) -> str:
    """Solve a reCAPTCHA v2 image challenge. Returns the tile numbers to click."""
    return str(solve_recaptcha_grid(task, grid, image_base64))

OpenAI Agents SDK

OpenAI Agents SDK
from agents import function_tool

solve_tool = function_tool(solve_recaptcha_grid)

LlamaIndex

LlamaIndex
from llama_index.core.tools import FunctionTool

solve_tool = FunctionTool.from_defaults(fn=solve_recaptcha_grid)

A model cannot pass a large picture reliably as a tool argument in every framework. If your agent has trouble with long base64 text, give the tool a file path instead and read the file inside the function.

See reCAPTCHA image grids for the request and answer format, and Errors for the codes.

Solvecha is an independent service. It is not affiliated with NopeCHA, 2Captcha, CapSolver, Google or CloakHQ. Their names describe compatibility or recommendations only. Figures come from our own tests, see the compare page.

    ↑↓ to moveEnter to open