--- title: CAPTCHA & Bot Detection subtitle: How Skyvern detects, solves, and avoids CAPTCHAs and anti-bot systems slug: going-to-production/captcha-bot-detection --- Websites use CAPTCHAs and bot detection to block automated traffic. Skyvern handles both — it detects CAPTCHAs using vision, solves them automatically on Skyvern Cloud, and configures browsers to avoid triggering anti-bot systems in the first place. --- ## CAPTCHA detection Skyvern detects CAPTCHAs using its LLM vision model. During each step, the AI analyzes the page screenshot and identifies whether a CAPTCHA is present and what type it is. **Supported CAPTCHA types:** | Type | Examples | |------|----------| | `RECAPTCHA` | Google reCAPTCHA v2, v3 | | `HCAPTCHA` | hCaptcha checkbox, image challenges | | `CLOUDFLARE` | Cloudflare Turnstile, Challenge pages | | `FUNCAPTCHA` | FunCaptcha / ArkoseLabs | | `MTCAPTCHA` | MTCaptcha | | `TEXT_CAPTCHA` | Distorted text/number images with an input field | | `OTHER` | Unrecognized CAPTCHA types | When the AI detects a CAPTCHA, it emits a `SOLVE_CAPTCHA` action with the identified `captcha_type`. What happens next depends on your deployment. --- ## CAPTCHA solving ### Skyvern Cloud (automatic) On [Skyvern Cloud](https://app.skyvern.com), CAPTCHAs are solved automatically. When the AI detects a CAPTCHA, Skyvern's solver service handles it in the background. No configuration needed — it works out of the box for all supported CAPTCHA types. If the solver cannot resolve the CAPTCHA (rare edge cases or novel CAPTCHA types), the task continues with a `SOLVE_CAPTCHA` action failure. Handle this with [error code mapping](/going-to-production/error-handling): ```python Python result = await client.run_task( prompt="Submit the application form. COMPLETE when you see confirmation.", url="https://example.com/apply", error_code_mapping={ "captcha_failed": "Return this if a CAPTCHA blocks progress after multiple attempts", }, ) ``` ```typescript TypeScript const result = await client.runTask({ body: { prompt: "Submit the application form. COMPLETE when you see confirmation.", url: "https://example.com/apply", error_code_mapping: { captcha_failed: "Return this if a CAPTCHA blocks progress after multiple attempts", }, }, }); ``` ```bash cURL curl -X POST "https://api.skyvern.com/v1/run/tasks" \ -H "x-api-key: $SKYVERN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Submit the application form. COMPLETE when you see confirmation.", "url": "https://example.com/apply", "error_code_mapping": { "captcha_failed": "Return this if a CAPTCHA blocks progress after multiple attempts" } }' ``` ### Human Interaction block (workflows) For workflows where you want a human to solve the CAPTCHA manually, use the **Human Interaction** block. The workflow pauses and notifies you, then resumes after you solve it. ```yaml blocks: - block_type: navigation label: fill_form url: https://example.com/form navigation_goal: Fill out the registration form - block_type: human_interaction label: solve_captcha message: "Please solve the CAPTCHA and click Continue" - block_type: navigation label: submit_form navigation_goal: Click the submit button ``` --- ## Bot detection avoidance Skyvern automatically configures the browser to reduce bot detection triggers. These protections apply to every run — no configuration needed. ### Browser fingerprinting Skyvern launches Chromium with settings that remove common automation signals: - **`AutomationControlled` disabled** — Removes the Blink feature flag that marks the browser as automated - **`navigator.webdriver` hidden** — The `enable-automation` flag is suppressed so JavaScript detection scripts don't see a webdriver - **Viewport and user agent** — Set to match real consumer browsers - **Locale and timezone** — Automatically matched to the proxy location (see [Proxy & Geolocation](/going-to-production/proxy-geolocation)) ### Reducing detection risk Beyond fingerprinting, how you structure your automation affects detection. Three patterns that help: **1. Use residential proxies for sensitive sites.** Datacenter IPs are the most common bot signal. Residential proxies route through real ISP addresses. See [Proxy & Geolocation](/going-to-production/proxy-geolocation). **2. Reuse browser sessions for multi-step flows.** Creating a fresh browser for every step looks suspicious. A persistent session maintains cookies, cache, and history — appearing as a returning user. See [Browser Sessions](/optimization/browser-sessions). **3. Use browser profiles for repeat visits.** Profiles save browser state from a previous session. Starting with an existing profile means the site sees a known browser with familiar cookies, not a blank slate. See [Browser Profiles](/optimization/browser-profiles). --- ## Self-hosted deployment The sections above apply to Skyvern Cloud. If you're running Skyvern locally, the following differences apply. ### CAPTCHA solving The open-source version does **not** include automatic CAPTCHA solving. When a CAPTCHA is detected, the agent pauses for 30 seconds to allow manual intervention (e.g., solving it in the browser window yourself), then continues. To handle CAPTCHAs in self-hosted workflows, use the Human Interaction block as described above. ### Browser extensions Self-hosted deployments can load Chrome extensions for additional stealth or functionality: ```bash # .env EXTENSIONS=extension1,extension2 EXTENSIONS_BASE_PATH=/path/to/extensions ``` Extensions are loaded automatically when the browser launches. ### Proxies Self-hosted deployments need their own proxy infrastructure. The `proxy_location` parameter is not available — configure proxies at the network level or via environment variables. --- ## Troubleshooting ### CAPTCHA blocks the run **On Skyvern Cloud:** This is rare. If it happens, the CAPTCHA type may be unsupported or the site changed its challenge. Add an `error_code_mapping` entry to detect the failure, and contact [support@skyvern.com](mailto:support@skyvern.com). **Self-hosted:** Use a Human Interaction block, or solve it manually within the 30-second window. ### Bot detection triggered (access denied) 1. Switch to a residential proxy — `proxy_location="RESIDENTIAL"` or `RESIDENTIAL_ISP` for static IPs 2. Reuse a browser session instead of creating fresh browsers 3. Use a browser profile with existing cookies 4. Add `wait` blocks between rapid actions to reduce behavioral signals ### Cloudflare challenge page loops Cloudflare sometimes loops through multiple challenges. If a task gets stuck: - Increase `max_steps` to give the solver more attempts - Use `RESIDENTIAL_ISP` for a static IP that Cloudflare is more likely to trust - Use a browser profile that has previously passed the Cloudflare challenge on that domain --- ## Next steps Route traffic through residential proxies in 19 countries Configure TOTP, email, and SMS verification codes Persist browser state across multiple runs Map CAPTCHA and bot failures to custom error codes