<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: luisgustvo</title>
    <description>The latest articles on DEV Community by luisgustvo (@luisgustvo).</description>
    <link>https://dev.to/luisgustvo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1894995%2F6ea13137-c292-4572-8f1e-b5a30594b3e5.jpeg</url>
      <title>DEV Community: luisgustvo</title>
      <link>https://dev.to/luisgustvo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luisgustvo"/>
    <language>en</language>
    <item>
      <title>How to Handle CAPTCHA in Composio with CapSolver and Python</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Fri, 21 Aug 2026 08:58:34 +0000</pubDate>
      <link>https://dev.to/luisgustvo/how-to-handle-captcha-in-composio-with-capsolver-and-python-k9d</link>
      <guid>https://dev.to/luisgustvo/how-to-handle-captcha-in-composio-with-capsolver-and-python-k9d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Figz07b7w89aki2xolozv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Figz07b7w89aki2xolozv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wrap the full Playwright page workflow — open, solve, apply the result, submit, and verify — in a &lt;a href="https://docs.composio.dev/docs/extending-sessions/custom-tools-and-toolkits" rel="noopener noreferrer"&gt;&lt;strong&gt;Composio custom tool&lt;/strong&gt;&lt;/a&gt; that the OpenAI Agents SDK can call from natural-language instructions.&lt;/li&gt;
&lt;li&gt;The example covers two challenge types: reCAPTCHA v2 with a returned token and image CAPTCHA recognition with ImageToTextTask, registered as separate tools in one session.&lt;/li&gt;
&lt;li&gt;The workflow connects directly to the official OpenAI API and uses Playwright for browser automation.&lt;/li&gt;
&lt;li&gt;Two common integration failures are a Composio key without &lt;code&gt;sessions: write&lt;/code&gt; permission, which returns 403, and a missing Pydantic BaseModel annotation on the tool's first parameter, which triggers a ValidationError.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Follow the code from dependency installation to reCAPTCHA v2, ImageToTextTask, and the two most common Composio integration errors.&lt;/p&gt;

&lt;p&gt;This guide integrates &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=integrate-capsolver-composio-ai-browser-automation" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; with &lt;a href="https://github.com/ComposioHQ/composio" rel="noopener noreferrer"&gt;&lt;strong&gt;Composio&lt;/strong&gt;&lt;/a&gt; as an agent tool that completes a reCAPTCHA v2 workflow. Instead of returning only a token, the tool runs the full page sequence and treats the page's actual response as the success condition. &lt;a href="https://www.capsolver.com/blog/ai/how-to-solve-recaptcha-in-openai-agents-sdk" rel="noopener noreferrer"&gt;OpenAI Agents SDK&lt;/a&gt; decides when to call the tool, while &lt;a href="https://www.capsolver.com/integration/playwright-captcha-solver" rel="noopener noreferrer"&gt;Playwright browser automation&lt;/a&gt; preserves the page context used for submission and verification.&lt;/p&gt;

&lt;p&gt;Use this pattern only for lawful, reasonable, responsible, and user-authorized workflows. Technical capability does not grant permission to access private, restricted, sensitive, or unauthorized data; review the relevant &lt;a href="https://www.capsolver.com/faq/ai-and-automation" rel="noopener noreferrer"&gt;AI automation guidance&lt;/a&gt; before deployment.&lt;/p&gt;

&lt;p&gt;Workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run the script
  -&amp;gt; OpenAI Agents SDK decides which tool to call
  -&amp;gt; Composio custom tool: complete_recaptcha_v2
       -&amp;gt; Playwright opens the page
       -&amp;gt; capsolver.solve(...) returns gRecaptchaResponse
       -&amp;gt; Apply the token to g-recaptcha-response
       -&amp;gt; Playwright submits and waits for the page
       -&amp;gt; Read the page and determine accepted
  -&amp;gt; Tool returns {"accepted": ..., "message": ...}
  -&amp;gt; Agent reports the result from accepted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The components have the following responsibilities:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI Agents SDK&lt;/td&gt;
&lt;td&gt;Understands natural-language instructions, decides when to call the tool, executes it, and organizes the response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composio&lt;/td&gt;
&lt;td&gt;Registers a standard Python function as an agent-callable tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright&lt;/td&gt;
&lt;td&gt;Opens the page, applies the result, submits the form, and reads the resulting page state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CapSolver SDK&lt;/td&gt;
&lt;td&gt;Returns the CAPTCHA result through a single solve() call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install composio composio-openai-agents openai-agents capsolver pydantic playwright
playwright install chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each dependency serves a specific role:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;composio&lt;/td&gt;
&lt;td&gt;Creates sessions and registers or loads custom tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;composio-openai-agents&lt;/td&gt;
&lt;td&gt;Converts Composio tools into objects that OpenAI Agents can call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;openai-agents&lt;/td&gt;
&lt;td&gt;Provides Agent, Runner, and SQLite multi-turn memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;capsolver&lt;/td&gt;
&lt;td&gt;Provides the official SDK and returns a result through solve()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pydantic&lt;/td&gt;
&lt;td&gt;Defines the tool input schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;playwright&lt;/td&gt;
&lt;td&gt;Opens pages, applies results, submits forms, and reads responses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# API keys.
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..."          # Your official OpenAI API key.
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY   # OpenAI SDK reads the key from env.

# Configure CapSolver and Composio.
capsolver.api_key = "CAP-..."
composio = Composio(
    api_key=COMPOSIO_API_KEY,
    provider=OpenAIAgentsProvider(),
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Configuration notes:&lt;br&gt;
OPENAI_API_KEY&lt;br&gt;
must be written to the environment because the SDK reads it there;&lt;br&gt;
OpenAIAgentsProvider&lt;br&gt;
makes the tools returned by&lt;br&gt;
session.tools()&lt;br&gt;
compatible with Agent; and the Composio key needs&lt;br&gt;
sessions: write&lt;br&gt;
permission or session creation returns 403.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The current &lt;a href="https://docs.composio.dev/docs/providers/openai" rel="noopener noreferrer"&gt;&lt;strong&gt;Composio OpenAI provider&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://openai.github.io/openai-agents-python/" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenAI Agents SDK&lt;/strong&gt;&lt;/a&gt; references explain the provider and agent boundary used by this configuration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Redeem Your CapSolver Bonus Code&lt;br&gt;
Boost your automation budget instantly!&lt;br&gt;
Use bonus code&lt;br&gt;
CAP26&lt;br&gt;
when topping up your CapSolver account to get an extra&lt;br&gt;
5% bonus&lt;br&gt;
on every recharge — with no limits.&lt;br&gt;
Redeem it now in your&lt;br&gt;
CapSolver Dashboard&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Core Implementation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Stopping condition:&lt;br&gt;
the tool reports success only when the page contains the expected success text. The&lt;br&gt;
finally&lt;br&gt;
block closes the browser in both success and failure paths.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from typing import List, cast
import capsolver
from agents import Agent, Runner, SQLiteSession
from composio import Composio
from composio.core.models.custom_tool import CustomTool
from composio.core.models.tool_router import ToolRouterExperimentalConfig
from composio_openai_agents import OpenAIAgentsProvider
from playwright.sync_api import sync_playwright
from pydantic import BaseModel, Field

# API keys.
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..."          # Your official OpenAI API key.
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

# Configure CapSolver and Composio.
capsolver.api_key = "CAP-..."
composio = Composio(
    api_key=COMPOSIO_API_KEY,
    provider=OpenAIAgentsProvider(),
)


# Input schema for the custom tool; Composio requires a Pydantic BaseModel here.
class CompleteRecaptchaInput(BaseModel):
    target_url: str = Field(
        default="https://www.google.com/recaptcha/api2/demo",
        description="Page URL containing the reCAPTCHA v2 demo",
    )
    website_key: str = Field(
        default="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        description="reCAPTCHA v2 website key from the current page",
    )


# Register the whole flow as one Composio tool the agent can call.
# The first parameter's type annotation is required by Composio to infer the schema.
@composio.experimental.tool(preload=True)
def complete_recaptcha_v2(input: CompleteRecaptchaInput, _ctx):
    """Open the page with Playwright, solve reCAPTCHA v2, submit, and verify."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)  # Set headless=True to hide the window.
        page = browser.new_page()
        try:
            page.goto(input.target_url)
            # Ask CapSolver to solve the reCAPTCHA v2 challenge.
            solution = capsolver.solve(
                {
                    "type": "ReCaptchaV2TaskProxyLess",
                    "websiteURL": input.target_url,
                    "websiteKey": input.website_key,
                }
            )
            token = solution.get("gRecaptchaResponse")
            page.evaluate(
                """
                (token) =&amp;gt; {
                    const textarea = document.getElementById('g-recaptcha-response');
                    if (textarea) {
                        textarea.value = token;
                    }
                }
                """,
                token,
            )
            page.click("#recaptcha-demo-submit")
            page.wait_for_load_state("networkidle")
            result_page = page.content()
            # Success only if the page actually shows the success text
            accepted = "Verification Success" in result_page
            return {
                "accepted": accepted,
                "message": (
                    "Verification Success"
                    if accepted
                    else "The page did not report Verification Success"
                ),
            }
        finally:
            browser.close()
def main():
    experimental: ToolRouterExperimentalConfig = {
        "custom_tools": cast(List[CustomTool], [complete_recaptcha_v2]),
    }
    session = composio.sessions.create(
        user_id="playwright-recaptcha-demo-user",
        experimental=experimental,
        sandbox={"enable": False},  # Run the tool in this process, not a sandbox.
    )
    agent = Agent(
        name="Playwright reCAPTCHA Assistant",
        instructions=(
            "When the user asks to run the demo, call complete_recaptcha_v2 "
            "with its default values. Report success only when accepted is true."
        ),
        model="gpt-5.2",
        tools=session.tools(),
    )
    # Memory for multi-turn conversation
    memory = SQLiteSession("conversation")
    print("Composio + Playwright reCAPTCHA v2 demo running once...")
    user_input = (
        "Call complete_recaptcha_v2 now with its default target_url "
        "and website_key. Do not ask for confirmation."
    )
    result = Runner.run_sync(
        starting_agent=agent,
        input=user_input,
        session=memory,
    )
    print(f"Assistant: {result.final_output}\n")
if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Image CAPTCHA Recognition with ImageToTextTask
&lt;/h2&gt;

&lt;p&gt;The same pattern can handle a standard image-text CAPTCHA by registering a second Composio tool. This example uses the &lt;a href="https://captcha.com/demos/features/captcha-demo.aspx" rel="noopener noreferrer"&gt;&lt;strong&gt;BotDetect CAPTCHA Demo&lt;/strong&gt;&lt;/a&gt;: the image element is &lt;code&gt;#demoCaptcha_CaptchaImage&lt;/code&gt;, the input is &lt;code&gt;#captchaCode&lt;/code&gt;, and the validation button is &lt;code&gt;#validateCaptchaButton&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy1pidmdkyv8puiky2pr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy1pidmdkyv8puiky2pr6.png" alt="BotDetect CAPTCHA image, input, and validation elements inspected in the browser" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/" rel="noopener noreferrer"&gt;ImageToTextTask&lt;/a&gt; request submits the Base64 image through &lt;code&gt;body&lt;/code&gt;. Unlike token-based tasks, this task returns the recognized text directly and does not require a separate polling loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 Read the Image as Base64
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
    raise RuntimeError("A valid CAPTCHA image Data URL was not found")
base64_image = image_src.split(",", 1)[1]  # Strip the "data:image/...;base64," prefix.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.2 Custom Tool Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CompleteImageCaptchaInput(BaseModel):
    target_url: str = Field(
        default="https://captcha.com/demos/features/captcha-demo.aspx",
        description="Image CAPTCHA demo page URL",
    )
    module: str = Field(
        default="common",
        description="CapSolver ImageToTextTask recognition module",
    )

@composio.experimental.tool(preload=True)
def complete_image_captcha(input: CompleteImageCaptchaInput, _ctx):
    """Open the page with Playwright, recognize the image CAPTCHA, submit, and verify."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            page.goto(input.target_url)
            page.wait_for_selector("#demoCaptcha_CaptchaImage", state="visible")

            # The image src is already a data URL; strip the prefix to get Base64.
            image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
            if not image_src or "," not in image_src:
                raise RuntimeError("A valid CAPTCHA image Data URL was not found")
            base64_image = image_src.split(",", 1)[1]
            solution = capsolver.solve(
                {
                    "type": "ImageToTextTask",
                    "websiteURL": input.target_url,
                    "module": input.module,
                    "body": base64_image,
                }
            )
            captcha_text = solution.get("text")
            if not isinstance(captcha_text, str) or not captcha_text:
                raise RuntimeError("CapSolver did not return recognized text")
            page.fill("#captchaCode", captcha_text)      # Fill the recognized text.
            page.click("#validateCaptchaButton")
            page.wait_for_load_state("networkidle")
            result_page = page.content()
            # The demo page shows "Correct!" on success, "Incorrect!" on failure.
            accepted = "Correct!" in result_page
            return {
                "accepted": accepted,
                "recognized_text": captcha_text,
                "message": "Correct!" if accepted else "The page did not report Correct!",
            }
        finally:
            browser.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flow overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Playwright opens the CAPTCHA page
  -&amp;gt; Wait for #demoCaptcha_CaptchaImage to become visible
  -&amp;gt; Read src (data URL) and remove the prefix to get Base64
  -&amp;gt; capsolver.solve(ImageToTextTask) returns text
  -&amp;gt; page.fill writes the result to #captchaCode
  -&amp;gt; page.click activates #validateCaptchaButton
  -&amp;gt; page.content checks Correct! or Incorrect!
  -&amp;gt; finally closes the browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.3 Choose the Appropriate Recognition Model
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;module&lt;/code&gt; parameter is optional and defaults to &lt;code&gt;common&lt;/code&gt;. If the CAPTCHA contains only numbers, use &lt;code&gt;number&lt;/code&gt;. Special styles can use a documented independent model when appropriate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuhzjpdosdjvkk1s00kgl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuhzjpdosdjvkk1s00kgl.png" alt="CapSolver ImageToTextTask independent model examples and accuracy values" width="800" height="1044"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, use the following unchanged source code for numeric-only recognition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solution = capsolver.solve({
    "type": "ImageToTextTask",
    "module": "number",
    "images": [base64_image],
})

