Skip to main content

Command Palette

Search for a command to run...

Integrating CapSolver with Skyvern: A Developer-First Pattern

Updated
3 min readView as Markdown

Skyvern can interpret a page and act on natural-language instructions. CapSolver can return a documented CAPTCHA solution. A production integration should connect them without placing secrets or low-level verification state inside the AI agent.

This tutorial shows the pattern for owned or explicitly authorized environments.

Architecture

Use a narrow pipeline:

Navigate with Skyvern
→ classify the authorized challenge
→ call CapSolver from application code
→ return the result to the same browser page
→ continue with Skyvern
→ verify the intended operation

Skyvern’s public SDK exposes AI-assisted page operations such as page.act() and page.validate(). CapSolver’s SDK accepts task parameters and returns a solution. Your application remains responsible for authorization, session ownership, secrets, and success checks.

Setup

Skyvern currently supports Python 3.11–3.13 in its pip quickstart:

python -m venv .venv
source .venv/bin/activate

pip install "skyvern[all]"
pip install --upgrade capsolver
python -m playwright install chromium

Load credentials outside the prompt:

export CAPSOLVER_API_KEY="set-this-in-your-secret-manager"

Solve a documented reCAPTCHA v2 task

The official CapSolver documentation shows:

import capsolver

solution = capsolver.solve({
    "type": "ReCaptchaV2TaskProxyLess",
    "websiteURL": "https://www.google.com/recaptcha/api2/demo",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
})

token = solution["gRecaptchaResponse"]

Use the actual authorized page URL and site key. Keep the API key in the host process; do not add it to Skyvern instructions or logs.

Hand the result to the page

For a page that uses the standard hidden response field:

async def inject_token(page, token: str) -> None:
    await page.evaluate(
        """
        (token) => {
            const textarea = document.getElementById('g-recaptcha-response');
            if (!textarea) {
                throw new Error('g-recaptcha-response field not found');
            }
            textarea.value = token;
            textarea.dispatchEvent(new Event('change', { bubbles: true }));
        }
        """,
        token,
    )

Treat this as one integration pattern, not a universal recipe. A system you own may use a callback or server request instead. Inspect its implementation and preserve the same browser session.

Resume and validate

await page.act("Submit the form")
ok = await page.validate(
    "The authorized test completed and the expected result is visible"
)
if not ok:
    raise RuntimeError("Expected result was not verified")

Never treat “CapSolver returned a value” as proof that the business operation completed.

Add ImageToTextTask when the page uses an image code

For an authorized image CAPTCHA:

image_src = await page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
    raise RuntimeError("A valid Base64 CAPTCHA image was not found")

base64_image = image_src.split(",", 1)[1]
solution = capsolver.solve({
    "type": "ImageToTextTask",
    "websiteURL": TARGET_URL,
    "module": "common",
    "body": base64_image,
})
captcha_text = solution["text"]

Fill the returned text into the expected input, submit, and verify the page result. Consult the current ImageToTextTask reference before using optional modules.

Debugging checklist

  • Does websiteURL match the current page?

  • Does the site key belong to that page?

  • Did navigation invalidate the page state?

  • Did the result reach the expected field or callback?

  • Is the browser session unchanged?

  • Is the success assertion specific?

  • Is the retry budget bounded?

Security checklist

  • Allowlist authorized domains.

  • Keep API keys in a secret store.

  • Redact tokens and cookies from traces.

  • Reject redirects to unapproved hosts.

  • Limit retries and total runtime.

  • Require a final application assertion.

Closing thought

AI browser automation works best when the model handles semantic interaction and deterministic code handles security-sensitive state. Skyvern and CapSolver fit that division naturally when the integration keeps authorization, secrets, token handoff, and verification outside the prompt.

Links: