DEV Community

luisgustvo
luisgustvo

Posted on

Solving reCAPTCHA v2 in LangChain: Token Mode and Browser Mode

If your LangChain agent drives browser tasks, sooner or later it may hit reCAPTCHA v2. This dev.to version keeps the walkthrough hands-on: install the packages, detect the site key, solve in Token mode, and use Browser mode when the page is discovered dynamically.

AI agents built with LangChain are increasingly used to run browser workflows, collect structured data, submit forms, and complete multi-step web tasks. In many real-world environments, those workflows may encounter reCAPTCHA v2 challenges, including checkbox challenges and invisible reCAPTCHA prompts.

When a LangChain agent reaches a page protected by reCAPTCHA, the automation flow can stop unless the agent has a way to request a valid verification token and continue the workflow. This guide shows how to integrate CapSolver with LangChain so an authorized agent can handle reCAPTCHA v2 in two practical ways:

  • Token mode, where you provide the page URL and site key.
  • Browser mode, where the SDK detects the CAPTCHA on the live page and fills the response back into the DOM.

The examples below use CapSolver's capsolver-agent package and LangChain-compatible tools, so CAPTCHA handling can become part of the agent's normal reasoning and execution loop.

Quick Summary

  • reCAPTCHA v2 is one of the most common verification types that browser-based LangChain agents may encounter.
  • CapSolver can return a usable reCAPTCHA v2 token for checkbox and invisible challenges.
  • Token mode is useful when the agent or application already knows the target URL and site key.
  • Browser mode is useful when the agent is navigating pages dynamically and needs automatic detection.
  • capsolver-agent provides LangChain tool support, making it easier to plug CAPTCHA handling into ReAct-style agents.

Use these techniques only for websites, workflows, and accounts where you have authorization to automate access.

Why reCAPTCHA Interrupts LangChain Workflows

reCAPTCHA is designed to evaluate whether a request appears to come from a legitimate user session. It looks at signals such as browser behavior, environment, interaction patterns, and page context. Because AI agents often run through scripted browser sessions, headless environments, or repeated task flows, they can trigger verification checks during otherwise normal automation.

For LangChain agents, this can happen during:

  • 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 the process.

reCAPTCHA v2 usually appears in one of two forms. The first is the familiar checkbox challenge. The second is invisible reCAPTCHA, which may run in the background and trigger only when the page decides additional verification is needed. In both cases, the page expects a valid token, usually submitted through the g-recaptcha-response field.

Without a token-handling step, the agent cannot proceed and the chain may fail. CapSolver solves this by returning a valid token that your authorized workflow can submit as part of the page interaction.

Prerequisites

Install the required packages before building the LangChain integration.

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
Enter fullscreen mode Exit fullscreen mode

Then configure your API keys.

export CAPSOLVER_API_KEY="your-capsolver-api-key"
export OPENAI_API_KEY="your-openai-api-key"
Enter fullscreen mode Exit fullscreen mode

For Token mode, you also need the reCAPTCHA site key from the page. You can find it by inspecting the page source, using 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 usually stored in a data-sitekey attribute.

<div
  class="g-recaptcha"
  data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI">
</div>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Record the following values:

  • The full page URL.
  • The data-sitekey value.
  • Whether the page uses visible or invisible reCAPTCHA.

If your workflow already uses Playwright, you can also detect CAPTCHA details 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()
Enter fullscreen mode Exit fullscreen mode

The site key matters because the token must be generated for 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 in LangChain with Token Mode

Token mode is the simplest option when your application already has the page URL and site key. The LangChain agent can call CapSolver as a tool and receive a token that can be submitted 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())
Enter fullscreen mode Exit fullscreen mode

If you prefer to control the call directly instead of letting the agent decide when to use the tool, use the executor interface.

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
Enter fullscreen mode Exit fullscreen mode

After you receive the token, submit it through the field expected by the page, usually g-recaptcha-response.

Token mode is fast and lightweight because it does not require a browser session. It is a good fit for agent workflows where the target page and 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"
})
Enter fullscreen mode Exit fullscreen mode

The main difference appears after the token is returned. Invisible reCAPTCHA is often tied to a JavaScript callback, a button click, or a form submission event. 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,
)
Enter fullscreen mode Exit fullscreen mode

Because callback structures can vary by implementation, inspect the page carefully during integration and test the flow in a controlled environment.

Step 4: Use Browser Mode for Automatic Detection

Browser mode is useful when your 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"))
Enter fullscreen mode Exit fullscreen mode

This approach is especially helpful for agents that browse pages dynamically. The agent can navigate as usual, and the browser-level helper can handle detection and token fill-back when verification appears.

Step 5: Add reCAPTCHA Handling to a Production Agent

In a production LangChain application, CAPTCHA handling should be one part of a broader workflow. The agent should know when it is allowed to automate a page, when it needs verification support, and when it should stop and return an error.

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)
Enter fullscreen mode Exit fullscreen mode

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 your 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 your 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.

How fast is reCAPTCHA v2 solving?

Solve time depends on the target challenge, network conditions, and service load. In typical workflows, plan for a short wait between requesting the task and receiving the token.

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, you 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.

Full guide: https://www.capsolver.com/blog/langchain-recaptcha-solver-ai-agent-guide?utm_source=devto&utm_medium=article&utm_campaign=langchain-recaptcha-solver-ai-agent-guide

Top comments (0)