How to Handle reCAPTCHA in LangChain Agents with CapSolver
LangChain agents are increasingly used for real browser workflows: collecting public web data, submitting forms, testing user journeys, and coordinating multi-step automation tasks. In those workflows, one practical interruption appears often: reCAPTCHA v2.
For developers building agents, the important question is not just "can the agent click through a page?" It is how to handle verification in a controlled, auditable, and authorized workflow. A good agent architecture should make CAPTCHA handling a bounded tool call, not an improvised browser action.
This Hugging Face article walks through a full LangChain integration pattern using CapSolver. It covers two approaches:
- Token mode, where the workflow already knows the page URL and reCAPTCHA site key.
- Browser mode, where a Playwright page is inspected live, solved, and filled back automatically.
The examples use capsolver-agent, capsolver-core, LangChain, LangGraph, and Playwright.
What This Enables for Agent Builders
With this pattern, developers can build:
- LangChain agents that request a reCAPTCHA token through a dedicated tool.
- Browser automation workflows that continue only after an approved verification step succeeds.
- Playwright-based agents that detect CAPTCHA parameters on live pages.
- Public web data, QA, RPA, and internal testing workflows with clearer stop conditions.
- Production agent systems with retry limits, logging, and explicit authorization boundaries.
Use these techniques only for sites, accounts, and workflows where you have permission to automate access.
Why reCAPTCHA Interrupts LangChain Workflows
reCAPTCHA is designed to evaluate whether a session appears to come from a legitimate user. It can consider browser environment, navigation behavior, interaction patterns, risk signals, and page context. Since AI agents often use scripted browsers, headless sessions, or repeated task loops, they may encounter verification challenges during otherwise normal workflows.
Common examples include:
- Data collection from pages that require verification.
- Login or account-based workflows.
- Form submission tasks.
- Search, booking, checkout, or portal navigation.
- Multi-step browser tasks where verification appears midway through execution.
reCAPTCHA v2 usually appears in two forms. The first is the visible checkbox challenge. The second is invisible reCAPTCHA, which may run in the background and trigger during a button click or form submission. Both forms ultimately expect a valid token, commonly submitted through the g-recaptcha-response field.
If an agent reaches that point without a token-handling step, the chain can fail. CapSolver provides the solving layer, while LangChain provides the agent/tool orchestration layer.
Prerequisites
Install the packages required for the examples.
pip install git+https://github.com/capsolver-ai/capsolver-core.git
pip install "capsolver-agent[langchain] @ git+https://github.com/capsolver-ai/capsolver-agent.git"
pip install langchain-openai langgraph
Set your API keys.
export CAPSOLVER_API_KEY="your-capsolver-api-key"
export OPENAI_API_KEY="your-openai-api-key"
For Token mode, you also need the reCAPTCHA site key from the target page. You can find it by inspecting the page source, checking browser developer tools, or using the CapSolver browser extension to identify CAPTCHA parameters.
Step 1: Find the reCAPTCHA Site Key
For reCAPTCHA v2, the site key is commonly stored in a data-sitekey attribute.
<div
class="g-recaptcha"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI">
</div>
Invisible reCAPTCHA v2 often uses the same site key pattern but includes data-size="invisible".
<div
class="g-recaptcha"
data-sitekey="6LeIxAcT..."
data-size="invisible">
</div>
Record these values:
- The full page URL.
- The
data-sitekeyvalue. - Whether the page uses visible or invisible reCAPTCHA.
If your workflow already uses Playwright, you can also detect CAPTCHA information programmatically with CapSolver Core.
from capsolver_core import create_capsolver
from playwright.async_api import async_playwright
async def detect_recaptcha(url: str):
cap = create_capsolver(api_key="YOUR_CAPSOLVER_API_KEY")
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto(url)
captcha_infos = await cap.get_captcha_info(page)
for info in captcha_infos:
print(f"type={info.type}, site_key={info.website_key}")
await browser.close()
await cap.aclose()
The site key matters because the token must match the exact page and CAPTCHA configuration. Do not assume that every page on the same domain uses the same key.
Step 2: Solve reCAPTCHA v2 with a LangChain Tool
Token mode is the simplest option when your application already knows the page URL and site key. The agent can call CapSolver as a tool and receive a token that your workflow can submit with the form.
import asyncio
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from capsolver_agent.langchain import get_langchain_tools
async def solve_recaptcha_with_langchain():
tools = get_langchain_tools(api_key="YOUR_CAPSOLVER_API_KEY")
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, tools=tools)
result = await agent.ainvoke({
"messages": [
(
"user",
"Solve the reCAPTCHA v2 for https://example.com/login. "
"The site key is 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI. "
"Return the response token."
)
]
})
print(result["messages"][-1].content)
asyncio.run(solve_recaptcha_with_langchain())
If you prefer deterministic control instead of letting the agent decide when to call the tool, use the executor interface directly.
from capsolver_agent.schema import create_executor
async def solve_recaptcha_directly():
executor = create_executor(api_key="YOUR_CAPSOLVER_API_KEY")
result = await executor.execute("solve_captcha", {
"captcha_type": "reCaptchaV2",
"website_url": "https://example.com/login",
"website_key": "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
})
if not result["success"]:
print(f"Captcha solving failed: {result['error']}")
return None
token = result["solution"]["token"]
print(f"Received token: {token[:60]}...")
return token
After receiving the token, submit it through the field expected by the page, usually g-recaptcha-response.
This mode is lightweight because it does not require a browser session. It is useful for agent workflows where the target URL and CAPTCHA parameters are already known.
Step 3: Handle Invisible reCAPTCHA v2
From the solving API perspective, invisible reCAPTCHA v2 uses the same task type as the checkbox version.
result = await executor.execute("solve_captcha", {
"captcha_type": "reCaptchaV2",
"website_url": "https://example.com/checkout",
"website_key": "6Ld_SITE_KEY_HERE"
})
The difference appears after the token is returned. Invisible reCAPTCHA is often tied to a button click, form submission event, or JavaScript callback. In a browser automation flow, you may need to write the token into the page and trigger the callback expected by the site.
await page.evaluate(
"""(token) => {
const response = document.getElementById("g-recaptcha-response");
if (response) {
response.innerHTML = token;
}
if (typeof ___grecaptcha_cfg !== "undefined") {
const clients = ___grecaptcha_cfg.clients;
for (const id in clients) {
const client = clients[id];
const callback =
client?.callback ||
client?.L?.L?.callback ||
client?.l?.l?.callback;
if (typeof callback === "function") {
callback(token);
break;
}
}
}
}""",
token,
)
Callback structures can vary by implementation, so test this part carefully in a controlled environment.
Step 4: Use Browser Mode for Automatic Detection
Browser mode is useful when the LangChain workflow does not know in advance whether a page contains a CAPTCHA. Instead of extracting the site key manually, the SDK can inspect the live page, identify supported CAPTCHA types, solve them, and fill the response token back into the page.
import asyncio
from capsolver_core import create_capsolver
from playwright.async_api import async_playwright
async def solve_recaptcha_on_page(target_url: str):
cap = create_capsolver(api_key="YOUR_CAPSOLVER_API_KEY")
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(target_url)
await page.wait_for_load_state("networkidle")
results = await cap.solve_on_page(page)
for result in results:
if result.solution:
print(f"Solved {result.info.type}")
print(f"Filled into page: {result.filled}")
else:
print(f"Failed to solve {result.info.type}: {result.error}")
submit = page.locator('button[type="submit"]')
if await submit.count() > 0:
await submit.click()
await page.wait_for_load_state("networkidle")
print(f"Current page: {page.url}")
await browser.close()
await cap.aclose()
asyncio.run(solve_recaptcha_on_page("https://example.com/login"))
This is especially helpful for agents that browse pages dynamically. The agent can navigate as usual, while the browser-level helper handles detection and token fill-back when verification appears.
Step 5: Add reCAPTCHA Handling to a Production Agent
In production, CAPTCHA handling should be one part of a broader agent workflow. The application should define where automation is allowed, when the solving tool can be called, how many retries are permitted, and what evidence should be logged.
Here is a simple pattern using CapSolver tools in a ReAct agent.
import asyncio
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from capsolver_agent.langchain import get_langchain_tools
async def run_authorized_agent_workflow():
capsolver_tools = get_langchain_tools(api_key="YOUR_CAPSOLVER_API_KEY")
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, tools=capsolver_tools)
response = await agent.ainvoke({
"messages": [
(
"user",
"For my authorized test workflow, solve the reCAPTCHA v2 "
"at https://example.com/gate. The site key is "
"6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI. Return the token."
)
]
})
return response["messages"][-1].content
result = asyncio.run(run_authorized_agent_workflow())
print(result)
For more complex workflows, consider adding:
- Retry logic for transient failures.
- Token refresh logic when submission is delayed.
- Clear logging around CAPTCHA type, solve status, and response time.
- Human review or stop conditions for sensitive workflows.
- Separate handling for reCAPTCHA v2, reCAPTCHA v3, and Enterprise variants.
If a page uses reCAPTCHA v3, the task parameters are different. For example, v3 commonly requires a page_action value. Enterprise implementations may also require additional fields. Detect the CAPTCHA type first, then pass the correct parameters to the solver.
Common Integration Mistakes
Using the wrong CAPTCHA type
reCAPTCHA v2 and v3 are not interchangeable. v2 commonly appears as a checkbox or invisible challenge. v3 usually runs with a score-based action and may be loaded with a render=SITE_KEY script parameter.
Waiting too long before submission
reCAPTCHA tokens are time-sensitive. Generate the token close to the moment you submit the form. If the agent performs additional steps after solving, request a fresh token before final submission.
Reusing site keys across pages
Even pages on the same website can use different keys or configurations. Detect or confirm the site key for the exact URL your workflow is automating.
Ignoring invisible reCAPTCHA callbacks
Invisible challenges may require more than filling g-recaptcha-response. If the page expects a callback, trigger the callback after injecting the token.
Treating CAPTCHA solving as a universal fallback
CAPTCHA handling should be used only inside authorized workflows. If the agent reaches a page it should not automate, the correct behavior is to stop, report the issue, or route the task for human review.
FAQ
Can LangChain solve reCAPTCHA without opening a browser?
Yes. Token mode does not require a browser. Provide the website URL and site key, and CapSolver returns a token that your application can submit with the form.
When should I use Browser mode?
Use Browser mode when the agent is already navigating with Playwright and CAPTCHA parameters are not known in advance. Browser mode can detect supported challenges on the page and fill the token back automatically.
Does the same method work for invisible reCAPTCHA?
Yes. Invisible reCAPTCHA v2 uses the same reCaptchaV2 task type. The solving request is similar, but the browser-side submission may need callback handling.
What happens if the token expires?
Request a new token and submit it immediately. A reliable production workflow should solve CAPTCHA as close as possible to the final form submission step.
Can this be used with reCAPTCHA Enterprise?
Yes, but Enterprise integrations may require additional parameters depending on the page. Identify the CAPTCHA configuration first and pass the required fields when creating the task.
Conclusion
LangChain agents can run into reCAPTCHA v2 during real-world browser automation, especially on login pages, forms, search flows, and protected portals. With CapSolver's LangChain tools, developers can add CAPTCHA token handling directly into the agent workflow instead of stopping the chain when verification appears.
Use Token mode when you already know the page URL and site key. Use Browser mode when the agent is navigating live pages and needs automatic detection and fill-back. For production use, keep the workflow authorized, log solve results clearly, and request tokens only when the agent is ready to submit the protected form.