Files
Dorod-Sky/docs/going-to-production/captcha-bot-detection.mdx
2026-02-11 12:45:37 +00:00

155 lines
5.8 KiB
Plaintext

---
title: CAPTCHA & Bot Detection
subtitle: How Skyvern handles CAPTCHAs and avoids triggering anti-bot systems
slug: going-to-production/captcha-bot-detection
---
Skyvern detects CAPTCHAs using its vision model and solves them automatically.
However, CAPTCHA solving is not guaranteed. Skyvern's solvers can fail on novel challenges or rate-limited IPs.
This guide helps you detect CAPTCHA failures and implement fallbacks to keep your automation running smoothly.
**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 |
---
## Use [`error_code_mapping`](/going-to-production/error-handling#step-3-use-error_code_mapping)
When a CAPTCHA blocks your automation, this gives you a consistent error code instead of parsing free-text failure messages.
<CodeGroup>
```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={
"cant_solve_captcha": "return this error if captcha isn't solved after multiple retries",
},
)
```
```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: {
cant_solve_captcha: "return this error if captcha isn't solved after multiple retries",
},
},
});
```
```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": {
"cant_solve_captcha": "return this error if captcha isn't solved after multiple retries"
}
}'
```
</CodeGroup>
When a CAPTCHA blocks the run, the response includes `output.error = "cant_solve_captcha"`. You can branch your logic on this code.
<Info>
For more on error code mapping and handling failures programmatically, see [Error Handling](/going-to-production/error-handling).
</Info>
## Take Control from the browser stream
In the Cloud UI, head to Runs > Click on *your run* > Click on the "Take Control" button over the browser stream.
This lets you manually solve CAPTCHAs.
<img src="/images/take-control.png" />
Release control when you're done and the agent resumes from where you left off.
---
## Built-in bot detection avoidance
Skyvern automatically configures the browser to reduce bot detection triggers. These protections apply to every run. No configuration needed.
- **`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:
- **Use residential proxies for sensitive sites**: Datacenter IPs are the most common bot signal. Residential proxies route through real ISP addresses. Set `proxy_location="RESIDENTIAL"` or use `RESIDENTIAL_ISP` for static IPs.
- **Reuse browser sessions for multi-step flows**: Creating a fresh browser for every step looks suspicious. A persistent session maintains cookies, cache, and history. See [Browser Sessions](/optimization/browser-sessions).
- **Use browser profiles for repeat visits**: Profiles save browser state from a previous session. The site sees a known browser with familiar cookies instead of a blank slate. See [Browser Profiles](/optimization/browser-profiles).
- **Add wait blocks between rapid actions**: Instant actions can trigger behavioral detection. A short pause between steps looks more human.
### If you get blocked
- **Increase `max_steps`**: Some bot challenges (like Cloudflare) loop through multiple verification pages. More steps give the solver more attempts.
- **Switch to a residential proxy**: `RESIDENTIAL_ISP` provides a static IP that services are more likely to trust.
- **Use a browser profile that previously passed**: If a profile has already cleared a Cloudflare challenge on a domain, it's more likely to pass again.
- **Load Chrome extensions**: Extensions can add additional stealth capabilities. Set `EXTENSIONS` and `EXTENSIONS_BASE_PATH` in your environment.
---
## Self-hosted deployments
Automatic CAPTCHA solving is not available for self-hosted deployments.
Instead, when a CAPTCHA is detected, the agent pauses for 30 seconds to allow manual intervention. Solve it in the browser window yourself, then the agent continues automatically.
---
## Next steps
<CardGroup cols={2}>
<Card
title="Proxy & Geolocation"
icon="globe"
href="/going-to-production/proxy-geolocation"
>
Route traffic through residential proxies in 19 countries
</Card>
<Card
title="Handle 2FA"
icon="lock"
href="/credentials/handle-2fa"
>
Configure TOTP, email, and SMS verification codes
</Card>
<Card
title="Browser Sessions"
icon="window-restore"
href="/optimization/browser-sessions"
>
Persist browser state across multiple runs
</Card>
<Card
title="Error Handling"
icon="triangle-exclamation"
href="/going-to-production/error-handling"
>
Map CAPTCHA and bot failures to custom error codes
</Card>
</CardGroup>