answers = solution["answers"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;number&lt;/code&gt; model supports multiple images in one submission, and &lt;code&gt;images&lt;/code&gt; can contain up to nine Base64 strings. The supported model names and use cases are listed in the CapSolver ImageToTextTask page linked above.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1 The First Tool Parameter Must Be a BaseModel
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;experimental.tool: first parameter of "complete_recaptcha_v2" must be
annotated with a Pydantic BaseModel subclass. Got: &amp;lt;class 'inspect._empty'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Composio infers the input schema from the first parameter's type annotation, so &lt;code&gt;input: CompleteRecaptchaInput&lt;/code&gt; cannot be omitted. This is a functional annotation, not an optional type hint. The &lt;a href="https://docs.pydantic.dev/latest/api/base_model/" rel="noopener noreferrer"&gt;&lt;strong&gt;Pydantic BaseModel&lt;/strong&gt;&lt;/a&gt; reference describes the model type used for the schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.2 Composio Returns 403
&lt;/h3&gt;

&lt;p&gt;Session creation can return the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;403 APIKey_InsufficientPermissions
This route requires "sessions" write access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cause is that &lt;code&gt;composio.sessions.create()&lt;/code&gt; requires project-key write access for sessions, while the current key has read-only access. The key is valid, but its scope is insufficient, so the response is 403 rather than 401.&lt;/p&gt;

&lt;p&gt;Resolution steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Composio dashboard and go to the API Keys settings for the relevant project.&lt;/li&gt;
&lt;li&gt;Change the current key's sessions permission from read to write.&lt;/li&gt;
&lt;li&gt;If the permission cannot be edited, create a new key with &lt;code&gt;sessions: write&lt;/code&gt; and replace &lt;code&gt;COMPOSIO_API_KEY&lt;/code&gt; at the top of the script.&lt;/li&gt;
&lt;li&gt;Run the script again. Reaching the interactive flow without 403 confirms that the permission is active.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  7. Conclusion and CTA
&lt;/h2&gt;

&lt;p&gt;The core of this integration is a complete business workflow packaged as one Composio tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Composio tool = Playwright page actions + CapSolver result + page-state verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Composio converts the Python function into an agent tool and handles schema inference and execution.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://playwright.dev/python/docs/intro" rel="noopener noreferrer"&gt;&lt;strong&gt;Playwright&lt;/strong&gt;&lt;/a&gt; opens the page, applies the result, submits the form, and reads the final state.&lt;/li&gt;
&lt;li&gt;CapSolver handles &lt;a href="https://docs.capsolver.com/en/guide/captcha/ReCaptchaV2/" rel="noopener noreferrer"&gt;reCAPTCHA v2&lt;/a&gt; and image CAPTCHA recognition for this specific workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the example only on pages and processes you own or are authorized to automate. Use environment variables or a secret manager for credentials, stop when the page does not reach the expected business state, and review repeated failures instead of retrying indefinitely.&lt;/p&gt;

&lt;p&gt;For an authorized Composio agent workflow that needs a focused CAPTCHA infrastructure layer, test &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=integrate-capsolver-composio-ai-browser-automation" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; with your own controlled pages and verify the application result after every solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What does Composio handle in this integration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Composio registers the Python function as an agent-callable custom tool, creates the session, exposes the tool schema, and routes execution from the OpenAI agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why must the first tool parameter be a Pydantic BaseModel?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Composio uses that annotation to infer the tool's input schema. Omitting it prevents schema construction and raises a validation error before the browser workflow starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the reCAPTCHA v2 tool stop after CapSolver returns a token?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. The unchanged code applies the token, submits the demo form, reads the resulting HTML, and reports success only when the page contains the expected Verification Success text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does ImageToTextTask require a separate polling loop?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. In this workflow, the official SDK returns the recognized text directly. The tool then fills the input, submits the page, and checks for Correct! as the stopping condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can this workflow be used on any website?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Use it only for lawful, reasonable, responsible, and user-authorized automation. Respect site terms, applicable laws, rate limits, and data-minimization requirements.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>BrowserAct + CapSolver Tutorial: Handling CAPTCHA with Python</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Tue, 11 Aug 2026 08:54:27 +0000</pubDate>
      <link>https://dev.to/luisgustvo/browseract-capsolver-tutorial-handling-captcha-with-python-45ko</link>
      <guid>https://dev.to/luisgustvo/browseract-capsolver-tutorial-handling-captcha-with-python-45ko</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1rd1dths6f1fmq7c14u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1rd1dths6f1fmq7c14u.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;BrowserAct manages browser sessions, page navigation, element actions, and business-result verification, while CapSolver returns CAPTCHA tokens, cookies, or image-recognition results.&lt;/li&gt;
&lt;li&gt;Use the official &lt;code&gt;capsolver&lt;/code&gt; Python SDK and call &lt;code&gt;capsolver.solve()&lt;/code&gt; directly; your application does not need to reimplement &lt;code&gt;createTask&lt;/code&gt; and result polling.&lt;/li&gt;
&lt;li&gt;CAPTCHA parameters must come from the current BrowserAct session, and the result must be returned to that same session before you reread the page state and confirm that the business action actually succeeded.&lt;/li&gt;
&lt;li&gt;Use this workflow only for lawful, reasonable, and responsible automation on pages and processes you are authorized to access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this hands-on Python tutorial, you will connect BrowserAct to CapSolver, return results to the same browser session, and verify what the target page actually did.&lt;/p&gt;

&lt;p&gt;BrowserAct is a browser automation tool for AI agents. Through its CLI, it can manage browser sessions and perform page navigation, element location, clicks, input, script execution, and network-state checks. Unlike a script that focuses on one selector at a time, BrowserAct is better suited to organizing multiple page actions into a recoverable task flow.&lt;/p&gt;

&lt;p&gt;When a login, form submission, or data-access workflow encounters a CAPTCHA challenge, BrowserAct maintains the page, cookies, proxy, and browser identity, while &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=how-to-integrate-browseract-with-capsolver-for-captcha-handling" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; handles the CAPTCHA task. The program extracts the &lt;code&gt;websiteURL&lt;/code&gt;, site key, user agent, or image Base64 from the current page, calls the official CapSolver SDK for a result, and then returns that result to the original browser session through BrowserAct's &lt;code&gt;eval&lt;/code&gt;, cookie commands, or page-input actions.&lt;/p&gt;

&lt;p&gt;The key to this integration is not simply obtaining a token. It is keeping the context consistent before and after solving and using the target page's business result as the final success condition.&lt;/p&gt;

&lt;p&gt;For agent-native implementation options, start with &lt;a href="https://docs.capsolver.com/en/guide/ai/capsolver-for-ai-agents/" rel="noopener noreferrer"&gt;CapSolver for AI Agents&lt;/a&gt; and the &lt;a href="https://docs.capsolver.com/en/guide/ai/introduction-and-quick-start/" rel="noopener noreferrer"&gt;introduction and quick start&lt;/a&gt;. The official &lt;a href="https://docs.capsolver.com/en/guide/ai/core-sdk/" rel="noopener noreferrer"&gt;Core SDK&lt;/a&gt;, &lt;a href="https://docs.capsolver.com/en/guide/ai/agent-tools/" rel="noopener noreferrer"&gt;Agent Tools&lt;/a&gt;, and &lt;a href="https://docs.capsolver.com/en/guide/ai/mcp-service/" rel="noopener noreferrer"&gt;MCP Service&lt;/a&gt; explain the supported paths for scripts, agent tool calls, and MCP clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install the Dependencies
&lt;/h2&gt;

&lt;p&gt;Install the BrowserAct CLI first and confirm that the command runs correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;browser-act-cli &lt;span class="nt"&gt;--python&lt;/span&gt; 3.12
browser-act &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first use requires you to connect a BrowserAct account. &lt;code&gt;auth login&lt;/code&gt; only generates a registration link; it does not complete authentication directly in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;browser-act auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the link returned by the command and complete registration or login, then poll the authentication result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;browser-act auth poll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the command returns &lt;code&gt;status=pending&lt;/code&gt;, wait a few seconds and run it again. Authentication is complete only when it returns &lt;code&gt;status=completed&lt;/code&gt; and confirms that the API key has been saved. Finally, check the browser list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;browser-act browser list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the first authentication, &lt;code&gt;No browsers found.&lt;/code&gt; is normal. It means that no BrowserAct browser instance has been created in the account yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use the Official CapSolver SDK
&lt;/h2&gt;

&lt;p&gt;Install the official CapSolver Python SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; capsolver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pip install --upgrade capsolver
# export CAPSOLVER_API_KEY='...'
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;

&lt;span class="c1"&gt;# capsolver.api_key = "..."
&lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.google.com/recaptcha/api2/demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three parameters work as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; selects the CAPTCHA task type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;websiteURL&lt;/code&gt; and &lt;code&gt;websiteKey&lt;/code&gt; must match the actual configuration on the current page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CapSolver SDK handles task creation and result polling. The returned field depends on the task type: reCAPTCHA typically uses &lt;code&gt;gRecaptchaResponse&lt;/code&gt;, Turnstile uses &lt;code&gt;token&lt;/code&gt;, DataDome uses &lt;code&gt;cookie&lt;/code&gt;, and image CAPTCHA recognition uses &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Create a BrowserAct Session
&lt;/h2&gt;

&lt;p&gt;When you need a stable proxy and browser identity, you can create a fixed stealth session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;browser-act&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stealth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"capsolver-demo"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Authorized CAPTCHA integration test"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--custom-proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;socks5://user:pass&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;proxy.example:1080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command normally returns a web confirmation URL and a &lt;code&gt;&amp;lt;request_id&amp;gt;&lt;/code&gt; first; it does not immediately return a &lt;code&gt;&amp;lt;browser_id&amp;gt;&lt;/code&gt; in the terminal. Open the confirmation URL and finish creating the browser, then query the creation result and browser list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;browser-act&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a navigation, a closed pop-up, or a refreshed CAPTCHA, run &lt;code&gt;state&lt;/code&gt; again. BrowserAct element numbers belong to the current page state and must not be reused across pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Integrate BrowserAct with CapSolver
&lt;/h2&gt;

&lt;p&gt;The following example puts the BrowserAct CLI and CapSolver SDK in the same Python script and completes these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the target page and read the page state.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;capsolver.solve()&lt;/code&gt; to obtain a token.&lt;/li&gt;
&lt;li&gt;Use BrowserAct &lt;code&gt;eval --stdin&lt;/code&gt; to write the token to &lt;code&gt;g-recaptcha-response&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Let BrowserAct continue the submission and inspect the final page state.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Verification note: This source example is preserved exactly. Live execution requires a configured BrowserAct CLI and session, a BrowserAct browser resource, and a CapSolver API key; replace the blank placeholders only in your own test environment.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;

&lt;span class="n"&gt;BROWSER_ACT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Absolute path to the BrowserAct CLI executable.
&lt;/span&gt;&lt;span class="n"&gt;SESSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Name of the BrowserAct session used by this script.
&lt;/span&gt;&lt;span class="n"&gt;BROWSER_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# ID of the existing BrowserAct browser resource.
&lt;/span&gt;&lt;span class="n"&gt;TARGET_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.google.com/recaptcha/api2/demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Page used for the reCAPTCHA v2 integration test.
&lt;/span&gt;&lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BROWSER_ACT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SESSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;#
&lt;/span&gt;        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BrowserAct failed (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;): &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;browser_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute JavaScript in the current BrowserAct page.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--stdin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inject_recaptcha_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;token_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
((token) =&amp;gt; {{
  const textarea = document.getElementById(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;);
  if (textarea) {{
    textarea.value = token;
  }}
}})(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token_json&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="nf"&gt;browser_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;browser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BROWSER_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.google.com/recaptcha/api2/demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
    &lt;span class="nf"&gt;inject_recaptcha_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--selector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#recaptcha-demo-submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# Read the resulting page.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution flow can be summarized as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BrowserAct opens the reCAPTCHA v2 demo page
  -&amp;gt; Read the current page state
  -&amp;gt; Call capsolver.solve(ReCaptchaV2TaskProxyLess)
  -&amp;gt; Read solution["gRecaptchaResponse"]
  -&amp;gt; Write to #g-recaptcha-response
  -&amp;gt; Click #recaptcha-demo-submit
  -&amp;gt; Wait for the page to stabilize
  -&amp;gt; Read BrowserAct markdown and confirm the final result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;inject_recaptcha_token()&lt;/code&gt; only writes the token into the page field; it does not automatically submit the business form. Add the submission action according to the target site's actual button, form, or BrowserAct agent instruction, then reread &lt;code&gt;state&lt;/code&gt; or the network result after submission.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Redeem Your CapSolver Bonus Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Boost your automation budget instantly!&lt;br&gt;
Use bonus code &lt;strong&gt;CAP26&lt;/strong&gt; when topping up your CapSolver account to get an extra &lt;strong&gt;5% bonus&lt;/strong&gt; on every recharge — with no limits.&lt;br&gt;
Redeem it now in your &lt;a href="https://dashboard.capsolver.com/dashboard/overview/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=how-to-integrate-browseract-with-capsolver-for-captcha-handling" rel="noopener noreferrer"&gt;CapSolver Dashboard&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpb1jgg04gjyh3xbottm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpb1jgg04gjyh3xbottm.png" alt="Bonus Code" width="472" height="140"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Use the CapSolver API for Image-to-Text CAPTCHA Recognition
&lt;/h2&gt;

&lt;p&gt;In addition to token-based challenges, BrowserAct can work with CapSolver to process standard image-text CAPTCHAs. This section uses the &lt;a href="https://captcha.com/demos/features/captcha-demo.aspx" rel="nofollow noopener noreferrer"&gt;BotDetect CAPTCHA Demo&lt;/a&gt;. The CAPTCHA image element ID is &lt;code&gt;demoCaptcha_CaptchaImage&lt;/code&gt;, the result input ID is &lt;code&gt;captchaCode&lt;/code&gt;, and the validation button ID is &lt;code&gt;validateCaptchaButton&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdantih6e5k1315stwup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdantih6e5k1315stwup.png" alt="BotDetect CAPTCHA image and input elements inspected in the browser" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ImageToTextTask&lt;/code&gt; requires you to convert the CAPTCHA image to Base64 and submit it to CapSolver through the &lt;code&gt;body&lt;/code&gt; parameter. If the image &lt;code&gt;src&lt;/code&gt; is a Data URL, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data:image/png;base64,iVBORw0KGgoAAA...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When sending it to CapSolver, keep only the Base64 content after the comma; do not include the &lt;code&gt;data:image/...;base64,&lt;/code&gt; prefix. Unlike token-based tasks, &lt;code&gt;ImageToTextTask&lt;/code&gt; returns the recognition result directly, so your application does not need to implement additional &lt;code&gt;getTaskResult&lt;/code&gt; polling.&lt;/p&gt;

&lt;p&gt;The following example uses BrowserAct &lt;code&gt;eval --stdin&lt;/code&gt; to read the current page image, call the official SDK, fill in the recognition result, and click the validation button:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Verification note: This source example is preserved exactly. Live execution requires the BrowserAct prerequisites, a CapSolver API key, and authorized access to the demo page.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;

&lt;span class="n"&gt;BROWSER_ACT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Absolute path to the BrowserAct CLI executable.
&lt;/span&gt;&lt;span class="n"&gt;BROWSER_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# ID of the existing BrowserAct browser resource.
&lt;/span&gt;&lt;span class="n"&gt;TARGET_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://captcha.com/demos/features/captcha-demo.aspx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Image CAPTCHA demo page.
&lt;/span&gt;&lt;span class="n"&gt;SESSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Name of the BrowserAct session used by this script.
&lt;/span&gt;&lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Configure the CapSolver client with the account API key.
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BROWSER_ACT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SESSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;browser_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--stdin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;browser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BROWSER_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;image_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;browser_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
(() =&amp;gt; document.querySelector(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#demoCaptcha_CaptchaImage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)?.getAttribute(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;) || &lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="s"&gt;)()
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A valid Base64 CAPTCHA image was not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;base64_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ImageToTextTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;common&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;base64_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;captcha_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Recognition result:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;captcha_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;browser_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document.querySelector(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#captchaCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;).value = &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;captcha_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--selector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#validateCaptchaButton&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;browser_act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Incorrect!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA verification: FAILED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Correct!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA verification: PASSED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA verification: UNKNOWN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution flow can be summarized as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BrowserAct opens the CAPTCHA page
  -&amp;gt; Read the Data URL from #demoCaptcha_CaptchaImage
  -&amp;gt; Extract the Base64 image content after the comma
  -&amp;gt; Call capsolver.solve(ImageToTextTask)
  -&amp;gt; Read solution["text"]
  -&amp;gt; Fill #captchaCode
  -&amp;gt; Click #validateCaptchaButton
  -&amp;gt; Wait for the page to stabilize
  -&amp;gt; Read BrowserAct markdown
  -&amp;gt; Output the verification result from Correct!/Incorrect!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Choose the Appropriate Recognition Model
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;module&lt;/code&gt; is optional, and &lt;code&gt;common&lt;/code&gt; can be used by default. If the CAPTCHA contains only numbers, use &lt;code&gt;number&lt;/code&gt;. For certain special styles, select the corresponding independent model from the CapSolver documentation to improve recognition accuracy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frzn5tee89ppdphkq58bv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frzn5tee89ppdphkq58bv.png" alt="CapSolver ImageToText independent module examples" width="800" height="1044"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, when recognizing a numeric CAPTCHA only, change the task parameters to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ImageToTextTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;base64_image&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;number&lt;/code&gt; model supports multiple images in one submission, and &lt;code&gt;images&lt;/code&gt; can contain up to nine Base64 strings. For other model names and supported image types, consult the official &lt;a href="https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/" rel="noopener noreferrer"&gt;CapSolver ImageToTextTask documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Choosing a CAPTCHA-handling approach for BrowserAct depends on the target site's verification type, session stability, and business-flow complexity. BrowserAct is suited to browser lifecycle management, page actions, and result verification, while CapSolver is suited to specialized handling for reCAPTCHA, Turnstile, DataDome, or image CAPTCHAs.&lt;/p&gt;

&lt;p&gt;The recommended workflow can be summarized as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BrowserAct opens and inspects the page
  -&amp;gt; Extract the CAPTCHA parameters from the current session
  -&amp;gt; capsolver.solve()
  -&amp;gt; Return the token, cookie, or recognized text to the same session
  -&amp;gt; BrowserAct continues the submission or navigation
  -&amp;gt; Read the page state and business response to confirm the result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the official SDK, a fixed session, consistent proxy and user-agent settings, and explicit timeout, retry, and logging policies, BrowserAct and CapSolver can form a more maintainable AI browser automation workflow. Store the API key in environment variables or a secret-management system, and limit automation to pages and business processes for which access is authorized. Technical capability does not grant permission to access private, restricted, sensitive, or unauthorized data.&lt;/p&gt;

&lt;p&gt;For an authorized BrowserAct workflow that needs structured CAPTCHA handling, evaluate &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=how-to-integrate-browseract-with-capsolver-for-captcha-handling" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; with your own controlled test cases and verify the final business state after every solve.&lt;/p&gt;

&lt;p&gt;For related implementation patterns and product guidance, review the &lt;a href="https://www.capsolver.com/blog/" rel="noopener noreferrer"&gt;CapSolver blog&lt;/a&gt; and &lt;a href="https://www.capsolver.com/faq" rel="noopener noreferrer"&gt;CapSolver FAQ&lt;/a&gt; before rollout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Documentation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.browseract.com/agent-cli/introduction" rel="nofollow noopener noreferrer"&gt;BrowserAct Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.browseract.com/agent-cli/quick-start" rel="nofollow noopener noreferrer"&gt;BrowserAct Quick Start&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.capsolver.com/en/guide/captcha/ReCaptchaV2/" rel="noopener noreferrer"&gt;CapSolver reCAPTCHA v2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/" rel="noopener noreferrer"&gt;CapSolver ImageToTextTask&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: What does BrowserAct handle in this integration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BrowserAct manages the browser session, navigation, page actions, and final-state checks. CapSolver handles the CAPTCHA task and returns the token, cookie, or recognized text that the authorized workflow needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Why must the CAPTCHA result return to the same BrowserAct session?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The browser context contains the page state, cookies, proxy identity, and user agent associated with the challenge. Returning the result to a different context can make the result unusable and prevents reliable business-state verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does &lt;code&gt;inject_recaptcha_token()&lt;/code&gt; submit the form automatically?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. The function only writes the token to &lt;code&gt;g-recaptcha-response&lt;/code&gt;; the workflow must still perform the site's real submission action and confirm the resulting page or network state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does &lt;code&gt;ImageToTextTask&lt;/code&gt; require separate result polling?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. The official CapSolver documentation states that &lt;code&gt;ImageToTextTask&lt;/code&gt; returns the recognition result directly, so the application does not need a separate &lt;code&gt;getTaskResult&lt;/code&gt; polling loop for that task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can this workflow be used on any website?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Use it only for lawful, reasonable, and responsible automation on pages and workflows you own or are authorized to access, while respecting site terms, applicable laws, rate limits, and data-minimization requirements.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
    </item>
    <item>
      <title>Add a Controlled CapSolver Step to a Skyvern Browser Workflow</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Tue, 28 Jul 2026 08:36:10 +0000</pubDate>
      <link>https://dev.to/luisgustvo/add-a-controlled-capsolver-step-to-a-skyvern-browser-workflow-569e</link>
      <guid>https://dev.to/luisgustvo/add-a-controlled-capsolver-step-to-a-skyvern-browser-workflow-569e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbm8f1vhrbbmln1kg3dzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbm8f1vhrbbmln1kg3dzm.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skyvern can navigate a page and act from natural-language instructions. CapSolver can return a CAPTCHA result through its SDK. The clean integration is a small deterministic bridge between them.&lt;/p&gt;

&lt;p&gt;Use this only for systems you own or are explicitly authorized to automate.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install the SDKs
&lt;/h2&gt;

&lt;p&gt;Skyvern’s current pip quickstart supports Python 3.11–3.13:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"skyvern[all]"&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; capsolver
python &lt;span class="nt"&gt;-m&lt;/span&gt; playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Load credentials outside source control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"set-this-in-your-secret-manager"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Understand the boundary
&lt;/h2&gt;

&lt;p&gt;Skyvern should own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;navigation;&lt;/li&gt;
&lt;li&gt;semantic element interaction;&lt;/li&gt;
&lt;li&gt;natural-language actions;&lt;/li&gt;
&lt;li&gt;result validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Application code should own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;target authorization;&lt;/li&gt;
&lt;li&gt;CapSolver credentials;&lt;/li&gt;
&lt;li&gt;task parameters;&lt;/li&gt;
&lt;li&gt;browser-session continuity;&lt;/li&gt;
&lt;li&gt;token or text handoff;&lt;/li&gt;
&lt;li&gt;retry limits;&lt;/li&gt;
&lt;li&gt;final assertions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Call the documented reCAPTCHA v2 task
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;

&lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.google.com/recaptcha/api2/demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the demo values only with parameters from your authorized page.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hand the token to the current page
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inject_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        (token) =&amp;gt; {
            const textarea = document.getElementById(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;);
            if (!textarea) {
                throw new Error(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;g-recaptcha-response field not found&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;);
            }
            textarea.value = token;
            textarea.dispatchEvent(new Event(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;change&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, { bubbles: true }));
        }
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not every frontend uses this field. Some owned applications use a configured callback or application request. Implement the method expected by that application rather than asking the model to guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Continue with Skyvern
&lt;/h2&gt;

&lt;p&gt;Skyvern’s current SDK documents AI-assisted page commands such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Submit the form&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The authorized test reached the expected successful result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Final validation failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final validation is mandatory. A returned token is an intermediate result.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Add ImageToTextTask
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;image_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#demoCaptcha_CaptchaImage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A valid Base64 CAPTCHA image was not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;base64_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image_src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capsolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ImageToTextTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;common&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;base64_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;captcha_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then fill the expected input, submit, and verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#captchaCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;captcha_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#validateCaptchaButton&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the &lt;a href="https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/" rel="noopener noreferrer"&gt;current ImageToTextTask documentation&lt;/a&gt; before selecting optional recognition modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Handle failures deliberately
&lt;/h2&gt;

&lt;p&gt;If the page rejects the result:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;confirm the page URL and site key;&lt;/li&gt;
&lt;li&gt;check whether navigation changed the page;&lt;/li&gt;
&lt;li&gt;verify the expected field or callback;&lt;/li&gt;
&lt;li&gt;preserve the same browser session;&lt;/li&gt;
&lt;li&gt;inspect the final assertion;&lt;/li&gt;
&lt;li&gt;stop when the retry budget is exhausted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Never log the API key, cookies, or raw verification result.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Put it together
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Skyvern navigation
→ authorization check
→ CapSolver SDK
→ deterministic page handoff
→ Skyvern action
→ application verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure lets the AI layer handle changing interfaces without giving it control over secrets or unrestricted challenge handling.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Skyvern-AI/skyvern" rel="noopener noreferrer"&gt;Skyvern GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=skyvern-capsolver" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.capsolver.com/en/guide/captcha/ReCaptchaV2/" rel="noopener noreferrer"&gt;CapSolver reCAPTCHA v2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build a Controlled AWS WAF Recovery Path for LangChain</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Thu, 23 Jul 2026 08:50:59 +0000</pubDate>
      <link>https://dev.to/luisgustvo/build-a-controlled-aws-waf-recovery-path-for-langchain-gkb</link>
      <guid>https://dev.to/luisgustvo/build-a-controlled-aws-waf-recovery-path-for-langchain-gkb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmw4wvdurj4185ljo5txi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmw4wvdurj4185ljo5txi.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A robust agent should not decide that a page “looks like” an AWS WAF challenge. It should receive a typed signal from deterministic code, run only tools approved for that target and purpose, and continue only after the original operation has been verified.&lt;/p&gt;

&lt;p&gt;This tutorial builds that boundary around LangChain or LangGraph. The examples are for systems you own or are explicitly authorized to automate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AWS WAF changes in an agent workflow
&lt;/h2&gt;

&lt;p&gt;AWS documents two response patterns that matter here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Challenge: HTTP &lt;code&gt;202&lt;/code&gt; with &lt;code&gt;x-amzn-waf-action: challenge&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CAPTCHA: HTTP &lt;code&gt;405&lt;/code&gt; with &lt;code&gt;x-amzn-waf-action: captcha&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With a valid token, the request continues to the next rule. Without one, a browser may receive a JavaScript interstitial. A successful interaction updates client token state and resubmits the request.&lt;/p&gt;

&lt;p&gt;An agent-facing HTTP tool can misread these responses as success, an empty page, or a transient server error. The fix is not more prompting. The host application should classify the response and route it through a bounded recovery path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use five separate components
&lt;/h2&gt;

&lt;p&gt;Keep these responsibilities independent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; selects the next business action from a restricted tool set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/browser client:&lt;/strong&gt; owns cookies, headers, and page state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy gate:&lt;/strong&gt; checks target, purpose, redirects, and retry budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenge adapter:&lt;/strong&gt; exposes only documented capabilities needed by the recovery node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifier:&lt;/strong&gt; repeats the intended action and checks an application-owned success condition.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://docs.capsolver.com/en/guide/ai/agent-tools/" rel="noopener noreferrer"&gt;CapSolver’s agent tools guide&lt;/a&gt; describes &lt;code&gt;capsolver-agent&lt;/code&gt; as an adapter over &lt;code&gt;capsolver-core&lt;/code&gt;. Its LangChain path supplies framework-compatible tools through &lt;code&gt;get_langchain_tools()&lt;/code&gt;. That lets application code decide when a tool can run while the model sees only a narrow contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare an authorized test environment
&lt;/h2&gt;

&lt;p&gt;Define the boundary before installing packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allowlisted hostnames you own or have explicit permission to test;&lt;/li&gt;
&lt;li&gt;approved purposes such as QA validation;&lt;/li&gt;
&lt;li&gt;a secret store for model and CapSolver credentials;&lt;/li&gt;
&lt;li&gt;one session owner for detection, recovery, retry, and verification;&lt;/li&gt;
&lt;li&gt;a small retry and total-time budget;&lt;/li&gt;
&lt;li&gt;a specific success assertion;&lt;/li&gt;
&lt;li&gt;a review route for unknown signals or state-changing actions;&lt;/li&gt;
&lt;li&gt;redaction rules for tokens, cookies, credentials, and page data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set up an isolated environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/capsolver-ai/capsolver-core.git
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"capsolver-agent[langchain] @ git+https://github.com/capsolver-ai/capsolver-agent.git"&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain-openai langgraph playwright

playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Load credentials from the environment for local development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"set-this-in-your-secret-manager"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"set-this-in-your-secret-manager"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not put real values in prompts, traces, notebooks, issues, or graph checkpoints. Use a managed secret store in deployed environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classify the WAF response outside the model
&lt;/h2&gt;

&lt;p&gt;Require the documented header and status together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;

&lt;span class="n"&gt;WafAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;challenge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WafAction&lt;/span&gt;
    &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;needs_review&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_aws_waf_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-amzn-waf-action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;challenge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;202&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;challenge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;challenge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;needs_review&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;WafSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;202&lt;/code&gt; by itself may be a valid asynchronous response. A &lt;code&gt;405&lt;/code&gt; by itself may simply reject the method. Mismatched signals should lead to review.&lt;/p&gt;

&lt;p&gt;AWS notes that cross-origin browser JavaScript cannot read &lt;code&gt;x-amzn-waf-action&lt;/code&gt; through CORS. In that case, classify the network response in the automation layer or use an owned same-origin integration; do not infer the result from page text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a deterministic authorization gate
&lt;/h2&gt;

&lt;p&gt;The model should never expand the list of allowed targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlparse&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;


&lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;staging.example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research.example.org&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;ALLOWED_PURPOSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qa-validation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorized-research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authorize_recovery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host-not-allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_PURPOSES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;purpose-not-allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retry-budget-exhausted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PolicyDecision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production, read this configuration from a reviewed, versioned source. Validate redirects too, and record only non-sensitive policy metadata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Register the smallest CapSolver tool set
&lt;/h2&gt;

&lt;p&gt;The documented adapter can create LangChain-compatible tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_langchain_tools&lt;/span&gt;


&lt;span class="n"&gt;capsolver_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_langchain_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LangChain and LangGraph construction APIs evolve, so isolate this wiring and pin versions that pass your integration tests. Do not give every agent every tool. Make challenge handling available only from the recovery subgraph after authorization succeeds.&lt;/p&gt;

&lt;p&gt;CapSolver documents mappings for &lt;code&gt;solve_captcha&lt;/code&gt;, &lt;code&gt;detect_captchas&lt;/code&gt;, and &lt;code&gt;solve_on_page&lt;/code&gt;, backed by corresponding core capabilities. Choose the smallest appropriate capability. A browser-oriented flow can preserve page context without exposing raw solution data to the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the browser out of graph state
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/waf/latest/developerguide/waf-tokens-usage.html" rel="noopener noreferrer"&gt;AWS WAF token documentation&lt;/a&gt; explains that Challenge and CAPTCHA actions use client tokens to track completed interactions. Starting a new browser between detection and retry can discard that state.&lt;/p&gt;

&lt;p&gt;Store browser objects in an application-owned registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BrowserRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;browser page is not registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Graph state needs only the opaque &lt;code&gt;page_id&lt;/code&gt;, current URL, purpose, attempt count, and typed status. Exclude cookies, storage, tokens, API keys, raw HTML, and browser objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route on typed results
&lt;/h2&gt;

&lt;p&gt;Use a compact state contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;

&lt;span class="n"&gt;RecoveryStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_needed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;denied&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RecoveryState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;request_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;current_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;waf_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;recovery_status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RecoveryStatus&lt;/span&gt;
    &lt;span class="n"&gt;error_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;final_assertion_passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route_after_detection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RecoveryState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;waf_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;challenge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recovery_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recover&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recovery_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;denied&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;human_review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route_after_recovery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RecoveryState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recovery_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;human_review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The recovery node may call the approved tool, but it should return only a typed status and stable error code—not the raw tool response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the original operation
&lt;/h2&gt;

&lt;p&gt;Challenge completion is not proof that the business action succeeded. Repeat the intended operation in the same session and assert something your application controls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_expected_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_url_prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_load_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domcontentloaded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_url_prefix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_by_test_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorized-content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;visible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer a stable test ID, expected API response, or known state transition. Avoid broad text checks because error pages often contain plausible-looking words.&lt;/p&gt;

&lt;p&gt;If verification fails, reclassify the current response and inspect session state. Do not immediately invoke another recovery attempt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bound retries, logs, and monitoring
&lt;/h2&gt;

&lt;p&gt;Route known, authorized signals to recovery. Route mismatches, unexpected redirects, missing sessions, and exhausted budgets to review or denial. A transient timeout may receive one retry if the total budget allows it; there should be no unbounded loop.&lt;/p&gt;

&lt;p&gt;Log events such as &lt;code&gt;waf_signal_detected&lt;/code&gt;, &lt;code&gt;policy_allowed&lt;/code&gt;, &lt;code&gt;recovery_started&lt;/code&gt;, &lt;code&gt;recovery_finished&lt;/code&gt;, and &lt;code&gt;page_verified&lt;/code&gt;. Include an internal request ID, hostname, duration, attempt number, and stable error code. Exclude credentials, cookies, tokens, raw challenge data, and sensitive page content.&lt;/p&gt;

&lt;p&gt;AWS exposes CloudWatch metrics for Challenge and CAPTCHA activity in its &lt;a href="https://docs.aws.amazon.com/waf/latest/developerguide/waf-metrics.html" rel="noopener noreferrer"&gt;WAF metrics reference&lt;/a&gt;. Correlate agent decisions and infrastructure metrics using an internal request ID—not a credential or token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the failure paths
&lt;/h2&gt;

&lt;p&gt;Before production, test:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;normal response without a challenge;&lt;/li&gt;
&lt;li&gt;documented Challenge signal;&lt;/li&gt;
&lt;li&gt;documented CAPTCHA signal;&lt;/li&gt;
&lt;li&gt;header/status mismatch;&lt;/li&gt;
&lt;li&gt;unapproved hostname;&lt;/li&gt;
&lt;li&gt;redirect outside the allowlist;&lt;/li&gt;
&lt;li&gt;missing browser session;&lt;/li&gt;
&lt;li&gt;tool timeout;&lt;/li&gt;
&lt;li&gt;failed final assertion;&lt;/li&gt;
&lt;li&gt;retry-budget exhaustion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unit-test the classifier, policy gate, and verifier. Use credentialed end-to-end tests only on an approved environment. Add explicit assertions that logs contain no credentials, cookies, or token values.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture in one line
&lt;/h2&gt;

&lt;p&gt;The dependable sequence is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;detect → authorize → recover → retry original action → verify → continue/review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For authorized automation, &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=how-to-solve-aws-waf-in-langchain" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; supplies documented agent and core layers for LangChain integrations. Your application should still own policy, secrets, session state, retries, and the final assertion.&lt;/p&gt;

&lt;p&gt;Use the &lt;a href="https://docs.capsolver.com/en/" rel="noopener noreferrer"&gt;current CapSolver documentation&lt;/a&gt; when implementing the integration, and do not guess API fields from outdated snippets.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>aws</category>
    </item>
    <item>
      <title>How to Solve reCAPTCHA Enterprise in Browser Use (with CapSolver)</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Thu, 16 Jul 2026 08:43:49 +0000</pubDate>
      <link>https://dev.to/luisgustvo/how-to-solve-recaptcha-enterprise-in-browser-use-with-capsolver-16ik</link>
      <guid>https://dev.to/luisgustvo/how-to-solve-recaptcha-enterprise-in-browser-use-with-capsolver-16ik</guid>
      <description>&lt;h2&gt;
  
  
  TL;Dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Browser Use developers can solve reCAPTCHA Enterprise challenges by integrating CapSolver's API through custom controller actions.&lt;/li&gt;
&lt;li&gt;The Browser Use framework allows AI agents to control web browsers using natural language, but CAPTCHAs remain a primary obstacle.&lt;/li&gt;
&lt;li&gt;Integration involves defining a custom action that detects the CAPTCHA, calls the CapSolver API, and injects the solution back into the page.&lt;/li&gt;
&lt;li&gt;Using specialized solving services like CapSolver ensures that autonomous browsing tasks can proceed without manual intervention.&lt;/li&gt;
&lt;li&gt;This approach is essential for large-scale data scraping and automated form filling on protected websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The evolution of AI agents has led to the development of powerful frameworks like Browser Use, which enables models to control web browsers and perform complex tasks autonomously. Browser Use leverages Playwright for browser automation and integrates with large language models to interpret natural language commands. However, the effectiveness of these agents is often limited by anti-bot measures, particularly reCAPTCHA Enterprise. These sophisticated challenges are designed to detect and block automated traffic, often stalling an agent's progress. To maintain the flow of autonomous tasks, developers can integrate CapSolver's solving capabilities directly into the Browser Use workflow. This guide provides a technical walkthrough on how to solve reCAPTCHA Enterprise in Browser Use, focusing on the setup, custom action definition, and practical implementation. By automating the resolution of these challenges, you can ensure your AI agents operate efficiently across a wide range of protected web environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Role of Browser Use in Modern Automation
&lt;/h2&gt;

&lt;p&gt;Browser Use is an open-source Python library that simplifies the process of building AI agents that can browse the web. Unlike traditional automation tools that require explicit coding for every interaction, Browser Use allows developers to issue high-level instructions that the agent then translates into browser actions. This makes it an ideal choice for tasks like market research, competitive price monitoring, and automated account management.&lt;/p&gt;

&lt;p&gt;Despite its power, Browser Use is not inherently designed to bypass advanced security measures like reCAPTCHA Enterprise. When an agent encounters such a challenge, it typically fails to proceed unless a specific mechanism is in place to handle the resolution. Integrating a dedicated solving service is the most reliable way to overcome this hurdle. For a deeper understanding of the tools available for these tasks, exploring &lt;a href="https://www.capsolver.com/blog/web-scraping/webscraping-tools-explained" rel="noopener noreferrer"&gt;webscraping tools explained&lt;/a&gt; can provide valuable context on the current automation landscape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why reCAPTCHA Enterprise Requires Specialized Solving
&lt;/h2&gt;

&lt;p&gt;reCAPTCHA Enterprise is a more advanced version of the standard reCAPTCHA system, offering enhanced protection against automated attacks. It uses a scoring system and various behavioral analysis techniques to distinguish between legitimate users and bots. For an AI agent, solving these challenges manually is not feasible, and simple script-based bypasses are often ineffective against the enterprise-grade detection used by Google.&lt;/p&gt;

&lt;p&gt;CapSolver provides a robust solution by offering an AI-powered API specifically tuned for reCAPTCHA Enterprise. By offloading the solving process to CapSolver, your Browser Use agent can obtain the necessary tokens to pass the verification without having to navigate the challenge itself. This is particularly important for high-stakes automation where reliability and speed are critical. You can learn more about the technical nuances of this challenge in the guide on &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/bypass-recaptcha-v2-enterprise" rel="noopener noreferrer"&gt;how to solve recaptcha enterprise&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating CapSolver with Browser Use
&lt;/h2&gt;

&lt;p&gt;The integration process involves extending the Browser Use controller with a custom action that handles the CAPTCHA resolution. This allows the agent to call the solver whenever it detects a challenge on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Prerequisites and Installation
&lt;/h3&gt;

&lt;p&gt;Before you can implement the solving logic, you need to install the required libraries and set up your environment. Ensure you have an active CapSolver account and your API key ready.&lt;/p&gt;

&lt;p&gt;First, install the Browser Use library and its dependencies:&lt;br&gt;
pip install browser-use playwright requests&lt;/p&gt;

&lt;p&gt;Next, ensure that Playwright has the necessary browser binaries:&lt;br&gt;
playwright install chromium&lt;/p&gt;

&lt;p&gt;Finally, set your CapSolver API key as an environment variable to keep it secure:&lt;br&gt;
export CAPSOLVER_API_KEY="your-capsolver-api-key"&lt;/p&gt;

&lt;p&gt;By using the official &lt;a href="https://github.com/capsolver-ai/capsolver-core" rel="noopener noreferrer"&gt;capsolver-core&lt;/a&gt; engine as a reference, you can build a highly reliable integration that scales with your automation needs.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Defining a Custom Controller Action
&lt;/h3&gt;

&lt;p&gt;In Browser Use, the Controller class manages the actions available to the agent. You can define a custom action using the @controller.action decorator. This action will be responsible for detecting the reCAPTCHA Enterprise site key, calling the CapSolver API, and injecting the resulting token into the page.&lt;/p&gt;

&lt;p&gt;The action logic typically follows these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect the presence of a reCAPTCHA element on the current page.&lt;/li&gt;
&lt;li&gt;Extract the site key and the page URL.&lt;/li&gt;
&lt;li&gt;Send a request to CapSolver to create a solving task.&lt;/li&gt;
&lt;li&gt;Poll the CapSolver API for the solution.&lt;/li&gt;
&lt;li&gt;Inject the solution token into the hidden g-recaptcha-response field and trigger the callback function if necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This modular approach ensures that the solving logic is reusable across different tasks and websites. For developers looking for more &lt;a href="https://docs.capsolver.com/en/guide/ai/agent-tools/" rel="noopener noreferrer"&gt;integrated agent tools&lt;/a&gt;, CapSolver provides specialized libraries that simplify this process even further.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation Example: Solving reCAPTCHA Enterprise
&lt;/h2&gt;

&lt;p&gt;The following code snippet demonstrates how to implement the custom action within a Browser Use script. This example uses the requests library to communicate with the CapSolver API and Playwright to interact with the browser page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;browser_use&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ActionResult&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Page&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@controller.action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Solve reCAPTCHA Enterprise&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_captcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Detect site key
&lt;/span&gt;    &lt;span class="n"&gt;site_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document.querySelector(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.g-recaptcha&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;).getAttribute(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data-sitekey&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;page_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;

    &lt;span class="c1"&gt;# Create task with CapSolver
&lt;/span&gt;    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2EnterpriseTaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;page_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;site_key&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/createTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Poll for result
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/getTaskResult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ready&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Inject token
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document.getElementById(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;).innerHTML = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA solved and token injected.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This custom action can then be used by the AI agent whenever it encounters a reCAPTCHA Enterprise challenge. To understand the different parameters required for various versions, refer to the article on &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-v2" rel="noopener noreferrer"&gt;how to solve recaptcha v2&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Summary: Manual vs. Automated Solving in Browser Use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual Solving in Browser Use&lt;/th&gt;
&lt;th&gt;CapSolver API Integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Automation Level&lt;/td&gt;
&lt;td&gt;Low (requires human intervention)&lt;/td&gt;
&lt;td&gt;High (fully autonomous)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success Rate&lt;/td&gt;
&lt;td&gt;High (but slow)&lt;/td&gt;
&lt;td&gt;High (fast and reliable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical Complexity&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Moderate (requires custom action setup)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integration&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Browser Use Controller / Custom Action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;High (breaks on UI changes)&lt;/td&gt;
&lt;td&gt;Low (handled by CapSolver API)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Best Practices for Browser Use Agents
&lt;/h2&gt;

&lt;p&gt;To maximize the reliability of your Browser Use agents, consider the following best practices for CAPTCHA resolution and general automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Intelligent Detection Logic
&lt;/h3&gt;

&lt;p&gt;Instead of calling the solver on every page load, implement logic to detect if a CAPTCHA is actually present and blocking the task. This saves API credits and reduces the overall execution time of your agent. Using the &lt;a href="https://www.capsolver.com/blog/web-scraping/top-5-web-scraping-services" rel="noopener noreferrer"&gt;top 5 web scraping services&lt;/a&gt; in combination with CapSolver can help you build more robust detection mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Managing Browser Context
&lt;/h3&gt;

&lt;p&gt;Browser Use allows you to maintain a persistent browser context, which is essential for tasks that require logging in or navigating through multiple pages. Ensure that your CAPTCHA solution is applied within the correct context so that the website recognizes the verification. For more advanced browser-based strategies, learning &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-in-web-scraping-using-python" rel="noopener noreferrer"&gt;how to solve recaptcha in web scraping using python&lt;/a&gt; is highly recommended.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Proxy Usage and Rotation
&lt;/h3&gt;

&lt;p&gt;To avoid IP-based blocking, it is essential to use a reliable proxy network. CapSolver allows you to use your own proxies during the solving process, which helps maintain a consistent IP identity for your agent. Selecting the &lt;a href="https://www.capsolver.com/blog/web-scraping/best-proxy-services" rel="noopener noreferrer"&gt;best proxy services&lt;/a&gt; is a key factor in the long-term success of your automation infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Robust Error Handling
&lt;/h3&gt;

&lt;p&gt;Always include error handling in your custom actions. If the CapSolver API returns an error or if the token fails to validate on the page, the agent should be able to retry the solve or log the issue for developer review. Understanding &lt;a href="https://www.capsolver.com/blog/The-other-captcha/what-are-captchas" rel="noopener noreferrer"&gt;what are captchas&lt;/a&gt; and how they evolve will help you build more resilient error recovery logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Solving reCAPTCHA Enterprise in Browser Use is a vital capability for developers building autonomous AI agents for the modern web. By integrating CapSolver's AI-powered API through custom controller actions, you can ensure that your agents can overcome even the most sophisticated anti-bot defenses. This integration not only enhances the reliability of your automation tasks but also provides the scalability needed for large-scale operations. As the field of AI agents continues to grow, having a robust strategy for CAPTCHA resolution will remain a critical requirement for success. We encourage you to explore the official documentation and GitHub repositories for &lt;a href="https://github.com/browser-use/browser-use" rel="noopener noreferrer"&gt;Browser Use&lt;/a&gt; and CapSolver to fully leverage these technologies in your projects.&lt;/p&gt;

</description>
      <category>browser</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Solve AWS WAF in LangChain: A Technical Guide for AI Agents</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Wed, 15 Jul 2026 09:10:53 +0000</pubDate>
      <link>https://dev.to/luisgustvo/how-to-solve-aws-waf-in-langchain-a-technical-guide-for-ai-agents-4bpl</link>
      <guid>https://dev.to/luisgustvo/how-to-solve-aws-waf-in-langchain-a-technical-guide-for-ai-agents-4bpl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ym1y8qr4iqxjt9pa4xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ym1y8qr4iqxjt9pa4xp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;Dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;LangChain developers can handle AWS WAF challenges in authorized workflows by integrating CapSolver agent tools into their agentic workflows.&lt;/li&gt;
&lt;li&gt;The capsolver-agent library provides a seamless adapter layer for LangChain, enabling models to call solving tools directly.&lt;/li&gt;
&lt;li&gt;Integration involves setting up capsolver-core and capsolver-agent from their official GitHub repositories.&lt;/li&gt;
&lt;li&gt;Using the ReAct framework in LangChain allows AI agents to autonomously detect and handle AWS WAF challenges in authorized workflows.&lt;/li&gt;
&lt;li&gt;Specialized solving tools can help for maintaining the reliability of long-running AI agent tasks on protected websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As enterprises increasingly deploy AI agents to automate complex web-based tasks, the role of security frameworks like AWS WAF (Web Application Firewall) has become a significant focus for developers. AWS WAF is designed to protect web applications from various threats, including automated scraping and bot-driven attacks. For developers using LangChain to build autonomous agents, encountering an AWS WAF challenge can halt a task and disrupt the entire workflow. To respond to this, CapSolver provides a specialized set of agent tools that can be integrated directly into LangChain. This guide provides a technical walkthrough on how to solve AWS WAF in LangChain, ensuring your AI agents can handle permitted challenge flows programmatically. we will explore the architecture of this integration, the installation process, and how to implement solving logic within a LangChain agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of AWS WAF in AI Automation
&lt;/h2&gt;

&lt;p&gt;AWS WAF uses a variety of techniques to identify and block automated traffic. This includes rate limiting, IP reputation checks, and cryptographic challenges that require a browser-like environment to solve. For an AI agent built with LangChain, these challenges appear as interruptions that prevent the model from accessing the required data or completing an action. Unlike traditional web scraping, where a developer might manually handle a block, an autonomous agent needs a way to detect and resolve these challenges on its own.&lt;/p&gt;

&lt;p&gt;The integration of CapSolver into LangChain addresses this by providing the model with a "tool" for solving. In the LangChain ecosystem, tools are capabilities that the model can choose to use based on the context of the task. By providing an AWS WAF solving tool, you empower the agent to recognize when it is being blocked and to call the CapSolver API to obtain the necessary token or cookie to proceed. This approach maintains the agent's autonomy while reducing manual interruption in permitted data and testing workflows. For more context on the types of challenges you might face, you can read about &lt;a href="https://www.capsolver.com/blog/web-scraping/webscraping-tools-explained" rel="noopener noreferrer"&gt;webscraping tools explained&lt;/a&gt; to understand the broader security landscape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural Overview: capsolver-agent and LangChain
&lt;/h2&gt;

&lt;p&gt;The integration is built on a layered architecture that ensures a clean separation between the AI model's decision-making and the technical execution of the solve.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Role of capsolver-core
&lt;/h3&gt;

&lt;p&gt;At the foundation is the capsolver-core engine. This is the primary library that handles the communication with the CapSolver API. It contains the logic for submitting challenges, polling for results, and returning the final solution. This core engine is agnostic to the AI framework being used and serves as the technical heart of the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The capsolver-agent Adapter
&lt;/h3&gt;

&lt;p&gt;The capsolver-agent library acts as a thin adapter layer over the core engine. Its primary purpose is to wrap the core's capabilities into a format that LLMs can understand. This includes generating the JSON schemas for the tools and providing an executor that dispatches the model's tool calls to the core engine. This adapter layer is what makes it possible to "hand the tools to the model" in a framework like LangChain. You can explore the &lt;a href="https://github.com/capsolver-ai/capsolver-agent" rel="noopener noreferrer"&gt;capsolver-agent&lt;/a&gt; repository for more details on this implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. LangChain Integration
&lt;/h3&gt;

&lt;p&gt;In LangChain, these tools are exposed as BaseTool objects. When the agent is running in a loop (such as a ReAct loop), it can inspect the page content, detect an AWS WAF challenge, and decide to use the CapSolver tool. The tool then interacts with the core engine, gets the solution, and returns it to the agent, which can then apply the solution (e.g., by setting a cookie or adding a header) and continue its task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and Environment Setup
&lt;/h2&gt;

&lt;p&gt;To begin solving AWS WAF in LangChain, you need to install the CapSolver libraries from GitHub. It is recommended to use the latest versions to ensure compatibility with recent AWS WAF updates.&lt;/p&gt;

&lt;p&gt;First, install the core engine:&lt;br&gt;
pip install git+&lt;a href="https://github.com/capsolver-ai/capsolver-core.git" rel="noopener noreferrer"&gt;https://github.com/capsolver-ai/capsolver-core.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, install the agent library with LangChain support:&lt;br&gt;
pip install "capsolver-agent[langchain] @ git+&lt;a href="https://github.com/capsolver-ai/capsolver-agent.git" rel="noopener noreferrer"&gt;https://github.com/capsolver-ai/capsolver-agent.git&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;You will also need to install the LangChain OpenAI package and the LangGraph library if you are building complex agentic workflows:&lt;br&gt;
pip install langchain-openai langgraph&lt;/p&gt;

&lt;p&gt;Finally, ensure your CapSolver API key is set as an environment variable:&lt;br&gt;
export CAPSOLVER_API_KEY="your-capsolver-api-key"&lt;/p&gt;

&lt;p&gt;These steps establish the technical environment required for your agent to access CapSolver's solving capabilities. By using the official &lt;a href="https://github.com/capsolver-ai/capsolver-core" rel="noopener noreferrer"&gt;capsolver-core&lt;/a&gt; repository, you ensure your infrastructure is built on a reliable and high-performance engine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing AWS WAF Solving in LangChain
&lt;/h2&gt;

&lt;p&gt;The most effective way to integrate solving into LangChain is by using the create_executor function from the agent library. This function assembles the necessary components and provides a set of tools that can be passed directly to a LangChain agent.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Creating the Toolset
&lt;/h3&gt;

&lt;p&gt;The capsolver-agent library includes a helper function called get_langchain_tools() that returns a list of tools compatible with LangChain's tool-calling interface. These tools cover various CAPTCHA types, including the specific requirements for AWS WAF.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Wiring the Agent Loop
&lt;/h3&gt;

&lt;p&gt;In a typical LangChain agent setup, you define the tools, the model, and the prompt, and then use an agent executor to run the loop. When the agent hits an AWS WAF challenge, it will see the challenge in the page content and use the solve_captcha tool to get a solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example of integrating CapSolver tools into a LangChain agent
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentExecutor&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_langchain_tools&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize the model and tools
&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_langchain_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the prompt and create the agent
&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hwchase17/react&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent_executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AgentExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run the agent on a task involving AWS WAF
# agent_executor.invoke({"input": "Navigate to the protected page at https://example.com and extract the data."})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation allows the agent to handle the challenge as part of its normal reasoning process. If you need to understand the specific steps for handling these challenges, the guide on &lt;a href="https://www.capsolver.com/blog/aws-waf/how-to-solve-aws-amazon-captcha-token" rel="noopener noreferrer"&gt;how to solve AWS WAF&lt;/a&gt; provides a detailed breakdown of the required parameters and response formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Summary: Manual vs. LangChain-Integrated Solving
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual Solving in LangChain&lt;/th&gt;
&lt;th&gt;CapSolver Agent Integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Integration Logic&lt;/td&gt;
&lt;td&gt;Complex, custom-built for each task&lt;/td&gt;
&lt;td&gt;Simplified, standardized tool adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model Autonomy&lt;/td&gt;
&lt;td&gt;Low (requires explicit instructions)&lt;/td&gt;
&lt;td&gt;High (model decides when to solve)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success Rate&lt;/td&gt;
&lt;td&gt;Variable based on custom code&lt;/td&gt;
&lt;td&gt;Structured tool result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;High (breaks on AWS WAF updates)&lt;/td&gt;
&lt;td&gt;Centralized interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocol Support&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;LangChain Tool-Calling / ReAct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library Support&lt;/td&gt;
&lt;td&gt;capsolver-core&lt;/td&gt;
&lt;td&gt;capsolver-agent + capsolver-core&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Advanced Strategies for AWS WAF Resolution
&lt;/h2&gt;

&lt;p&gt;AWS WAF challenges often require more than just a simple token. They may involve specific cookies or headers that must be present in subsequent requests. A robust LangChain agent should be designed to handle these complexities.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cookie and Header Management
&lt;/h3&gt;

&lt;p&gt;When the solve_captcha tool returns a solution for AWS WAF, it often includes a cookie (e.g., aws-waf-token). Your agent must be able to extract this cookie from the tool's response and apply it to its future browser sessions or API calls. Frameworks like Browser Use are particularly well-suited for this because they maintain a persistent browser state throughout the agent's task.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Utilizing Browser Mode
&lt;/h3&gt;

&lt;p&gt;For agents that interact directly with the DOM, using the solve_on_page tool can be more effective. This tool allows the agent to delegate the entire detection and resolution process to CapSolver, which will then fill the solution back into the page. This is especially useful for challenges that require complex interaction with the page's JavaScript environment. For more information on this approach, you can read about &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-in-web-scraping-using-python" rel="noopener noreferrer"&gt;how to solve recaptcha in web scraping using python&lt;/a&gt; for similar browser-based strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Proxy Integration
&lt;/h3&gt;

&lt;p&gt;AWS WAF is highly sensitive to the reputation of the IP address making the request. To keep network conditions consistent with the authorized workflow, it is essential to use high-quality proxies. CapSolver allows you to provide your own proxy information during the solve request, ensuring that the solve occurs from an IP that is consistent with your agent's traffic. Selecting the &lt;a href="https://www.capsolver.com/blog/web-scraping/best-proxy-services" rel="noopener noreferrer"&gt;best proxy services&lt;/a&gt; is a critical part of building a resilient infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for AI Agent Reliability
&lt;/h2&gt;

&lt;p&gt;To build reliable AI agents that can consistently respond to AWS WAF challenges, follow these operational best practices:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Implement Intelligent Retries
&lt;/h3&gt;

&lt;p&gt;Web security measures can be unpredictable. Your LangChain agent should include retry logic that allows it to attempt a solve again if the first one fails. This should be combined with exponential backoff to avoid triggering further security blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Monitor Agent Performance
&lt;/h3&gt;

&lt;p&gt;Track the success and failure rates of your CAPTCHA solves. This data is invaluable for identifying patterns and optimizing your agent's logic. If you notice a drop in success rates for a specific site, it may indicate a change in the site's AWS WAF configuration that requires an update to your solving parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ensure Compliance and Ethics
&lt;/h3&gt;

&lt;p&gt;Always ensure that your agent's activities comply with the target website's terms of service and relevant legal frameworks. Use automation responsibly and avoid activities that could negatively impact the target application's performance. For a foundational understanding of these concepts, refer to the article on &lt;a href="https://www.capsolver.com/blog/The-other-captcha/what-are-captchas" rel="noopener noreferrer"&gt;what are captchas&lt;/a&gt; to understand their intended purpose in web security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Handling AWS WAF challenges in LangChain can be useful for developers building advanced AI agents for web automation. By integrating CapSolver's agent tools, you provide your models with the necessary capabilities to respond to permitted challenge flows through explicit tools. Whether you are using the standardized LangChain tool-calling interface or building custom agentic loops, the combination of capsolver-agent and capsolver-core provides a structured integration path. As the web security landscape continues to evolve, having a reliable strategy for AWS WAF resolution will remain a cornerstone of successful AI agent development. We encourage you to explore the official documentation and GitHub repositories to fully leverage these tools in your LangChain projects. For more information on LangChain, visit the &lt;a href="https://www.langchain.com/" rel="noopener noreferrer"&gt;LangChain official site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>langchain</category>
    </item>
    <item>
      <title>Add reCAPTCHA v2 Handling to Cursor with CapSolver MCP</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Tue, 14 Jul 2026 09:57:18 +0000</pubDate>
      <link>https://dev.to/luisgustvo/add-recaptcha-v2-handling-to-cursor-with-capsolver-mcp-1lcg</link>
      <guid>https://dev.to/luisgustvo/add-recaptcha-v2-handling-to-cursor-with-capsolver-mcp-1lcg</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdfu1ql34s474mrecrrcr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdfu1ql34s474mrecrrcr.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cursor can call CapSolver through the Model Context Protocol (MCP), so an AI agent can handle reCAPTCHA v2 in an authorized browser or data workflow.&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;capsolver-core&lt;/code&gt; and &lt;code&gt;capsolver-mcp&lt;/code&gt;, add the server to Cursor, and expose your API key through an environment variable.&lt;/li&gt;
&lt;li&gt;Use token mode when the agent already knows the page URL and site key; use browser mode when Playwright must detect and complete the challenge on the page.&lt;/li&gt;
&lt;li&gt;For agents outside Cursor, &lt;code&gt;capsolver-agent&lt;/code&gt; provides a thin tool-calling layer over the same core engine.&lt;/li&gt;
&lt;li&gt;Add rate limits, retries, logging, and permission checks before using CAPTCHA automation in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why MCP Matters for AI Development
&lt;/h2&gt;

&lt;p&gt;AI coding environments are increasingly able to plan and execute multi-step tasks, but they still need explicit tools for actions outside the model. A reCAPTCHA v2 prompt can interrupt an otherwise automated test, browser workflow, or public-data collection task. MCP addresses that gap by giving Cursor a standard way to discover and invoke external capabilities.&lt;/p&gt;

&lt;p&gt;After the CapSolver MCP server is connected, Cursor can see tool definitions for operations such as challenge detection and solution generation. The model does not need a custom adapter for every project. It selects a tool, supplies structured arguments, and receives a structured result. For more context on how these components fit into a broader automation stack, see this overview of &lt;a href="https://www.capsolver.com/blog/web-scraping/webscraping-tools-explained" rel="noopener noreferrer"&gt;web-scraping tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Use this integration only on websites and workflows you are authorized to automate. Respect site terms, privacy requirements, and applicable laws.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the CapSolver MCP Server
&lt;/h2&gt;

&lt;p&gt;The setup has two parts: the shared solving engine and the MCP service that exposes it to Cursor.&lt;/p&gt;

&lt;p&gt;Install the core package from its official repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/capsolver-ai/capsolver-core.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/capsolver-ai/capsolver-mcp.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your workflow needs an actual browser session, install the browser extras and Chromium:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"capsolver-mcp[browser] @ git+https://github.com/capsolver-ai/capsolver-mcp.git"&lt;/span&gt;
playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official &lt;a href="https://github.com/capsolver-ai/capsolver-mcp" rel="noopener noreferrer"&gt;capsolver-mcp repository&lt;/a&gt; is the best place to check current installation and configuration details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Cursor
&lt;/h3&gt;

&lt;p&gt;Open Cursor's MCP settings and register a server with these values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: capsolver
Type: stdio
Command: capsolver-mcp
Environment Variables: CAPSOLVER_API_KEY=YOUR_API_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obtain the API key from your CapSolver dashboard and keep it out of source control. If Cursor cannot resolve &lt;code&gt;capsolver-mcp&lt;/code&gt;, specify the absolute path to the Python executable and launch the package with &lt;code&gt;-m capsolver_mcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the configuration is saved and the process connects successfully, Cursor should display the tools exposed by the server, including tools such as &lt;code&gt;solve_captcha&lt;/code&gt; and &lt;code&gt;detect_captchas&lt;/code&gt;. At that point an agent can request a solve as part of an authorized workflow without embedding the integration logic in every prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose Between Token Mode and Browser Mode
&lt;/h2&gt;

&lt;p&gt;CapSolver MCP supports two useful patterns for reCAPTCHA v2. The right option depends on whether your agent already controls the request data or must interact with a rendered page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token mode with &lt;code&gt;solve_captcha&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Token mode is suited to API-oriented workflows. The agent sends the target page URL and the reCAPTCHA site key. The service returns a &lt;code&gt;g-recaptcha-response&lt;/code&gt; token that the authorized application can place in its form submission.&lt;/p&gt;

&lt;p&gt;Because this approach does not require a full browser session, it typically uses fewer local resources and is easier to incorporate into repeatable pipelines. It works well when the page structure and site key are already known. The CapSolver guide to &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-v2" rel="noopener noreferrer"&gt;solving reCAPTCHA v2&lt;/a&gt; describes the relevant request parameters in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser mode with &lt;code&gt;solve_on_page&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Browser mode is useful when an agent operates through Playwright or another browser-driving framework. The MCP tool opens or controls the page, detects the challenge, obtains a solution, and places the result into the page. This keeps challenge detection and field handling out of the agent's higher-level task logic.&lt;/p&gt;

&lt;p&gt;The pattern is particularly useful for browser agents and end-to-end QA flows, where the surrounding interaction already depends on a live DOM. Enterprise variants may require additional parameters; consult the relevant &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/bypass-recaptcha-v2-enterprise" rel="noopener noreferrer"&gt;reCAPTCHA v2 Enterprise guide&lt;/a&gt; and apply the technique only in permitted environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual Handling Compared with MCP Integration
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual handling&lt;/th&gt;
&lt;th&gt;CapSolver MCP integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;Custom logic for each workflow&lt;/td&gt;
&lt;td&gt;Standard tools exposed through MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling&lt;/td&gt;
&lt;td&gt;Requires repeated human intervention&lt;/td&gt;
&lt;td&gt;Can be incorporated into automated jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Page-specific code must be maintained&lt;/td&gt;
&lt;td&gt;Solving interface is centralized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Depends on a person being available&lt;/td&gt;
&lt;td&gt;Designed for machine-driven workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Results&lt;/td&gt;
&lt;td&gt;Vary with manual operation&lt;/td&gt;
&lt;td&gt;Returned as structured tool output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interface&lt;/td&gt;
&lt;td&gt;No shared protocol&lt;/td&gt;
&lt;td&gt;Model Context Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Build Agents Outside Cursor with &lt;code&gt;capsolver-agent&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Cursor is not the only place where the core tools can be used. The &lt;a href="https://github.com/capsolver-ai/capsolver-agent" rel="noopener noreferrer"&gt;capsolver-agent&lt;/a&gt; package provides a small wrapper that maps an LLM's tool call to methods in the underlying engine. This separation is helpful in LangChain, the OpenAI Agents SDK, or a custom orchestration loop: the model decides when a challenge tool is needed, while the executor remains responsible for validation and execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example of using capsolver-agent in a custom loop
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.schema&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_executor&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_challenge&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solve_captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reCaptchaV2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Le-wvkSAAAAAPBMRT...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Solution found: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# asyncio.run(handle_challenge())
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The executor is deliberately thin. Your application should still decide which domains are allowed, protect credentials, validate tool arguments, record failures, and prevent uncontrolled retries. The &lt;a href="https://github.com/capsolver-ai/capsolver-core" rel="noopener noreferrer"&gt;capsolver-core repository&lt;/a&gt; contains the underlying engine used by this style of integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Practices for Responsible CAPTCHA Automation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Respect rate limits and server capacity
&lt;/h3&gt;

&lt;p&gt;Throttle requests and introduce sensible delays. A solver is not permission to generate excessive traffic. Set per-domain limits, cap concurrency, and stop jobs when a site returns repeated rate-limit or access errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use appropriate network infrastructure
&lt;/h3&gt;

&lt;p&gt;Network reputation can affect whether a challenge appears and whether a session remains stable. Select infrastructure that matches the authorized use case and avoid rotating identities to evade a site's controls. This comparison of &lt;a href="https://www.capsolver.com/blog/web-scraping/best-proxy-services" rel="noopener noreferrer"&gt;proxy services&lt;/a&gt; can help teams understand common options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add bounded retries and useful logs
&lt;/h3&gt;

&lt;p&gt;Treat a failed solve as an expected operational event. Record the challenge type, tool result, timing, and non-sensitive error details. Use exponential backoff, limit retry counts, and escalate persistent failures to an operator instead of creating an infinite loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep dependencies and policies current
&lt;/h3&gt;

&lt;p&gt;Challenge formats, browser APIs, and MCP tooling change over time. Pin versions in production, test upgrades in a controlled environment, and periodically review the permitted scope of the automation. A primer on &lt;a href="https://www.capsolver.com/blog/The-other-captcha/what-are-captchas" rel="noopener noreferrer"&gt;what CAPTCHAs are&lt;/a&gt; can help teams understand why these controls appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Connecting CapSolver MCP to Cursor turns CAPTCHA handling into a discoverable tool rather than page-specific glue code. Install the core and MCP packages, register the stdio server, protect the API key, and choose token or browser mode based on the surrounding workflow. Developers building outside Cursor can expose the same capability through &lt;code&gt;capsolver-agent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The technical integration is only one part of a reliable system. Domain allowlists, rate limits, bounded retries, audit logs, and explicit authorization should travel with the solver from the first prototype to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does MCP add to Cursor?
&lt;/h3&gt;

&lt;p&gt;MCP gives Cursor a standard interface for discovering and calling external tools. That removes the need to write a separate prompt adapter for each CapSolver operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can this setup support reCAPTCHA v2 Enterprise?
&lt;/h3&gt;

&lt;p&gt;The source packages support multiple reCAPTCHA variants, including Enterprise configurations when the required parameters are supplied. Confirm current parameters in the official repositories before implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a browser always required?
&lt;/h3&gt;

&lt;p&gt;No. Token mode can work with the website URL and site key. Browser mode is available when the agent must detect and complete the challenge within a rendered page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where does the API key come from?
&lt;/h3&gt;

&lt;p&gt;Create a CapSolver account and retrieve the key from the user dashboard. Store it as a secret or environment variable rather than committing it to a repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can MCP expose support for other challenge types?
&lt;/h3&gt;

&lt;p&gt;The server can expose discovery tools such as &lt;code&gt;get_supported_captchas&lt;/code&gt; for the challenge types available in the installed version. Tool discovery is a core concept in the &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;. Cursor information is available from the &lt;a href="https://cursor.sh" rel="noopener noreferrer"&gt;official Cursor site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>cursor</category>
    </item>
    <item>
      <title>Solving reCAPTCHA v2 in LangChain: Token Mode and Browser Mode</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Thu, 09 Jul 2026 09:34:57 +0000</pubDate>
      <link>https://dev.to/luisgustvo/solving-recaptcha-v2-in-langchain-token-mode-and-browser-mode-2fip</link>
      <guid>https://dev.to/luisgustvo/solving-recaptcha-v2-in-langchain-token-mode-and-browser-mode-2fip</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzbw89y6z0h4vzm2o8uhh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzbw89y6z0h4vzm2o8uhh.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token mode, where you provide the page URL and site key.&lt;/li&gt;
&lt;li&gt;Browser mode, where the SDK detects the CAPTCHA on the live page and fills the response back into the DOM.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Quick Summary
&lt;/h2&gt;

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

&lt;p&gt;Use these techniques only for websites, workflows, and accounts where you have authorization to automate access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why reCAPTCHA Interrupts LangChain Workflows
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;For LangChain agents, this can happen during:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data collection from pages that require verification.&lt;/li&gt;
&lt;li&gt;Login or account-based workflows.&lt;/li&gt;
&lt;li&gt;Form submission tasks.&lt;/li&gt;
&lt;li&gt;Search, booking, checkout, or portal navigation.&lt;/li&gt;
&lt;li&gt;Multi-step browser tasks where verification appears midway through the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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 &lt;code&gt;g-recaptcha-response&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Install the required packages before building the LangChain integration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/capsolver-ai/capsolver-core.git
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"capsolver-agent[langchain] @ git+https://github.com/capsolver-ai/capsolver-agent.git"&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;langchain-openai langgraph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure your API keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-capsolver-api-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-openai-api-key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Find the reCAPTCHA Site Key
&lt;/h2&gt;

&lt;p&gt;For reCAPTCHA v2, the site key is usually stored in a &lt;code&gt;data-sitekey&lt;/code&gt; attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"g-recaptcha"&lt;/span&gt;
  &lt;span class="na"&gt;data-sitekey=&lt;/span&gt;&lt;span class="s"&gt;"6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invisible reCAPTCHA v2 often uses the same site key pattern but includes &lt;code&gt;data-size="invisible"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"g-recaptcha"&lt;/span&gt;
  &lt;span class="na"&gt;data-sitekey=&lt;/span&gt;&lt;span class="s"&gt;"6LeIxAcT..."&lt;/span&gt;
  &lt;span class="na"&gt;data-size=&lt;/span&gt;&lt;span class="s"&gt;"invisible"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The full page URL.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;data-sitekey&lt;/code&gt; value.&lt;/li&gt;
&lt;li&gt;Whether the page uses visible or invisible reCAPTCHA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your workflow already uses Playwright, you can also detect CAPTCHA details programmatically with CapSolver Core.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_capsolver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_recaptcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_capsolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;captcha_infos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_captcha_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;captcha_infos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, site_key=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aclose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Solve reCAPTCHA v2 in LangChain with Token Mode
&lt;/h2&gt;

&lt;p&gt;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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.prebuilt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_langchain_tools&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_recaptcha_with_langchain&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_langchain_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Solve the reCAPTCHA v2 for https://example.com/login. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The site key is 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return the response token.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;solve_recaptcha_with_langchain&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer to control the call directly instead of letting the agent decide when to use the tool, use the executor interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.schema&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_executor&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_recaptcha_directly&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solve_captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reCaptchaV2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Captcha solving failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Received token: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you receive the token, submit it through the field expected by the page, usually &lt;code&gt;g-recaptcha-response&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Handle Invisible reCAPTCHA v2
&lt;/h2&gt;

&lt;p&gt;From the solving API perspective, invisible reCAPTCHA v2 uses the same task type as the checkbox version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solve_captcha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reCaptchaV2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Ld_SITE_KEY_HERE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;(token) =&amp;gt; {
        const response = document.getElementById(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;g-recaptcha-response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;);
        if (response) {
            response.innerHTML = token;
        }

        if (typeof ___grecaptcha_cfg !== &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;undefined&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;) {
            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 === &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;) {
                    callback(token);
                    break;
                }
            }
        }
    }&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because callback structures can vary by implementation, inspect the page carefully during integration and test the flow in a controlled environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Use Browser Mode for Automatic Detection
&lt;/h2&gt;

&lt;p&gt;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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_capsolver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.async_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;async_playwright&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_recaptcha_on_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_capsolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;async_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_load_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;networkidle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve_on_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Solved &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Filled into page: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to solve &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;button[type=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_load_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;networkidle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Current page: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aclose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;solve_recaptcha_on_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Add reCAPTCHA Handling to a Production Agent
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Here is a simple pattern using CapSolver tools in a ReAct agent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.prebuilt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_react_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;capsolver_agent.langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_langchain_tools&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_authorized_agent_workflow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;capsolver_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_langchain_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;capsolver_tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;For my authorized test workflow, solve the reCAPTCHA v2 &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;at https://example.com/gate. The site key is &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI. Return the token.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;


&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run_authorized_agent_workflow&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more complex workflows, consider adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retry logic for transient failures.&lt;/li&gt;
&lt;li&gt;Token refresh logic when submission is delayed.&lt;/li&gt;
&lt;li&gt;Clear logging around CAPTCHA type, solve status, and response time.&lt;/li&gt;
&lt;li&gt;Human review or stop conditions for sensitive workflows.&lt;/li&gt;
&lt;li&gt;Separate handling for reCAPTCHA v2, reCAPTCHA v3, and Enterprise variants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a page uses reCAPTCHA v3, the task parameters are different. For example, v3 commonly requires a &lt;code&gt;page_action&lt;/code&gt; value. Enterprise implementations may also require additional fields. Detect the CAPTCHA type first, then pass the correct parameters to the solver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Integration Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using the wrong CAPTCHA type
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;render=SITE_KEY&lt;/code&gt; script parameter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Waiting too long before submission
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reusing site keys across pages
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignoring invisible reCAPTCHA callbacks
&lt;/h3&gt;

&lt;p&gt;Invisible challenges may require more than filling &lt;code&gt;g-recaptcha-response&lt;/code&gt;. If the page expects a callback, trigger the callback after injecting the token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treating CAPTCHA solving as a universal fallback
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can LangChain solve reCAPTCHA without opening a browser?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  When should I use Browser mode?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the same method work for invisible reCAPTCHA?
&lt;/h3&gt;

&lt;p&gt;Yes. Invisible reCAPTCHA v2 uses the same &lt;code&gt;reCaptchaV2&lt;/code&gt; task type. The solving request is similar, but the browser-side submission may need callback handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  How fast is reCAPTCHA v2 solving?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens if the token expires?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can this be used with reCAPTCHA Enterprise?
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Full guide: &lt;a href="https://www.capsolver.com/blog/langchain-recaptcha-solver-ai-agent-guide?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=langchain-recaptcha-solver-ai-agent-guide" rel="noopener noreferrer"&gt;https://www.capsolver.com/blog/langchain-recaptcha-solver-ai-agent-guide?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=langchain-recaptcha-solver-ai-agent-guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>langchain</category>
    </item>
    <item>
      <title>CAPTCHA Automation for InsurTech Claims Processing</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Wed, 08 Jul 2026 08:57:09 +0000</pubDate>
      <link>https://dev.to/luisgustvo/captcha-automation-for-insurtech-claims-processing-4aig</link>
      <guid>https://dev.to/luisgustvo/captcha-automation-for-insurtech-claims-processing-4aig</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm0tffdbuka39holayhs1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm0tffdbuka39holayhs1.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are wiring claims automation with Python, RPA, or browser automation, CAPTCHA handling is one of those production details that quickly becomes unavoidable. InsurTech workflows depend on carrier portals, state databases, medical-record systems, and fraud checks, and any one of those systems can interrupt a run with a challenge. The workflow may be digital, but CAPTCHA challenges still create manual pauses at exactly the wrong moment: during policy checks, eligibility validation, claims adjudication, and fraud review. This hands-on walkthrough explains how to design CAPTCHA automation for claims-processing pipelines, with attention to carrier portal integration, HIPAA boundaries, operational monitoring, and production-ready scaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Carrier portals and regulatory systems often introduce CAPTCHA challenges that can hold up automated claims batches for 15-45 minutes.&lt;/li&gt;
&lt;li&gt;A CapSolver API integration can remove manual CAPTCHA handling from more than 95% of carrier portal interactions when implemented correctly.&lt;/li&gt;
&lt;li&gt;Queue-based, asynchronous solving prevents CAPTCHA work from becoming a bottleneck during peak claims periods.&lt;/li&gt;
&lt;li&gt;HIPAA and state insurance rules make audit logging, PHI isolation, and access controls non-negotiable.&lt;/li&gt;
&lt;li&gt;CAPTCHA solving typically costs about $0.003-0.01 per claim, which is far below the cost of manual handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why InsurTech Claims Automation Encounters CAPTCHA Challenges
&lt;/h2&gt;

&lt;p&gt;Claims automation rarely touches just one system. A single claim may require policy verification from a carrier portal, eligibility checks against a state insurance database, medical code validation, information exchange access, and fraud indicator lookups across industry systems. Many of these environments use CAPTCHA protection to reduce abusive bulk access and keep portal traffic under control.&lt;/p&gt;

&lt;p&gt;That is reasonable from the portal operator's side, but it creates a real operations problem for claims teams. &lt;a href="https://www.naic.org/cipr-topics/topic-claims-handling.htm" rel="noopener noreferrer"&gt;&lt;strong&gt;NAIC guidelines&lt;/strong&gt;&lt;/a&gt; require claims to be acknowledged within defined windows, often 15-30 days depending on the state. When an automated workflow stops at a CAPTCHA, the delay is not just inconvenient; it can slow the queue that supports regulatory deadlines.&lt;/p&gt;

&lt;p&gt;The interruption appears in several common places: policy status verification, state eligibility lookups, medical record retrieval, subrogation research, and fraud checks. The CAPTCHA type also varies by system. Older carrier portals may still use reCAPTCHA v2 or image-based challenges, while newer InsurTech portals may use Cloudflare Turnstile or reCAPTCHA v3. A reliable claims pipeline needs a way to detect and route those differences instead of treating every portal as the same integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before building CAPTCHA automation into claims workflows, prepare the operational pieces that keep the system maintainable and compliant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://www.capsolver.com" rel="noopener noreferrer"&gt;CapSolver account&lt;/a&gt; with enough API credits for expected claims volume&lt;/li&gt;
&lt;li&gt;Python 3.9+ with &lt;code&gt;aiohttp&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt;, and the RPA or browser automation framework used by your team, such as UiPath, Automation Anywhere, or a custom stack&lt;/li&gt;
&lt;li&gt;Existing scripts or RPA flows that already interact with carrier portals&lt;/li&gt;
&lt;li&gt;HIPAA-compliant infrastructure with encryption in transit and at rest&lt;/li&gt;
&lt;li&gt;Audit logging for every automated portal interaction&lt;/li&gt;
&lt;li&gt;A working understanding of &lt;a href="https://www.capsolver.com/blog/The-other-captcha/How-to-Solve-CAPTCHA" rel="noopener noreferrer"&gt;CAPTCHA types and solving methods&lt;/a&gt; used across insurance systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any workflow may touch protected health information, confirm that the right Business Associate Agreements are in place for services that process or transmit PHI. The CAPTCHA solving layer should be designed so that PHI never leaves your environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Catalog Carrier Portal CAPTCHA Systems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to Do
&lt;/h3&gt;

&lt;p&gt;Most claims operations touch many external portals. A practical implementation starts with an inventory of those systems and the CAPTCHA behavior each one presents. Build a registry that records the portal, challenge type, trigger condition, PHI context, and compliance controls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;CARRIER_PORTALS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;carrier_a_claims&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Major Carrier A - Claims Portal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://claims.carrier-a.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Le...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login_and_every_50_requests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phi_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;baa_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state_insurance_db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;State Insurance Department Database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://insurance.state.gov/verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ImageToTextTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;every_request&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phi_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;baa_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medical_records_hie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Health Information Exchange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://hie-portal.example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AntiTurnstileTaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0x4B...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after_authentication&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phi_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;baa_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fraud_detection_db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Industry Fraud Database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://fraud-check.insurance-industry.org&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV3TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6Ld...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate_limited&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phi_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;baa_required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During discovery, use the &lt;a href="https://www.capsolver.com/blog/Extension/capsolver-captcha-solver-extension" rel="noopener noreferrer"&gt;CapSolver browser extension&lt;/a&gt; to identify the parameters required by each portal. The important fields are not only the CAPTCHA type and site key, but also whether PHI may be present on the page. That classification determines how strict the solving pipeline and audit process need to be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;InsurTech platforms often work across dozens of carrier systems, and each one changes on its own schedule. A central registry gives the automation team a single source of truth for CAPTCHA handling and reduces the risk of one-off fixes scattered across scripts. It also connects technical routing to security decisions, because portals with PHI require tighter safeguards than public regulatory lookups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Mistakes to Avoid
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not tracking portal changes&lt;/strong&gt;: Carrier portals can update CAPTCHA behavior on a regular basis. Assign ownership for checking and refreshing the registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring session-based CAPTCHAs&lt;/strong&gt;: Some systems present challenges only after login or after a threshold of activity. Automation must handle post-authentication challenges, not only login-page CAPTCHAs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2 — Build the HIPAA-Compliant CAPTCHA Solving Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to Do
&lt;/h3&gt;

&lt;p&gt;A claims-processing CAPTCHA pipeline must be built around a strict boundary: send only generic CAPTCHA parameters to the solver. Do not send patient data, claim details, page screenshots, portal content, or anything that could be PHI. The solving service should receive the website URL, challenge type, site key, page action, and related CAPTCHA fields only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="n"&gt;CAPSOLVER_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;CAPSOLVER_BASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SolveAuditEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Audit record for compliance documentation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;claim_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;portal_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;captcha_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;solve_duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;phi_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;  &lt;span class="c1"&gt;# Whether PHI was present on the page
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InsurTechCaptchaSolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA solver with HIPAA compliance controls.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audit_logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;audit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audit_logger&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_for_claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Solve CAPTCHA with compliance-aware processing.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Verify no PHI is included in the solving request
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_validate_no_phi_in_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Build task payload - only CAPTCHA parameters, never page content
&lt;/span&gt;        &lt;span class="n"&gt;task_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;task_payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;site_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;task_payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pageAction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;task_payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minScore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Submit solving task
&lt;/span&gt;        &lt;span class="n"&gt;create_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task_payload&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CAPSOLVER_BASE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/createTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;create_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errorId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_log_failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task creation failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;errorDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Poll for result with timeout
&lt;/span&gt;        &lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_poll_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;solve_duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;

        &lt;span class="c1"&gt;# Audit log
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA_SOLVE claim=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;claim_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; portal=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;captcha_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; duration=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;solve_duration&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s success=True&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_validate_no_phi_in_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Ensure CAPTCHA solving request contains no PHI.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Only URL, sitekey, and type are sent - never page content
&lt;/span&gt;        &lt;span class="c1"&gt;# This validation confirms the architecture is correct
&lt;/span&gt;        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Page content must never be sent to solver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;patient&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;portal_config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PHI detected in config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_poll_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CAPSOLVER_BASE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/getTaskResult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ready&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CAPTCHA solving exceeded timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The design principle is simple: the solver gets the CAPTCHA parameters, not the claim. Page content, patient information, policy details, and medical records stay inside your controlled infrastructure. The API returns a token or challenge solution that your automation can apply in the browser session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;HIPAA penalties can range from $100 to $50,000 per incident, with annual maximums that can reach $1.5 million per violation category. In a claims-processing environment, the safest CAPTCHA architecture is one that prevents PHI from being transmitted in the first place. The example above enforces that separation by validating the request payload and logging only compliance-safe operational details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Mistakes to Avoid
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sending page screenshots for solving&lt;/strong&gt;: Full-page screenshots may expose patient or claim details. Use ImageToTextTask only for isolated CAPTCHA images, never for entire portal pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging PHI in CAPTCHA audit trails&lt;/strong&gt;: Logs should capture claim IDs, portal identifiers, challenge type, duration, and status. They should not include patient names, policy details, or medical content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3 — Integrate with Claims Processing Workflows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to Do
&lt;/h3&gt;

&lt;p&gt;After the solving layer is isolated, connect it to the claims workflow itself. The key is to make CAPTCHA handling an internal capability of the pipeline rather than a manual exception path. The following pattern shows policy verification, eligibility checking, medical-code validation, and fraud screening with controlled concurrency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClaimsProcessor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Automated claims processing with CAPTCHA handling.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InsurTechCaptchaSolver&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Process a single insurance claim across multiple portals.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 1: Verify policy status
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;policy_verification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_verify_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 2: Check eligibility
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eligibility&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_check_eligibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 3: Validate medical codes
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_validation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_validate_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 4: Fraud screening
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fraud_check&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_screen_fraud&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Determine claim decision
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;decision&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_adjudicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_verify_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Verify policy on carrier portal with CAPTCHA handling.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;portal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CARRIER_PORTALS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;carrier_a_claims&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Attempt portal access
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_access_portal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;portal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;policy_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_is_captcha_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Solve CAPTCHA
&lt;/span&gt;            &lt;span class="n"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;solve_for_claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;portal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claim_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Retry with token
&lt;/span&gt;            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_access_portal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;portal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;policy_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;captcha_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_parse_policy_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Process a batch of claims with controlled concurrency.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;semaphore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_with_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claim_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claim_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;process_with_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For RPA-based teams, the &lt;a href="https://www.capsolver.com/blog/automation/captcha-handling-for-fintech-compliance-automation" rel="noopener noreferrer"&gt;CapSolver automation integration&lt;/a&gt; provides patterns that can be adapted to UiPath, Automation Anywhere, and related insurance operations platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;A claims processor may need to access 3-5 external systems for a single claim. At scale, that means hundreds or thousands of portal interactions per day. If humans must resolve each CAPTCHA manually, they can spend 20-30% of their time on access friction rather than on exceptions, judgment calls, and complex claims that actually need human review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Handle Peak Volume and Disaster Recovery
&lt;/h2&gt;

&lt;p&gt;Claims work is uneven by nature. Mondays collect weekend volume, month-end periods compress deadline-driven submissions, and catastrophe events can produce sudden spikes in claims. CAPTCHA automation has to scale with those patterns instead of assuming a flat daily load.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Claims Volume&lt;/th&gt;
&lt;th&gt;CAPTCHA Encounters&lt;/th&gt;
&lt;th&gt;Architecture Need&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal daily&lt;/td&gt;
&lt;td&gt;200-500 claims&lt;/td&gt;
&lt;td&gt;50-150 CAPTCHAs&lt;/td&gt;
&lt;td&gt;Single worker instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monday surge&lt;/td&gt;
&lt;td&gt;800-1,200 claims&lt;/td&gt;
&lt;td&gt;200-400 CAPTCHAs&lt;/td&gt;
&lt;td&gt;Auto-scaling workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month-end peak&lt;/td&gt;
&lt;td&gt;1,500-2,500 claims&lt;/td&gt;
&lt;td&gt;400-750 CAPTCHAs&lt;/td&gt;
&lt;td&gt;Queue-based with 3-5 workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catastrophe event&lt;/td&gt;
&lt;td&gt;5,000-20,000 claims&lt;/td&gt;
&lt;td&gt;1,500-6,000 CAPTCHAs&lt;/td&gt;
&lt;td&gt;Full horizontal scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A queue-based architecture helps decouple claim submission from portal processing. Claims can enter the queue immediately, while workers handle portal access, CAPTCHA solving, retries, and result collection in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ScalableClaimsQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Queue-based claims processing for peak volume handling.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InsurTechCaptchaSolver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solver&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max_workers&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;worker_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Process claims from queue with CAPTCHA handling.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClaimsProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;solver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;claim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Shutdown signal
&lt;/span&gt;                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claim_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claim_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
            &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;task_done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Submit claims batch and process with worker pool.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Start workers
&lt;/span&gt;        &lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

        &lt;span class="c1"&gt;# Submit claims to queue
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;claim&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Wait for completion
&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Shutdown workers
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/captcha-solver-response-api" rel="noopener noreferrer"&gt;CapSolver API&lt;/a&gt; supports thousands of concurrent solving tasks, which makes this pattern suitable for catastrophe-event scaling without pre-provisioning all solving capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Implement Monitoring and Regulatory Reporting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to Do
&lt;/h3&gt;

&lt;p&gt;Insurance automation needs monitoring that satisfies both operations and compliance teams. Track normal engineering metrics, such as queue depth and solve duration, but also capture the control evidence needed for insurance department audits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClaimsMonitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Monitoring for InsurTech CAPTCHA automation compliance.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_regulatory_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate report for insurance department audits.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reporting_period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;period&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_claims_processed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claims_processed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;automated_portal_accesses&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;portal_accesses&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_encounters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;captcha_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;average_processing_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_processing_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compliance_controls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phi_protection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No PHI transmitted to external services&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit_trail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complete logging of all portal interactions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data_retention&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Portal responses retained per policy schedule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_controls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Role-based access to automation systems&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sla_compliance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claims_acknowledged_within_deadline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sla_met_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;average_acknowledgment_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_ack_time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key metrics for InsurTech CAPTCHA automation include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claims processing SLA compliance&lt;/strong&gt;: Percentage of claims acknowledged within regulatory deadlines, with a target above 99%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CAPTCHA solve success rate&lt;/strong&gt;: Percentage of challenges solved on the first attempt, with a target above 95%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average claim processing time&lt;/strong&gt;: End-to-end time from submission to initial decision, with a target under 5 minutes for standard claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost per claim&lt;/strong&gt;: CAPTCHA solving cost divided by processed claims, with a target below $0.01.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Carrier Portal Compatibility Considerations
&lt;/h2&gt;

&lt;p&gt;Carrier portals are not technologically uniform. Legacy systems may rely on image-based CAPTCHAs, while newer systems may use Cloudflare Turnstile or reCAPTCHA v3. Treating all portals as identical will create fragile automation. The registry from Step 1 should drive type-specific routing.&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-reCAPTCHA-v3" rel="noopener noreferrer"&gt;reCAPTCHA v3 challenges&lt;/a&gt;, specify the appropriate &lt;code&gt;pageAction&lt;/code&gt; and request a minimum score of 0.7. Carrier portals often use thresholds around 0.5-0.7, so setting the requested score to 0.7 improves consistency.&lt;/p&gt;

&lt;p&gt;For legacy portals with &lt;a href="https://www.capsolver.com/blog/The-other-captcha/How-to-solve-image-captchas" rel="noopener noreferrer"&gt;image-based CAPTCHAs&lt;/a&gt;, ImageToTextTask can handle distorted text challenges with 90-95% accuracy. These older patterns are still common in state insurance department systems and smaller carrier portals.&lt;/p&gt;

&lt;p&gt;For portals protected by &lt;a href="https://www.capsolver.com/blog/Cloudflare/bypass-cloudflare-turnstile" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;, Turnstile-solving workflows can provide tokens that remain valid for a session, reducing the number of solves needed during a claims batch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CAPTCHA automation for InsurTech claims processing is not just a convenience feature. It requires a complete operating model: catalog carrier portal behavior, isolate the CAPTCHA solving request from PHI, integrate solving into claims workflows, scale through queues and workers, and monitor both reliability and regulatory evidence. &lt;a href="https://www.capsolver.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=captcha-automation-for-insurtech-claims-processing" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; provides solving infrastructure for varied CAPTCHA types while preserving the security boundaries required in healthcare-adjacent insurance workflows.&lt;/p&gt;

&lt;p&gt;Start with the highest-volume carrier portals, validate the integration on a small claims batch, and then expand the registry portal by portal. A queue-based architecture lets the system absorb catastrophe events, Monday spikes, and month-end pressure without turning CAPTCHA handling into a manual bottleneck. Monitor SLA compliance so automation can be shown to improve, not weaken, regulatory performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does CAPTCHA solving comply with HIPAA requirements?
&lt;/h3&gt;

&lt;p&gt;CAPTCHA solving through CapSolver can be HIPAA-compatible when the pipeline sends only generic CAPTCHA parameters, such as URL, site key, and challenge type. No patient data, claim details, page content, or PHI should be transmitted to the solving service. The API should receive and return CAPTCHA tokens only.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does CAPTCHA automation cost per insurance claim?
&lt;/h3&gt;

&lt;p&gt;For a typical claim that requires access to 3-4 carrier portals with a 40% CAPTCHA encounter rate, CAPTCHA solving costs usually average $0.003-0.01 per claim. At 500 claims per day, that works out to about $45-150 per month, which is much lower than the $2-5 per claim cost of manual CAPTCHA handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can CAPTCHA automation handle carrier portal login CAPTCHAs?
&lt;/h3&gt;

&lt;p&gt;Yes. Many portals show CAPTCHA challenges during login. The automation should detect the challenge, submit the solving task through the API, inject the returned token, and continue authentication. After a successful login, session cookies often prevent additional challenges for 30-60 minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens during a catastrophe event when claims volume spikes 10x?
&lt;/h3&gt;

&lt;p&gt;The queue-based architecture handles surge volume by adding more worker instances. CapSolver supports thousands of concurrent solving tasks, so CAPTCHA capacity can scale with the worker pool. Configure auto-scaling rules around queue depth and make sure the API credit balance can cover peak scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I handle carrier portals that change their CAPTCHA systems?
&lt;/h3&gt;

&lt;p&gt;Build CAPTCHA type detection into the automation instead of hardcoding assumptions per portal. When detection identifies a new challenge type, the system should select the correct solving method and alert the team if success rates fall below expected thresholds, such as 90% for a given portal.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Enterprise Public Records Infrastructure: A Strategic Imperative for Modern Businesses</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Tue, 07 Jul 2026 08:54:28 +0000</pubDate>
      <link>https://dev.to/luisgustvo/enterprise-public-records-infrastructure-a-strategic-imperative-for-modern-businesses-4mc1</link>
      <guid>https://dev.to/luisgustvo/enterprise-public-records-infrastructure-a-strategic-imperative-for-modern-businesses-4mc1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgt7who29t3wy99pn4xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgt7who29t3wy99pn4xp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
In an increasingly data-driven world, access to accurate and timely information is a critical differentiator for enterprises. Beyond proprietary datasets and market intelligence reports, &lt;strong&gt;public records&lt;/strong&gt; represent a vast, often untapped, reservoir of valuable insights. An &lt;strong&gt;Enterprise Public Records Infrastructure (EPRI)&lt;/strong&gt; is a sophisticated framework designed to systematically collect, process, analyze, and leverage data derived from government and public sources at scale. This infrastructure empowers organizations to enhance due diligence, mitigate risks, identify market opportunities, and ensure regulatory compliance.&lt;/p&gt;

&lt;p&gt;This article delves into the essential components, technical architecture, inherent challenges, and profound strategic value of establishing a robust EPRI. For businesses operating in complex regulatory environments or those requiring deep insights into market dynamics, an EPRI is not merely an advantage but a strategic imperative.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Public Records?
&lt;/h2&gt;

&lt;p&gt;Public records encompass a wide array of documents and data generated or maintained by governmental entities and made accessible to the public, often under freedom of information laws. These records provide transparent insights into legal, financial, and operational activities across various sectors. For enterprises, public records can include, but are not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Business Records&lt;/strong&gt;: Registrations, corporate filings, ownership structures, and professional licenses.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Legal and Court Records&lt;/strong&gt;: Litigation histories, bankruptcy filings, liens, judgments, and criminal records.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Financial Records&lt;/strong&gt;: Securities and Exchange Commission (SEC) filings, tax assessments, government grants, and loan information.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Real Estate Records&lt;/strong&gt;: Property deeds, ownership transfers, zoning permits, and mortgage details.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Procurement Records&lt;/strong&gt;: Government contracts, requests for proposals (RFPs), and vendor lists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leveraging these diverse data sources effectively requires a specialized infrastructure capable of handling their volume, variety, and often unstructured nature.&lt;/p&gt;

&lt;p&gt;centralized repository for actionable intelligence.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Graph Databases&lt;/strong&gt;: Increasingly used for mapping complex relationships between entities, such as corporate hierarchies, ownership networks, or litigation connections. Graph databases excel at uncovering non-obvious links within public records data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Metadata Management&lt;/strong&gt;: Robust metadata management systems are crucial for tracking data lineage, provenance, quality, and access controls. This ensures transparency, auditability, and trust in the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Analysis and Insights Layer
&lt;/h3&gt;

&lt;p&gt;The ultimate goal of an EPRI is to generate actionable insights from the collected data. This layer employs various analytical techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Risk Scoring&lt;/strong&gt;: Developing models to assess various risks, such as litigation risk for potential partners, creditworthiness of entities, or compliance risks associated with specific activities.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Competitive Intelligence&lt;/strong&gt;: Tracking government contracts awarded to competitors, analyzing patent filings to understand innovation trends, or monitoring regulatory changes that could impact market positions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Regulatory Compliance Monitoring&lt;/strong&gt;: Automatically identifying potential compliance breaches by cross-referencing internal data with public records, such as sanctions lists or environmental violation databases.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Predictive Analytics&lt;/strong&gt;: Utilizing machine learning models to forecast trends, identify emerging risks, or predict outcomes based on historical public records data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Components of an Enterprise Public Records Infrastructure
&lt;/h2&gt;

&lt;p&gt;Building a robust EPRI involves integrating several key technical components, each playing a crucial role in the data lifecycle from collection to insight generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Data Ingestion Layer
&lt;/h3&gt;

&lt;p&gt;The foundation of any EPRI is its data ingestion layer, responsible for gathering information from a multitude of public sources. This often involves a hybrid approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Automated Scrapers&lt;/strong&gt;: Specialized tools designed to extract data from government portals, such as the SEC EDGAR database for corporate filings, PACER for federal court records, and various state and local land registries. These scrapers must be resilient to website changes and anti-scraping mechanisms.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;API Connectors&lt;/strong&gt;: Integration with commercial public record providers and government APIs that offer structured access to their datasets. This provides a more stable and often higher-quality data stream compared to web scraping.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Diverse Format Handling&lt;/strong&gt;: The ingestion layer must be capable of processing a wide array of document formats, including structured data (e.g., XML, CSV), semi-structured data (e.g., HTML tables), and unstructured data (e.g., PDFs, scanned images, legacy mainframe outputs).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Data Transformation and Normalization
&lt;/h3&gt;

&lt;p&gt;Raw public records data is often inconsistent, incomplete, and in varied formats. The transformation and normalization layer addresses these challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Optical Character Recognition (OCR)&lt;/strong&gt;: For scanned documents and image-based PDFs, OCR technology is essential to convert images of text into machine-readable text, making the content searchable and analyzable.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Natural Language Processing (NLP)&lt;/strong&gt;: Advanced NLP techniques are employed to extract key entities (e.g., names of individuals, organizations, addresses, dates, financial figures) from unstructured text. This allows for the categorization and structuring of qualitative data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data Standardization&lt;/strong&gt;: Critical for harmonizing disparate data points. This includes standardizing address formats, resolving entity disambiguation (e.g., ensuring different spellings or abbreviations of a company name refer to the same entity), and normalizing date formats across various sources and jurisdictions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Data Storage and Management
&lt;/h3&gt;

&lt;p&gt;Effective storage and management are paramount for ensuring data accessibility, integrity, and security within an EPRI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Scalable Data Lakes&lt;/strong&gt;: Used for storing raw, untransformed public records data. Data lakes provide a flexible and cost-effective solution for housing large volumes of diverse data, preserving its original format for future analysis.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data Warehouses&lt;/strong&gt;: For structured and transformed data, data warehouses offer optimized storage for analytical queries and reporting, serving as a centralized repository for actionable intelligence.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Graph Databases&lt;/strong&gt;: Increasingly utilized for mapping complex relationships between entities, such as corporate hierarchies, ownership networks, or litigation connections. Graph databases excel at uncovering non-obvious links within public records data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Metadata Management&lt;/strong&gt;: Robust metadata management systems are crucial for tracking data lineage, provenance, quality, and access controls. This ensures transparency, auditability, and trust in the data, which is vital for compliance and regulatory purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Analysis and Insights Layer
&lt;/h3&gt;

&lt;p&gt;The ultimate goal of an EPRI is to generate actionable insights from the collected data. This layer employs various analytical techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Risk Scoring&lt;/strong&gt;: Developing sophisticated models to assess various risks, such as litigation risk for potential partners, creditworthiness of entities, or compliance risks associated with specific activities.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Competitive Intelligence&lt;/strong&gt;: Tracking government contracts awarded to competitors, analyzing patent filings to understand innovation trends, or monitoring regulatory changes that could impact market positions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Regulatory Compliance Monitoring&lt;/strong&gt;: Automatically identifying potential compliance breaches by cross-referencing internal data with public records, such as sanctions lists or environmental violation databases.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Predictive Analytics&lt;/strong&gt;: Utilizing machine learning models to forecast trends, identify emerging risks, or predict outcomes based on historical public records data, thereby enabling proactive strategic decision-making.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Challenges in Building and Maintaining an EPRI
&lt;/h2&gt;

&lt;p&gt;While the benefits of an EPRI are substantial, its implementation is not without significant technical hurdles. These challenges often require specialized solutions and continuous effort:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Anti-Scraping Mechanisms&lt;/strong&gt;: Many government websites and public databases employ sophisticated anti-scraping technologies, including CAPTCHAs, rate limiting, IP blocking, and dynamic content rendering. Overcoming these requires advanced scraping techniques, proxy rotations, and potentially CAPTCHA-solving services.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data Quality and Consistency&lt;/strong&gt;: Public records are notorious for their inconsistency. Data can be incomplete, contain typos, use varying formats across different jurisdictions, or be outdated. Ensuring high data quality requires robust validation, cleansing, and reconciliation processes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Scalability&lt;/strong&gt;: Processing and storing millions, if not billions, of documents and data points daily across numerous jurisdictions demands a highly scalable infrastructure. This involves distributed computing, efficient storage solutions, and optimized data pipelines.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Privacy and Ethics&lt;/strong&gt;: Public records often contain Personally Identifiable Information (PII). A critical challenge is to redact sensitive PII while maintaining the utility of the data for legitimate business purposes. Adhering to evolving data privacy regulations (e.g., GDPR, CCPA) is paramount and requires careful data governance and anonymization strategies.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Evolving Data Sources&lt;/strong&gt;: The structure and accessibility of public records sources can change frequently. Websites are redesigned, APIs are updated, and new regulations are introduced. An EPRI must be agile enough to adapt to these continuous changes without significant disruption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Strategic Value of an Enterprise Public Records Infrastructure
&lt;/h2&gt;

&lt;p&gt;Beyond merely overcoming technical challenges, a well-implemented EPRI delivers profound strategic advantages that can redefine an enterprise's competitive posture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Enhanced Risk Mitigation&lt;/strong&gt;: By providing comprehensive and up-to-date information on entities, an EPRI significantly strengthens due diligence processes for mergers and acquisitions, vendor onboarding, and client vetting. It helps identify potential legal, financial, or reputational risks proactively.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unlocking Market Expansion Opportunities&lt;/strong&gt;: Analysis of public records, such as business registrations, permits, and demographic data, can reveal untapped markets, emerging industry trends, and optimal locations for expansion.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Driving Operational Efficiency&lt;/strong&gt;: Automating the collection and processing of public records data streamlines traditionally manual and time-consuming tasks like background checks, Know Your Customer (KYC) processes, and compliance audits. This frees up human resources for higher-value analytical work.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Gaining Competitive Intelligence&lt;/strong&gt;: Monitoring competitor activities through public filings (e.g., patent applications, government contracts, litigation) provides invaluable insights into their strategies, R&amp;amp;D efforts, and market positioning.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ensuring Regulatory Compliance&lt;/strong&gt;: For industries heavily regulated, an EPRI provides the necessary tools to continuously monitor adherence to various laws and regulations, minimizing the risk of penalties and legal challenges.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  EPRI vs. Traditional Data Collection: A Comparison
&lt;/h2&gt;

&lt;p&gt;To further illustrate the advantages, consider this comparison between a modern EPRI and traditional, manual data collection methods:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Traditional Public Records Collection&lt;/th&gt;
&lt;th&gt;Enterprise Public Records Infrastructure (EPRI)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Volume&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited, often manual selection&lt;/td&gt;
&lt;td&gt;Massive, comprehensive, and automated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Velocity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow, periodic updates&lt;/td&gt;
&lt;td&gt;Real-time or near real-time ingestion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Variety&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Primarily structured, limited formats&lt;/td&gt;
&lt;td&gt;Highly diverse (structured, semi-structured, unstructured)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Accuracy &amp;amp; Consistency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prone to human error, inconsistencies&lt;/td&gt;
&lt;td&gt;High accuracy through automation, normalization, and validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited by human resources&lt;/td&gt;
&lt;td&gt;Highly scalable, cloud-native architectures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insight Generation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reactive, labor-intensive analysis&lt;/td&gt;
&lt;td&gt;Proactive, AI-driven, predictive analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High manual labor costs&lt;/td&gt;
&lt;td&gt;Lower operational costs at scale, higher ROI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compliance &amp;amp; Governance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual tracking, higher risk of oversight&lt;/td&gt;
&lt;td&gt;Automated monitoring, robust governance frameworks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion: The Future is Data-Driven
&lt;/h2&gt;

&lt;p&gt;Building an &lt;strong&gt;Enterprise Public Records Infrastructure&lt;/strong&gt; is a complex but ultimately rewarding endeavor. It represents a significant investment in technology, processes, and expertise, but the strategic returns—in terms of risk mitigation, market insight, operational efficiency, and competitive advantage—are substantial. As the volume and accessibility of public data continue to grow, organizations that master the art of leveraging this information through a sophisticated EPRI will be best positioned to navigate an increasingly intricate business landscape. For any enterprise aiming for proactive decision-making and sustainable growth, a robust EPRI is no longer a luxury but a fundamental pillar of modern business intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] LexisNexis. (n.d.). &lt;em&gt;Public Records: What You Need to Know&lt;/em&gt;. Retrieved from &lt;a href="https://www.lexisnexis.com/en-us/professional/research/glossary/public-records.page" rel="noopener noreferrer"&gt;https://www.lexisnexis.com/en-us/professional/research/glossary/public-records.page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] Thomson Reuters. (2025, July 29). &lt;em&gt;Strategies to leverage enhanced public record data&lt;/em&gt;. Retrieved from &lt;a href="https://legal.thomsonreuters.com/blog/strategies-to-leverage-enhanced-public-record-data/" rel="noopener noreferrer"&gt;https://legal.thomsonreuters.com/blog/strategies-to-leverage-enhanced-public-record-data/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] Tendem.ai. (2026, May 23). &lt;em&gt;Scraping Government and Public Records for Business Intelligence&lt;/em&gt;. Retrieved from &lt;a href="https://tendem.ai/blog/scraping-government-public-records" rel="noopener noreferrer"&gt;https://tendem.ai/blog/scraping-government-public-records&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] Harvard Library. (2025, August 15). &lt;em&gt;Factual Research and Public Records: Business Records&lt;/em&gt;. Retrieved from &lt;a href="https://guides.library.harvard.edu/c.php?g=845958&amp;amp;p=6047910" rel="noopener noreferrer"&gt;https://guides.library.harvard.edu/c.php?g=845958&amp;amp;p=6047910&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] ACLU New Jersey. (2023, March 13). &lt;em&gt;What is the Open Public Records Act and How Does It Impact New Jersey?&lt;/em&gt;. Retrieved from &lt;a href="https://www.aclu-nj.org/news/what-open-public-records-act-and-how-does-it-impact-new-jersey/" rel="noopener noreferrer"&gt;https://www.aclu-nj.org/news/what-open-public-records-act-and-how-does-it-impact-new-jersey/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] DataEntryOutsourced. (2025, December 19). &lt;em&gt;Key Challenges in Large-Scale Data Extraction and How to Solve Them&lt;/em&gt;. Retrieved from &lt;a href="https://www.dataentryoutsourced.com/blog/key-challenges-in-large-scale-data-extraction-and-how-to-solve-them/" rel="noopener noreferrer"&gt;https://www.dataentryoutsourced.com/blog/key-challenges-in-large-scale-data-extraction-and-how-to-solve-them/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] RecordPoint. (n.d.). &lt;em&gt;The Records Manager's Guide to Data Privacy&lt;/em&gt;. Retrieved from &lt;a href="https://www.recordpoint.com/records-managers-guide-to-data-privacy" rel="noopener noreferrer"&gt;https://www.recordpoint.com/records-managers-guide-to-data-privacy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] IBM. (n.d.). &lt;em&gt;Best Practices in Records Management and Regulatory Compliance&lt;/em&gt;. Retrieved from &lt;a href="https://public.dhe.ibm.com/software/emea/dk/frontlines/Best_practice_record_man.pdf" rel="noopener noreferrer"&gt;https://public.dhe.ibm.com/software/emea/dk/frontlines/Best_practice_record_man.pdf&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Scalable Market Intelligence Infrastructure: A Complete Guide</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Fri, 03 Jul 2026 08:13:47 +0000</pubDate>
      <link>https://dev.to/luisgustvo/scalable-market-intelligence-infrastructure-a-complete-guide-2mb5</link>
      <guid>https://dev.to/luisgustvo/scalable-market-intelligence-infrastructure-a-complete-guide-2mb5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy196i4keso1cprg1gebz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy196i4keso1cprg1gebz.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;Dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Data Hub:&lt;/strong&gt; A scalable market intelligence infrastructure unifies internal and external data sources into a single source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Collection:&lt;/strong&gt; Leveraging automation and AI reduces manual effort and ensures real-time data ingestion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Architecture:&lt;/strong&gt; Building with modular components allows for flexible scaling as business needs evolve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actionable Insights:&lt;/strong&gt; The ultimate goal is to translate raw data into strategic insights that drive competitive advantage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance and Security:&lt;/strong&gt; Robust governance frameworks are essential to protect data integrity and comply with regulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's hyper-competitive business landscape, relying on fragmented data and manual research is no longer sufficient. To stay ahead, organizations must build a &lt;strong&gt;Scalable Market Intelligence Infrastructure&lt;/strong&gt; that can continuously monitor competitors, track industry trends, and uncover new opportunities. This guide is designed for data engineers, marketing leaders, and strategic decision-makers who want to transform their market intelligence from a reactive process into a proactive, automated engine. By implementing a robust infrastructure, you can ensure that your team always has access to accurate, real-time insights, enabling faster and more confident strategic decisions. We will explore the technical architecture, operational strategies, and the critical tools required to maintain a smooth flow of information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Evolution of Market Intelligence Systems
&lt;/h2&gt;

&lt;p&gt;Market intelligence has moved far beyond simple news alerts and manual competitor tracking. Historically, teams would spend hours manually scouring websites, downloading PDFs, and compiling spreadsheets that were outdated the moment they were shared. A modern Scalable Market Intelligence Infrastructure replaces these labor-intensive tasks with automated pipelines that ingest data at scale. This evolution is driven by the need for speed and precision. Organizations that can process market signals faster than their rivals are better positioned to pivot their strategies, optimize pricing, and capture emerging customer segments.&lt;/p&gt;

&lt;p&gt;The shift toward a data-driven approach requires a fundamental change in how data is perceived. It is no longer just a supporting asset but the core driver of strategic agility. By treating market intelligence as a continuous stream rather than a series of snapshots, businesses can achieve a level of awareness that was previously impossible. This transition involves moving from siloed data pockets to a unified ecosystem where every department—from product development to sales—can utilize the same high-quality intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components of a Scalable Infrastructure
&lt;/h2&gt;

&lt;p&gt;Building a robust infrastructure requires careful planning and the integration of several key technical components. Each layer of the stack must be designed for reliability and growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Automated Data Ingestion Layer
&lt;/h3&gt;

&lt;p&gt;The foundation of any Scalable Market Intelligence Infrastructure is the ingestion layer. This component is responsible for gathering data from a vast array of sources. These sources include structured data from APIs, semi-structured data from social media feeds, and unstructured data from competitor blogs or news articles. Automation at this stage is non-negotiable. Manual collection cannot keep up with the volume and velocity of modern market data.&lt;/p&gt;

&lt;p&gt;Advanced scraping tools and API connectors are used to ensure that the data pipeline remains active 24/7. This layer must also handle the complexities of data diversity. For instance, a system might need to ingest financial reports from regulatory bodies while simultaneously monitoring sentiment on Twitter. The ability to harmonize these disparate data types into a standardized format is what separates a basic tool from a true enterprise-grade infrastructure. For a deeper understanding of the technical tools involved, you can explore how &lt;a href="https://www.capsolver.com/blog/web-scraping/webscraping-tools-explained" rel="noopener noreferrer"&gt;webscraping tools explained&lt;/a&gt; can clarify the selection process for your stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Centralized Data Storage and Management
&lt;/h3&gt;

&lt;p&gt;Once the data is ingested, it must be stored in a way that makes it accessible and searchable. A centralized data warehouse or data lake serves as the heart of the Scalable Market Intelligence Infrastructure. This centralized approach ensures that there is a single source of truth for the entire organization. It eliminates the problem of "data silos," where different teams have conflicting information.&lt;/p&gt;

&lt;p&gt;Data governance is also a critical aspect of this layer. Organizations must ensure that the data they collect is handled ethically and in compliance with privacy regulations like GDPR or CCPA. Implementing robust metadata management and data lineage tracking allows teams to understand the origin and reliability of every piece of intelligence. This transparency is essential for building trust in the insights generated by the system. According to &lt;a href="https://www.grandviewresearch.com/industry-analysis/ai-infrastructure-market-report" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Grand View Research&lt;/strong&gt;&lt;/a&gt;, the AI infrastructure market is projected to grow significantly, highlighting the importance of robust data foundations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Processing and Analytics Engine
&lt;/h3&gt;

&lt;p&gt;Raw data is essentially useless without processing. The analytics engine of a Scalable Market Intelligence Infrastructure uses machine learning and natural language processing (NLP) to extract meaning from the noise. For example, NLP can be used to perform sentiment analysis on customer reviews or to automatically categorize competitor product updates.&lt;/p&gt;

&lt;p&gt;This layer is where the "intelligence" in market intelligence truly comes to life. By applying predictive models, organizations can move from understanding what happened to anticipating what might happen next. Predictive analytics can forecast market trends, identify potential competitive threats, and even suggest the best time to launch a new product. This proactive capability is a primary benefit of investing in a scalable infrastructure. Industry experts at &lt;a href="https://www.thoughtspot.com/data-trends/best-practices/data-infrastructure-for-modern-analytics" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;ThoughtSpot&lt;/strong&gt;&lt;/a&gt; emphasize that modern data infrastructure must be built for speed and scale to support these advanced analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Summary: Traditional vs. Scalable Infrastructure
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Traditional Market Intelligence&lt;/th&gt;
&lt;th&gt;Scalable Market Intelligence Infrastructure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Collection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual, periodic updates&lt;/td&gt;
&lt;td&gt;Automated, real-time ingestion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Siloed spreadsheets and databases&lt;/td&gt;
&lt;td&gt;Centralized data warehouse/lake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Human-driven, reactive&lt;/td&gt;
&lt;td&gt;AI-powered, predictive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited by human capacity&lt;/td&gt;
&lt;td&gt;Highly scalable, modular architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Decision Making&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow, often based on outdated data&lt;/td&gt;
&lt;td&gt;Fast, data-driven, and proactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Integrity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prone to human error&lt;/td&gt;
&lt;td&gt;High accuracy through automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Overcoming Technical Barriers with CapSolver
&lt;/h2&gt;

&lt;p&gt;A major challenge in maintaining a Scalable Market Intelligence Infrastructure is the increasing complexity of automated detection protections on the web. Many high-value data sources use sophisticated CAPTCHA systems to block automated access. These barriers can stall your data pipelines and lead to significant gaps in your intelligence. Understanding &lt;a href="https://www.capsolver.com/blog/The-other-captcha/what-are-captchas" rel="noopener noreferrer"&gt;what are captchas&lt;/a&gt; and how they function is the first step in addressing these disruptions.&lt;/p&gt;

&lt;p&gt;To maintain a truly scalable and reliable system, you must integrate solutions that can handle these challenges automatically. We highly recommend using &lt;a href="https://www.capsolver.com" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; to manage these obstacles. CapSolver provides a robust API that can solve various types of CAPTCHAs, including reCAPTCHA, hCaptcha, and Cloudflare challenges, with high speed and accuracy.&lt;/p&gt;

&lt;p&gt;By incorporating CapSolver into your automation scripts, you ensure that your Scalable Market Intelligence Infrastructure remains uninterrupted. This is particularly important when scraping e-commerce sites or financial portals where data changes rapidly. For developers looking to implement this, the &lt;a href="https://docs.capsolver.com/" rel="noopener noreferrer"&gt;CapSolver documentation&lt;/a&gt; provides clear, code-based examples. For instance, if you encounter a CAPTCHA while scraping, you can simply call the CapSolver API to get the solution and continue your data extraction process. This level of reliability is essential for any enterprise-grade market intelligence system. You can also learn &lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-in-web-scraping-using-python" rel="noopener noreferrer"&gt;how to solve recaptcha in web scraping using python&lt;/a&gt; for more practical implementation tips.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example of using CapSolver to solve a CAPTCHA in an automated script
# Based on official CapSolver documentation
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_captcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;site_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;site_key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;site_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;site_key&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/createTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Poll for the result
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/getTaskResult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ready&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integrating such tools ensures that your infrastructure is resilient against the evolving landscape of web security, allowing your team to focus on analysis rather than troubleshooting connection issues. Using the &lt;a href="https://www.capsolver.com/blog/web-scraping/top-5-web-scraping-services" rel="noopener noreferrer"&gt;top 5 web scraping services&lt;/a&gt; in conjunction with these solutions can further bolster your system's performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operational Strategies for Success
&lt;/h2&gt;

&lt;p&gt;Building the technology is only half the battle. To truly utilize a Scalable Market Intelligence Infrastructure, you must also implement the right operational strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Defining Key Intelligence Questions (KIQs)
&lt;/h3&gt;

&lt;p&gt;A common mistake is collecting data for the sake of collection. A Scalable Market Intelligence Infrastructure should be guided by specific Key Intelligence Questions (KIQs). These are the strategic questions that your business needs to answer to succeed. For example, "What is our main competitor's pricing strategy for the next quarter?" or "Which emerging technologies are most likely to disrupt our core product line?" As &lt;a href="https://www.contify.com/resources/blog/market-and-competitive-intelligence-program-guide/" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Contify&lt;/strong&gt;&lt;/a&gt; suggests, defining these questions is the first step toward a winning intelligence program.&lt;/p&gt;

&lt;p&gt;By focusing your infrastructure on answering these questions, you ensure that the insights generated are actionable and relevant. KIQs should be reviewed and updated regularly to reflect changes in the business environment. This alignment between technology and strategy is what drives ROI from your market intelligence investments.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Establishing a Data-Driven Culture
&lt;/h3&gt;

&lt;p&gt;For a Scalable Market Intelligence Infrastructure to be effective, it must be embraced by the entire organization. This requires building a culture where data is the primary driver of decisions. Training team members on how to interpret and use the insights generated by the system is crucial. Organizations like &lt;a href="https://aligntoday.com/blog/building-a-scalable-infrastructure-to-support-rapid-growth/" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Align Today&lt;/strong&gt;&lt;/a&gt; emphasize that a scalable infrastructure must support rapid growth through standardized processes.&lt;/p&gt;

&lt;p&gt;Furthermore, internal intelligence sources should not be overlooked. Insights from sales calls, customer support tickets, and CRM data are often just as valuable as external market signals. A truly scalable infrastructure integrates these internal data points to provide a 360-degree view of the market landscape. This holistic approach ensures that your strategy is grounded in both external realities and internal performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Continuous Monitoring and Optimization
&lt;/h3&gt;

&lt;p&gt;A Scalable Market Intelligence Infrastructure is not a "set it and forget it" system. It requires ongoing monitoring to ensure that data pipelines are functioning correctly and that the insights generated remain accurate. Regular audits of data sources and analysis models are necessary to maintain the integrity of the system. Tools listed in the &lt;a href="https://improvado.io/blog/marketing-intelligence-tools" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Improvado&lt;/strong&gt;&lt;/a&gt; guide can help automate this monitoring and provide deeper visibility.&lt;/p&gt;

&lt;p&gt;As your business grows, your infrastructure must also evolve. This might involve adding new data sources, upgrading your analytics engine, or integrating new tools. A modular architecture allows you to make these updates without disrupting the entire system. This flexibility is the "scalable" part of Scalable Market Intelligence Infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategic Value and Competitive Advantage
&lt;/h2&gt;

&lt;p&gt;The ultimate goal of a Scalable Market Intelligence Infrastructure is to provide a sustainable competitive advantage. In a world where information is abundant but insights are rare, the ability to quickly identify and act on market signals is a superpower.&lt;/p&gt;

&lt;p&gt;By automating the heavy lifting of data collection and analysis, your team is freed up to focus on high-level strategic thinking. Instead of spending time gathering data, they can spend time deciding how to use it. This shift from data collection to strategic action is where the real value lies. Whether it's identifying a gap in a competitor's product lineup or anticipating a shift in customer preferences, a scalable infrastructure provides the clarity needed to win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a &lt;strong&gt;Scalable Market Intelligence Infrastructure&lt;/strong&gt; is a journey, not a destination. It requires a combination of advanced technology, strategic focus, and a commitment to data-driven decision-making. By investing in the right components—automated ingestion, centralized storage, and AI-powered analysis—you can transform your market intelligence into a powerful engine for growth. Remember to address technical hurdles like CAPTCHAs with reliable tools like CapSolver, and always keep your Key Intelligence Questions at the center of your efforts. The result will be a more agile, informed, and competitive organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1: What exactly is a Scalable Market Intelligence Infrastructure?&lt;/strong&gt;&lt;br&gt;
A: It is a comprehensive framework of tools and processes designed to automatically gather, store, and analyze market data at scale, allowing for real-time strategic insights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: How does automation improve market intelligence?&lt;/strong&gt;&lt;br&gt;
A: Automation removes the bottlenecks of manual data collection, ensuring that intelligence is gathered 24/7 and is free from human error, which is vital for maintaining a Scalable Market Intelligence Infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: Why is CapSolver recommended for this infrastructure?&lt;/strong&gt;&lt;br&gt;
A: CapSolver is essential for overcoming web-based barriers like CAPTCHAs that often block automated scraping, ensuring that your data pipelines remain uninterrupted and reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4: Can small businesses benefit from a scalable infrastructure?&lt;/strong&gt;&lt;br&gt;
A: Yes, by starting with modular, cloud-based tools, small businesses can build a Scalable Market Intelligence Infrastructure that grows with them, providing a competitive edge from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q5: What are the most important data sources to include?&lt;/strong&gt;&lt;br&gt;
A: A well-rounded Scalable Market Intelligence Infrastructure should include competitor websites, social media, industry news, regulatory filings, and internal data like CRM records. Finding the &lt;a href="https://www.capsolver.com/blog/web-scraping/best-proxy-services" rel="noopener noreferrer"&gt;best proxy services&lt;/a&gt; is also a key factor in accessing these diverse sources.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>infrastructure</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Scalable Market Intelligence Infrastructure: A Complete Guide</title>
      <dc:creator>luisgustvo</dc:creator>
      <pubDate>Tue, 30 Jun 2026 10:31:58 +0000</pubDate>
      <link>https://dev.to/luisgustvo/scalable-market-intelligence-infrastructure-a-complete-guide-2g25</link>
      <guid>https://dev.to/luisgustvo/scalable-market-intelligence-infrastructure-a-complete-guide-2g25</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ew8kzty5ocb2bergvjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ew8kzty5ocb2bergvjz.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;Dr
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Data Hub:&lt;/strong&gt; A scalable market intelligence infrastructure unifies internal and external data sources into a single source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Collection:&lt;/strong&gt; Leveraging automation and AI reduces manual effort and ensures real-time data ingestion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Architecture:&lt;/strong&gt; Building with modular components allows for flexible scaling as business needs evolve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actionable Insights:&lt;/strong&gt; The ultimate goal is to translate raw data into strategic insights that drive competitive advantage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance and Security:&lt;/strong&gt; Robust governance frameworks are essential to protect data integrity and comply with regulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's hyper-competitive business landscape, relying on fragmented data and manual research is no longer sufficient. To stay ahead, organizations must build a &lt;strong&gt;Scalable Market Intelligence Infrastructure&lt;/strong&gt; that can continuously monitor competitors, track industry trends, and uncover new opportunities. This guide is designed for data engineers, marketing leaders, and strategic decision-makers who want to transform their market intelligence from a reactive process into a proactive, automated engine. By implementing a robust infrastructure, you can ensure that your team always has access to accurate, real-time insights, enabling faster and more confident strategic decisions. We will explore the technical architecture, operational strategies, and the critical tools required to maintain a smooth flow of information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Evolution of Market Intelligence Systems
&lt;/h2&gt;

&lt;p&gt;Market intelligence has moved far beyond simple news alerts and manual competitor tracking. Historically, teams would spend hours manually scouring websites, downloading PDFs, and compiling spreadsheets that were outdated the moment they were shared. A modern Scalable Market Intelligence Infrastructure replaces these labor-intensive tasks with automated pipelines that ingest data at scale. This evolution is driven by the need for speed and precision. Organizations that can process market signals faster than their rivals are better positioned to pivot their strategies, optimize pricing, and capture emerging customer segments.&lt;/p&gt;

&lt;p&gt;The shift toward a data-driven approach requires a fundamental change in how data is perceived. It is no longer just a supporting asset but the core driver of strategic agility. By treating market intelligence as a continuous stream rather than a series of snapshots, businesses can achieve a level of awareness that was previously impossible. This transition involves moving from siloed data pockets to a unified ecosystem where every department—from product development to sales—can utilize the same high-quality intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components of a Scalable Infrastructure
&lt;/h2&gt;

&lt;p&gt;Building a robust infrastructure requires careful planning and the integration of several key technical components. Each layer of the stack must be designed for reliability and growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Automated Data Ingestion Layer
&lt;/h3&gt;

&lt;p&gt;The foundation of any Scalable Market Intelligence Infrastructure is the ingestion layer. This component is responsible for gathering data from a vast array of sources. These sources include structured data from APIs, semi-structured data from social media feeds, and unstructured data from competitor blogs or news articles. Automation at this stage is non-negotiable. Manual collection cannot keep up with the volume and velocity of modern market data.&lt;/p&gt;

&lt;p&gt;Advanced scraping tools and API connectors are used to ensure that the data pipeline remains active 24/7. This layer must also handle the complexities of data diversity. For instance, a system might need to ingest financial reports from regulatory bodies while simultaneously monitoring sentiment on Twitter. The ability to harmonize these disparate data types into a standardized format is what separates a basic tool from a true enterprise-grade infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Centralized Data Storage and Management
&lt;/h3&gt;

&lt;p&gt;Once the data is ingested, it must be stored in a way that makes it accessible and searchable. A centralized data warehouse or data lake serves as the heart of the Scalable Market Intelligence Infrastructure. This centralized approach ensures that there is a single source of truth for the entire organization. It eliminates the problem of "data silos," where different teams have conflicting information.&lt;/p&gt;

&lt;p&gt;Data governance is also a critical aspect of this layer. Organizations must ensure that the data they collect is handled ethically and in compliance with privacy regulations like GDPR or CCPA. Implementing robust metadata management and data lineage tracking allows teams to understand the origin and reliability of every piece of intelligence. This transparency is essential for building trust in the insights generated by the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Processing and Analytics Engine
&lt;/h3&gt;

&lt;p&gt;Raw data is essentially useless without processing. The analytics engine of a Scalable Market Intelligence Infrastructure uses machine learning and natural language processing (NLP) to extract meaning from the noise. For example, NLP can be used to perform sentiment analysis on customer reviews or to automatically categorize competitor product updates.&lt;/p&gt;

&lt;p&gt;This layer is where the "intelligence" in market intelligence truly comes to life. By applying predictive models, organizations can move from understanding what happened to anticipating what might happen next. Predictive analytics can forecast market trends, identify potential competitive threats, and even suggest the best time to launch a new product. This proactive capability is a primary benefit of investing in a scalable infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Summary: Traditional vs. Scalable Infrastructure
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Traditional Market Intelligence&lt;/th&gt;
&lt;th&gt;Scalable Market Intelligence Infrastructure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Collection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual, periodic updates&lt;/td&gt;
&lt;td&gt;Automated, real-time ingestion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Siloed spreadsheets and databases&lt;/td&gt;
&lt;td&gt;Centralized data warehouse/lake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Human-driven, reactive&lt;/td&gt;
&lt;td&gt;AI-powered, predictive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited by human capacity&lt;/td&gt;
&lt;td&gt;Highly scalable, modular architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Decision Making&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow, often based on outdated data&lt;/td&gt;
&lt;td&gt;Fast, data-driven, and proactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Integrity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prone to human error&lt;/td&gt;
&lt;td&gt;High accuracy through automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Overcoming Technical Barriers with CapSolver
&lt;/h2&gt;

&lt;p&gt;A major challenge in maintaining a Scalable Market Intelligence Infrastructure is the increasing complexity of automated detection protections on the web. Many high-value data sources use sophisticated CAPTCHA systems to block automated access. These barriers can stall your data pipelines and lead to significant gaps in your intelligence.&lt;/p&gt;

&lt;p&gt;To maintain a truly scalable and reliable system, you must integrate solutions that can handle these challenges automatically. We highly recommend using &lt;a href="https://www.capsolver.com" rel="noopener noreferrer"&gt;CapSolver&lt;/a&gt; to manage these obstacles. CapSolver provides a robust API that can solve various types of CAPTCHAs, including reCAPTCHA, hCaptcha, and Cloudflare challenges, with high speed and accuracy.&lt;/p&gt;

&lt;p&gt;By incorporating CapSolver into your automation scripts, you ensure that your Scalable Market Intelligence Infrastructure remains uninterrupted. This is particularly important when scraping e-commerce sites or financial portals where data changes rapidly. For developers looking to implement this, the &lt;a href="https://docs.capsolver.com/" rel="noopener noreferrer"&gt;CapSolver documentation&lt;/a&gt; provides clear, code-based examples. For instance, if you encounter a CAPTCHA while scraping, you can simply call the CapSolver API to get the solution and continue your data extraction process. This level of reliability is essential for any enterprise-grade market intelligence system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example of using CapSolver to solve a CAPTCHA in an automated script
# Based on official CapSolver documentation
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_captcha&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;site_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;site_key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_CAPSOLVER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ReCaptchaV2TaskProxyLess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;site_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websiteKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;site_key&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/createTask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Poll for the result
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clientKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taskId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.capsolver.com/getTaskResult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ready&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRecaptchaResponse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integrating such tools ensures that your infrastructure is resilient against the evolving landscape of web security, allowing your team to focus on analysis rather than troubleshooting connection issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operational Strategies for Success
&lt;/h2&gt;

&lt;p&gt;Building the technology is only half the battle. To truly utilize a Scalable Market Intelligence Infrastructure, you must also implement the right operational strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Defining Key Intelligence Questions (KIQs)
&lt;/h3&gt;

&lt;p&gt;A common mistake is collecting data for the sake of collection. A Scalable Market Intelligence Infrastructure should be guided by specific Key Intelligence Questions (KIQs). These are the strategic questions that your business needs to answer to succeed. For example, "What is our main competitor's pricing strategy for the next quarter?" or "Which emerging technologies are most likely to disrupt our core product line?"&lt;/p&gt;

&lt;p&gt;By focusing your infrastructure on answering these questions, you ensure that the insights generated are actionable and relevant. KIQs should be reviewed and updated regularly to reflect changes in the business environment. This alignment between technology and strategy is what drives ROI from your market intelligence investments.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Establishing a Data-Driven Culture
&lt;/h3&gt;

&lt;p&gt;For a Scalable Market Intelligence Infrastructure to be effective, it must be embraced by the entire organization. This requires building a culture where data is the primary driver of decisions. Training team members on how to interpret and use the insights generated by the system is crucial.&lt;/p&gt;

&lt;p&gt;Furthermore, internal intelligence sources should not be overlooked. Insights from sales calls, customer support tickets, and CRM data are often just as valuable as external market signals. A truly scalable infrastructure integrates these internal data points to provide a 360-degree view of the market landscape. This holistic approach ensures that your strategy is grounded in both external realities and internal performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Continuous Monitoring and Optimization
&lt;/h3&gt;

&lt;p&gt;A Scalable Market Intelligence Infrastructure is not a "set it and forget it" system. It requires ongoing monitoring to ensure that data pipelines are functioning correctly and that the insights generated remain accurate. Regular audits of data sources and analysis models are necessary to maintain the integrity of the system.&lt;/p&gt;

&lt;p&gt;As your business grows, your infrastructure must also evolve. This might involve adding new data sources, upgrading your analytics engine, or integrating new tools. A modular architecture allows you to make these updates without disrupting the entire system. This flexibility is the "scalable" part of Scalable Market Intelligence Infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategic Value and Competitive Advantage
&lt;/h2&gt;

&lt;p&gt;The ultimate goal of a Scalable Market Intelligence Infrastructure is to provide a sustainable competitive advantage. In a world where information is abundant but insights are rare, the ability to quickly identify and act on market signals is a superpower.&lt;/p&gt;

&lt;p&gt;By automating the heavy lifting of data collection and analysis, your team is freed up to focus on high-level strategic thinking. Instead of spending time gathering data, they can spend time deciding how to use it. This shift from data collection to strategic action is where the real value lies. Whether it's identifying a gap in a competitor's product lineup or anticipating a shift in customer preferences, a scalable infrastructure provides the clarity needed to win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a &lt;strong&gt;Scalable Market Intelligence Infrastructure&lt;/strong&gt; is a journey, not a destination. It requires a combination of advanced technology, strategic focus, and a commitment to data-driven decision-making. By investing in the right components—automated ingestion, centralized storage, and AI-powered analysis—you can transform your market intelligence into a powerful engine for growth. Remember to address technical hurdles like CAPTCHAs with reliable tools like CapSolver, and always keep your Key Intelligence Questions at the center of your efforts. The result will be a more agile, informed, and competitive organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1: What exactly is a Scalable Market Intelligence Infrastructure?&lt;/strong&gt;&lt;br&gt;
A: It is a comprehensive framework of tools and processes designed to automatically gather, store, and analyze market data at scale, allowing for real-time strategic insights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: How does automation improve market intelligence?&lt;/strong&gt;&lt;br&gt;
A: Automation removes the bottlenecks of manual data collection, ensuring that intelligence is gathered 24/7 and is free from human error, which is vital for maintaining a Scalable Market Intelligence Infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: Why is CapSolver recommended for this infrastructure?&lt;/strong&gt;&lt;br&gt;
A: CapSolver is essential for overcoming web-based barriers like CAPTCHAs that often block automated scraping, ensuring that your data pipelines remain uninterrupted and reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4: Can small businesses benefit from a scalable infrastructure?&lt;/strong&gt;&lt;br&gt;
A: Yes, by starting with modular, cloud-based tools, small businesses can build a Scalable Market Intelligence Infrastructure that grows with them, providing a competitive edge from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q5: What are the most important data sources to include?&lt;/strong&gt;&lt;br&gt;
A: A well-rounded Scalable Market Intelligence Infrastructure should include competitor websites, social media, industry news, regulatory filings, and internal data like CRM records.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/blog/The-other-captcha/what-are-captchas" rel="noopener noreferrer"&gt;What are CAPTCHAs?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/blog/web-scraping/best-proxy-services" rel="noopener noreferrer"&gt;Best Proxy Services for Web Scraping&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/blog/reCAPTCHA/how-to-solve-recaptcha-in-web-scraping-using-python" rel="noopener noreferrer"&gt;How to Solve CAPTCHA in Web Scraping Using Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/blog/web-scraping/top-5-web-scraping-services" rel="noopener noreferrer"&gt;Top 5 Web Scraping Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.capsolver.com/blog/web-scraping/webscraping-tools-explained" rel="noopener noreferrer"&gt;Web Scraping Tools Explained&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  External References
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://aligntoday.com/blog/building-a-scalable-infrastructure-to-support-rapid-growth/" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Align Today: Building Scalable Infrastructure&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://www.contify.com/resources/blog/market-and-competitive-intelligence-program-guide/" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Contify: 7 Steps to a Winning M&amp;amp;CI Program&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://improvado.io/blog/marketing-intelligence-tools" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Improvado: 10 Best Marketing Intelligence Tools&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://www.grandviewresearch.com/industry-analysis/ai-infrastructure-market-report" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;Grand View Research: AI Infrastructure Market Report&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://www.thoughtspot.com/data-trends/best-practices/data-infrastructure-for-modern-analytics" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;ThoughtSpot: Data Infrastructure for Modern Analytics&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
