AI agents
Browser Use
Add a custom action to Browser Use that solves a reCAPTCHA image challenge in the current tab with the Solvecha API, or load the Solvecha extension.
On this page
Browser Use lets an LLM drive a browser. There are two ways to add Solvecha.
#Option A: the extension
Start a Chrome that has the Solvecha extension and a debugging port, save your key in the extension, and give Browser Use the address:
from browser_use import Agent, Browser, ChatBrowserUse
browser = Browser(cdp_url="http://127.0.0.1:9222")
agent = Agent(task="Open the page and log in", llm=ChatBrowserUse(), browser=browser)
await agent.run()The extension solves the challenge by itself. See Hermes Agent for the Chrome command.
#Option B: a custom action
This action takes a screenshot of the challenge area and sends it to the API. It returns the tiles to click. The agent then clicks them with its normal click action. It uses the REST API with httpx, so the key check and billing are the same as everywhere.
import asyncio
import base64
import os
import httpx
from browser_use import ActionResult, Agent, BrowserSession, ChatBrowserUse, Tools
API = "https://api.solvecha.com"
KEY = os.environ["SOLVECHA_API_KEY"]
tools = Tools()
@tools.action(
description=(
"Solve a reCAPTCHA v2 image challenge that is visible in the current tab. "
"Pass the instruction text (for example 'Select all images with buses') and the grid "
"('3x3' or '4x4'). Returns the tile numbers to click, counted from 1, left to right, top to bottom."
)
)
async def solve_recaptcha(task: str, grid: str, browser_session: BrowserSession) -> ActionResult:
# Screenshot of the page. Crop to the challenge if you know its position.
png = await browser_session.take_screenshot()
image = base64.b64encode(png).decode() if isinstance(png, bytes) else png
headers = {"Authorization": f"Bearer {KEY}"}
async with httpx.AsyncClient(base_url=API, headers=headers, timeout=30) as client:
job = (await client.post(
"/v1/recognition/recaptcha",
json={"task": task, "grid": grid, "image_data": [image]},
)).json()
if "data" not in job:
return ActionResult(error=f"Solvecha error {job.get('error')}: {job.get('message')}")
for _ in range(40):
await asyncio.sleep(1)
answer = (await client.get("/v1/recognition/recaptcha", params={"id": job["data"]})).json()
if answer.get("error") == 14: # still working
continue
if "data" in answer:
tiles = [i + 1 for i, picked in enumerate(answer["data"]) if picked]
return ActionResult(extracted_content=f"Click tiles {tiles}, then press Verify.")
return ActionResult(error=f"Solvecha error {answer.get('error')}: {answer.get('message')}")
return ActionResult(error="No answer in 40 seconds")
agent = Agent(task="...", llm=ChatBrowserUse(), tools=tools)Restrict the action to the sites you automate with allowed_domains in the Browser Use action settings if you want to be strict.
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.