# Scrapfly Documentation

## Table of Contents

### Dashboard

- [Intro](https://scrapfly.io/docs)
- [Project](https://scrapfly.io/docs/project)
- [Account](https://scrapfly.io/docs/account)
- [Workspace & Team](https://scrapfly.io/docs/workspace-and-team)
- [Billing](https://scrapfly.io/docs/billing)

### Products

#### MCP Server

- [Getting Started](https://scrapfly.io/docs/mcp/getting-started)
- [Tools & API Spec](https://scrapfly.io/docs/mcp/tools)
- [Authentication](https://scrapfly.io/docs/mcp/authentication)
- [Examples & Use Cases](https://scrapfly.io/docs/mcp/examples)
- [FAQ](https://scrapfly.io/docs/mcp/faq)
##### Integrations

- [Overview](https://scrapfly.io/docs/mcp/integrations)
- [Claude Desktop](https://scrapfly.io/docs/mcp/integrations/claude-desktop)
- [Claude Code](https://scrapfly.io/docs/mcp/integrations/claude-code)
- [ChatGPT](https://scrapfly.io/docs/mcp/integrations/chatgpt)
- [Cursor](https://scrapfly.io/docs/mcp/integrations/cursor)
- [Cline](https://scrapfly.io/docs/mcp/integrations/cline)
- [Windsurf](https://scrapfly.io/docs/mcp/integrations/windsurf)
- [Zed](https://scrapfly.io/docs/mcp/integrations/zed)
- [Roo Code](https://scrapfly.io/docs/mcp/integrations/roo-code)
- [VS Code](https://scrapfly.io/docs/mcp/integrations/vscode)
- [LangChain](https://scrapfly.io/docs/mcp/integrations/langchain)
- [LlamaIndex](https://scrapfly.io/docs/mcp/integrations/llamaindex)
- [CrewAI](https://scrapfly.io/docs/mcp/integrations/crewai)
- [OpenAI](https://scrapfly.io/docs/mcp/integrations/openai)
- [n8n](https://scrapfly.io/docs/mcp/integrations/n8n)
- [Make](https://scrapfly.io/docs/mcp/integrations/make)
- [Zapier](https://scrapfly.io/docs/mcp/integrations/zapier)
- [Vapi AI](https://scrapfly.io/docs/mcp/integrations/vapi)
- [Agent Builder](https://scrapfly.io/docs/mcp/integrations/agent-builder)
- [Custom Client](https://scrapfly.io/docs/mcp/integrations/custom-client)


#### Web Scraping API

- [Getting Started](https://scrapfly.io/docs/scrape-api/getting-started)
- [API Specification]()
- [Monitoring](https://scrapfly.io/docs/monitoring)
- [Customize Request](https://scrapfly.io/docs/scrape-api/custom)
- [Debug](https://scrapfly.io/docs/scrape-api/debug)
- [Anti Scraping Protection](https://scrapfly.io/docs/scrape-api/anti-scraping-protection)
- [Proxy](https://scrapfly.io/docs/scrape-api/proxy)
- [Proxy Mode](https://scrapfly.io/docs/scrape-api/proxy-mode)
- [Proxy Mode - Screaming Frog](https://scrapfly.io/docs/scrape-api/proxy-mode/screaming-frog)
- [Proxy Mode - Apify](https://scrapfly.io/docs/scrape-api/proxy-mode/apify)
- [(Auto) Data Extraction](https://scrapfly.io/docs/scrape-api/extraction)
- [Javascript Rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering)
- [Javascript Scenario](https://scrapfly.io/docs/scrape-api/javascript-scenario)
- [SSL](https://scrapfly.io/docs/scrape-api/ssl)
- [DNS](https://scrapfly.io/docs/scrape-api/dns)
- [Cache](https://scrapfly.io/docs/scrape-api/cache)
- [Batch (Multi-URL Scraping)](https://scrapfly.io/docs/scrape-api/batch)
- [Session](https://scrapfly.io/docs/scrape-api/session)
- [Webhook](https://scrapfly.io/docs/scrape-api/webhook)
- [Screenshot](https://scrapfly.io/docs/scrape-api/screenshot)
- [Errors](https://scrapfly.io/docs/scrape-api/errors)
- [Timeout](https://scrapfly.io/docs/scrape-api/understand-timeout)
- [Throttling](https://scrapfly.io/docs/throttling)
- [Troubleshoot](https://scrapfly.io/docs/scrape-api/troubleshoot)
- [Billing](https://scrapfly.io/docs/scrape-api/billing)
- [FAQ](https://scrapfly.io/docs/scrape-api/faq)

#### Crawler API

- [Getting Started](https://scrapfly.io/docs/crawler-api/getting-started)
- [API Specification]()
- [Retrieving Results](https://scrapfly.io/docs/crawler-api/results)
- [WARC Format](https://scrapfly.io/docs/crawler-api/warc-format)
- [Data Extraction](https://scrapfly.io/docs/crawler-api/extraction-rules)
- [Webhook](https://scrapfly.io/docs/crawler-api/webhook)
- [Billing](https://scrapfly.io/docs/crawler-api/billing)
- [Errors](https://scrapfly.io/docs/crawler-api/errors)
- [Troubleshoot](https://scrapfly.io/docs/crawler-api/troubleshoot)
- [FAQ](https://scrapfly.io/docs/crawler-api/faq)

#### Screenshot API

- [Getting Started](https://scrapfly.io/docs/screenshot-api/getting-started)
- [API Specification]()
- [Accessibility Testing](https://scrapfly.io/docs/screenshot-api/accessibility)
- [Webhook](https://scrapfly.io/docs/screenshot-api/webhook)
- [Billing](https://scrapfly.io/docs/screenshot-api/billing)
- [Errors](https://scrapfly.io/docs/screenshot-api/errors)

#### Extraction API

- [Getting Started](https://scrapfly.io/docs/extraction-api/getting-started)
- [API Specification]()
- [Rules Template](https://scrapfly.io/docs/extraction-api/rules-and-template)
- [LLM Extraction](https://scrapfly.io/docs/extraction-api/llm-prompt)
- [AI Auto Extraction](https://scrapfly.io/docs/extraction-api/automatic-ai)
- [Webhook](https://scrapfly.io/docs/extraction-api/webhook)
- [Billing](https://scrapfly.io/docs/extraction-api/billing)
- [Errors](https://scrapfly.io/docs/extraction-api/errors)
- [FAQ](https://scrapfly.io/docs/extraction-api/faq)

#### Proxy Saver

- [Getting Started](https://scrapfly.io/docs/proxy-saver/getting-started)
- [Fingerprints](https://scrapfly.io/docs/proxy-saver/fingerprints)
- [Optimizations](https://scrapfly.io/docs/proxy-saver/optimizations)
- [SSL Certificates](https://scrapfly.io/docs/proxy-saver/certificates)
- [Protocols](https://scrapfly.io/docs/proxy-saver/protocols)
- [Pacfile](https://scrapfly.io/docs/proxy-saver/pacfile)
- [Secure Credentials](https://scrapfly.io/docs/proxy-saver/security)
- [Billing](https://scrapfly.io/docs/proxy-saver/billing)

#### Cloud Browser API

- [Getting Started](https://scrapfly.io/docs/cloud-browser-api/getting-started)
- [Proxy & Geo-Targeting](https://scrapfly.io/docs/cloud-browser-api/proxy)
- [Unblock API](https://scrapfly.io/docs/cloud-browser-api/unblock)
- [Captcha Solver](https://scrapfly.io/docs/cloud-browser-api/captcha-solver)
- [File Downloads](https://scrapfly.io/docs/cloud-browser-api/file-downloads)
- [Session Resume](https://scrapfly.io/docs/cloud-browser-api/session-resume)
- [Human-in-the-Loop](https://scrapfly.io/docs/cloud-browser-api/human-in-the-loop)
- [Debug Mode](https://scrapfly.io/docs/cloud-browser-api/debug-mode)
- [Bring Your Own Proxy](https://scrapfly.io/docs/cloud-browser-api/bring-your-own-proxy)
- [Browser Extensions](https://scrapfly.io/docs/cloud-browser-api/extensions)
- [Native Browser MCP](https://scrapfly.io/docs/cloud-browser-api/mcp)
- [DevTools Protocol](https://scrapfly.io/docs/cloud-browser-api/cdp-reference)
##### Integrations

- [Puppeteer](https://scrapfly.io/docs/cloud-browser-api/puppeteer)
- [Playwright](https://scrapfly.io/docs/cloud-browser-api/playwright)
- [Selenium](https://scrapfly.io/docs/cloud-browser-api/selenium)
- [Vercel Agent Browser](https://scrapfly.io/docs/cloud-browser-api/agent-browser)
- [Browser Use](https://scrapfly.io/docs/cloud-browser-api/browser-use)
- [Stagehand](https://scrapfly.io/docs/cloud-browser-api/stagehand)

- [Billing](https://scrapfly.io/docs/cloud-browser-api/billing)
- [Errors](https://scrapfly.io/docs/cloud-browser-api/errors)


### Tools

- [Antibot Detector](https://scrapfly.io/docs/tools/antibot-detector)

### SDK

- [Golang](https://scrapfly.io/docs/sdk/golang)
- [Python](https://scrapfly.io/docs/sdk/python)
- [Rust](https://scrapfly.io/docs/sdk/rust)
- [TypeScript](https://scrapfly.io/docs/sdk/typescript)
- [Scrapy](https://scrapfly.io/docs/sdk/scrapy)

### Integrations

- [Getting Started](https://scrapfly.io/docs/integration/getting-started)
- [LangChain](https://scrapfly.io/docs/integration/langchain)
- [LlamaIndex](https://scrapfly.io/docs/integration/llamaindex)
- [CrewAI](https://scrapfly.io/docs/integration/crewai)
- [Zapier](https://scrapfly.io/docs/integration/zapier)
- [Make](https://scrapfly.io/docs/integration/make)
- [n8n](https://scrapfly.io/docs/integration/n8n)

### Academy

- [Overview](https://scrapfly.io/academy)
- [Web Scraping Overview](https://scrapfly.io/academy/scraping-overview)
- [Tools](https://scrapfly.io/academy/tools-overview)
- [Reverse Engineering](https://scrapfly.io/academy/reverse-engineering)
- [Static Scraping](https://scrapfly.io/academy/static-scraping)
- [HTML Parsing](https://scrapfly.io/academy/html-parsing)
- [Dynamic Scraping](https://scrapfly.io/academy/dynamic-scraping)
- [Hidden API Scraping](https://scrapfly.io/academy/hidden-api-scraping)
- [Headless Browsers](https://scrapfly.io/academy/headless-browsers)
- [Hidden Web Data](https://scrapfly.io/academy/hidden-web-data)
- [JSON Parsing](https://scrapfly.io/academy/json-parsing)
- [Data Processing](https://scrapfly.io/academy/data-processing)
- [Scaling](https://scrapfly.io/academy/scaling)
- [Walkthrough Summary](https://scrapfly.io/academy/walkthrough-summary)
- [Scraper Blocking](https://scrapfly.io/academy/scraper-blocking)
- [Proxies](https://scrapfly.io/academy/proxies)

---

# Captcha Solver

 [  View as markdown ](https://scrapfly.io/?view=markdown)   Copy for LLM    Copy for LLM  [     Open in ChatGPT ](https://chatgpt.com/?hints=search&prompt=Read%20from%20https%3A%2F%2Fscrapfly.io%2Fdocs%2Fcloud-browser-api%2Fcaptcha-solver%20so%20I%20can%20ask%20questions%20about%20it.) [     Open in Claude ](https://claude.ai/new?q=Read%20from%20https%3A%2F%2Fscrapfly.io%2Fdocs%2Fcloud-browser-api%2Fcaptcha-solver%20so%20I%20can%20ask%20questions%20about%20it.) [     Open in Perplexity ](https://www.perplexity.ai/search/new?q=Read%20from%20https%3A%2F%2Fscrapfly.io%2Fdocs%2Fcloud-browser-api%2Fcaptcha-solver%20so%20I%20can%20ask%20questions%20about%20it.) 

 

 

 1. [Cloud Browser](https://scrapfly.io/docs/cloud-browser-api/getting-started)
2. Captcha Solver
 
  Scrapfly Cloud Browser can **detect and solve captchas automatically** while your browser session is live. Enable the captcha solver once, and every challenge that appears on the page (Turnstile, reCAPTCHA, DataDome, GeeTest, PerimeterX) is handled by the browser itself. Your code only observes the outcome through four structured CDP events.

  **Beta Feature:** Cloud Browser is currently in beta. The captcha solver is part of the `Antibot` CDP domain and is available on every Cloud Browser session. 

## How It Works

 A Cloud Browser session exposes a custom `Antibot` CDP domain in addition to the standard Chrome DevTools Protocol surface. A single call to `Antibot.captchaEnable` arms the browser's built-in solver for the lifetime of the session:

1. **Detect:** The browser continuously scans the frame tree (including cross-origin iframes) after every navigation for known captcha challenges.
2. **Solve:** On detection, the browser drives the solve autonomously. Interaction-based captchas use human-like slider drags and checkbox clicks. Token-based captchas (Turnstile, reCAPTCHA, GeeTest) are resolved by the built-in solver pipeline.
3. **Notify:** Your code receives CDP events at each step: `captchaDetected`, `captchaSolvingStarted`, `captchaSolved`, or `captchaError`. Use them to update UI, log outcomes, or gate subsequent actions on success.
4. **Continue:** Solves are serialized one-at-a-time; the browser never runs two in parallel, so the page state stays predictable.
 
  **Zero-orchestration design:** You do *not* call `solveCaptcha` yourself after each detection. The browser already does. `solveCaptcha` exists as a manual escape hatch for custom flows; the default automation path is `captchaEnable` plus listening for events. 



## Supported Captcha Types

 | Type | `CaptchaType` | Solve Method | Price per solved captcha |
|---|---|---|---|
| Cloudflare Turnstile (checkbox) | `turnstile_checkbox` | Checkbox click | 5 API credits |
| Cloudflare Turnstile (invisible / token) | `turnstile` | Token resolution | 20 API credits |
| DataDome slider | `datadome_slider` | Human-like slider drag | 5 API credits |
| Google reCAPTCHA v2/v3 | `recaptcha` | Token resolution | 20 API credits |
| Puzzle Click | `hcaptcha_click` | Token resolution | 20 API credits |
| GeeTest | `geetest` | Token resolution | 20 API credits |
| PerimeterX hold challenge | `perimeterx_hold` | Click-and-hold | 5 API credits |
| DataDome interstitial (token challenge) | `datadome` | *Blocked / unsolvable* | Not billed |
| Any other type the browser learns to handle | *(default)* | Varies | 10 API credits |

  **About `datadome` (interstitial):** the session is *blocked* and surfaced via `captchaDetected`, but the interstitial itself is unsolvable — it's a hard block, not a challenge. Any solver attempt ends in `captchaError`. `datadome` blocks are never billed. 

 **Why?** DataDome encodes the challenge outcome in the `t` query parameter of the captcha URL: - `t=fe` — a solvable interaction challenge. Handled by the `datadome_slider` type.
- `t=bv` — the exit IP has been banned by DataDome. No captcha solver (ours or an upstream provider) can recover this; the only fix is a fresh IP.
 
 The interstitial type always carries `t=bv`, which is why it's categorized as *blocked* rather than a challenge. Recovery: close the session and open a new one on a different proxy pool or country (a datacenter-to-residential rotation typically clears the ban fastest). 

  **Failures are free.** You're only billed when a captcha reaches `captchaSolved`. A `captchaError` costs nothing, whatever the reason. 

## Enabling the Solver

 The captcha solver is **opt-in** — it only runs when you ask for it. There are two ways to turn it on, and both result in the browser firing `Antibot.captchaEnable` on the first page attach.

### 1. `solve_captcha=true` connection parameter *(recommended)*

 Add `solve_captcha=true` to the Cloud Browser WebSocket URL (or pass it as an SDK option). The browser arms the solver as soon as the first page loads — no extra CDP plumbing in your client code.

 | Parameter | Type | Default | Description |
|---|---|---|---|
| `solve_captcha` | boolean | `false` | When `true`, arms Scrapium's built-in captcha detector + solver on the first page attach. Turnstile, DataDome slider, reCAPTCHA, GeeTest, PerimeterX hold, and puzzle captchas are handled automatically. Billed per solve — see [Pricing](#pricing). A `captchaError` costs nothing. |

  WSS URL  Python SDK  TypeScript SDK  CLI 

  ```
wss://browser.scrapfly.io?api_key=&proxy_pool=public_residential_pool&country=us&solve_captcha=true
```

 

   

 

 

 ```
from scrapfly import ScrapflyClient

client = ScrapflyClient(key="")
ws_url = client.cloud_browser(
    proxy_pool="residential",
    country="us",
    solve_captcha=True,   # arms the solver on page attach
)
```

 

   

 

 

 ```
import { ScrapflyClient } from 'scrapfly-sdk';

const client = new ScrapflyClient({ key: '' });
const wsUrl = client.cloudBrowser({
    proxy_pool: 'residential',
    country: 'us',
    solve_captcha: true,   // arms the solver on page attach
});
```

 

   

 

 

 ```
scrapfly browser \
  --proxy-pool residential \
  --country us \
  --solve-captcha \
  --pretty
```

 

   

 

 

 

 Once enabled, the solver remains active for the rest of the session. You can still subscribe to `Antibot.captchaDetected` / `captchaSolved` / `captchaError` events to observe progress.

### 2. `Antibot.captchaEnable` CDP command *(advanced)*

 For workflows that need runtime control (arm on specific pages only, re-arm after `captchaDisable`), skip the connection parameter and call `Antibot.captchaEnable` directly over CDP. See the [Quick Start](#quick-start) below for a full example.

## Quick Start

Enable the solver once, subscribe to the events you care about, and interact with the page normally. The browser handles the rest.

    Python · Playwright    JS · Playwright    Puppeteer  

  ```
from scrapfly import ScrapflyClient
from playwright.sync_api import sync_playwright

client = ScrapflyClient(key="")
ws_url = client.cloud_browser(proxy_pool="residential", country="us")

with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(ws_url)
    context = browser.contexts[0]
    page = context.pages[0] if context.pages else context.new_page()

    # Attach a raw CDP session to reach the Antibot domain
    cdp = context.new_cdp_session(page)

    # 1. Subscribe BEFORE enabling so no early detection is missed
    cdp.on("Antibot.captchaDetected",       lambda e: print("detected", e))
    cdp.on("Antibot.captchaSolvingStarted", lambda e: print("solving",  e))
    cdp.on("Antibot.captchaSolved",         lambda e: print("solved",   e))
    cdp.on("Antibot.captchaError",          lambda e: print("failed",   e))

    # 2. Arm the solver for the lifetime of this session
    cdp.send("Antibot.captchaEnable")

    # 3. Scrape as usual. Captchas are handled transparently
    page.goto("https://captcha-protected-site.com/product/42")
    page.wait_for_load_state("networkidle")
    print(page.title())

    # 4. (Optional) Inspect everything that happened this session
    history = cdp.send("Antibot.getSolvedCaptchas")
    print(history)

    browser.close()
```

 

   

 

 

 ```
import { chromium } from 'playwright';
import { ScrapflyClient } from 'scrapfly-sdk';

const client = new ScrapflyClient({ key: '' });
const wsUrl = client.cloudBrowser({ proxyPool: 'residential', country: 'us' });

const browser = await chromium.connectOverCDP(wsUrl);
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();

const cdp = await context.newCDPSession(page);

// 1. Subscribe BEFORE enabling
cdp.on('Antibot.captchaDetected',       (e) => console.log('detected', e));
cdp.on('Antibot.captchaSolvingStarted', (e) => console.log('solving',  e));
cdp.on('Antibot.captchaSolved',         (e) => console.log('solved',   e));
cdp.on('Antibot.captchaError',          (e) => console.log('failed',   e));

// 2. Arm the solver
await cdp.send('Antibot.captchaEnable');

// 3. Scrape as usual
await page.goto('https://captcha-protected-site.com/product/42');
await page.waitForLoadState('networkidle');
console.log(await page.title());

// 4. Inspect full session history
const history = await cdp.send('Antibot.getSolvedCaptchas');
console.log(history);

await browser.close();
```

 

   

 

 

 ```
import puppeteer from 'puppeteer-core';

const wsUrl = `wss://browser.scrapfly.io/?api_key=&proxy_pool=public_residential_pool&country=us`;
const browser = await puppeteer.connect({ browserWSEndpoint: wsUrl });

const [page] = await browser.pages();
const cdp = await page.target().createCDPSession();

// 1. Subscribe BEFORE enabling
cdp.on('Antibot.captchaDetected',       (e) => console.log('detected', e));
cdp.on('Antibot.captchaSolvingStarted', (e) => console.log('solving',  e));
cdp.on('Antibot.captchaSolved',         (e) => console.log('solved',   e));
cdp.on('Antibot.captchaError',          (e) => console.log('failed',   e));

// 2. Arm the solver
await cdp.send('Antibot.captchaEnable');

// 3. Scrape as usual
await page.goto('https://captcha-protected-site.com/product/42');
console.log(await page.title());

await browser.close();
```

 

   

 

 

 

  **MCP users:** If you are driving the browser through the [native MCP integration](https://scrapfly.io/docs/cloud-browser-api/mcp), `captchaEnable` is called automatically on every `cloud_browser_open` / `unblock`, and a concise captcha summary is appended to every tool response. No explicit wiring is needed. 

## Event Flow

Per detection, the browser emits up to three events in sequence. The lifecycle is always terminal. A given `detectionId` either finishes with `captchaSolved` or with `captchaError`, never both, never a second attempt.

 ```
captchaDetected        ──▶   detectionId=abc  type=turnstile_checkbox  frameUrl=...
captchaSolvingStarted  ──▶   detectionId=abc  method=checkbox
captchaSolved          ──▶   detectionId=abc  method=checkbox  token=""
                      OR
captchaError           ──▶   detectionId=abc  errorMessage="solver timeout"
```

 

   

 

 | Event | When it fires | Payload fields |
|---|---|---|
| `<a href="/docs/cloud-browser-api/cdp-reference/Antibot#event-captchaDetected">Antibot.captchaDetected</a>` | Browser recognized a captcha widget in any frame of the page | `detectionId`, `type`, `frameUrl`, `siteKey?`, `captchaUrl?` |
| `<a href="/docs/cloud-browser-api/cdp-reference/Antibot#event-captchaSolvingStarted">Antibot.captchaSolvingStarted</a>` | Browser began driving the solve (interaction started, or token resolution in progress) | `detectionId`, `type`, `method` (`slider` \| `checkbox` \| `token`) |
| `<a href="/docs/cloud-browser-api/cdp-reference/Antibot#event-captchaSolved">Antibot.captchaSolved</a>` | Challenge completed successfully | `detectionId`, `type`, `method`, `token?` (populated for token-based solves) |
| `<a href="/docs/cloud-browser-api/cdp-reference/Antibot#event-captchaError">Antibot.captchaError</a>` | Challenge could not be solved (timeout, missing key, DOM gone, upstream error) | `detectionId`, `type`, `errorMessage` |

> **Terminal failure:** When `captchaError` fires, the browser does *not* retry automatically and you should not retry the same `detectionId` either. The page has already consumed its one attempt, and most antibot vendors penalize rapid repeat submissions. Treat the failure as the signal that *this session* cannot progress past that challenge. Close the session and open a fresh one (new IP, new fingerprint) to try again.

## Method Reference

### `Antibot.captchaEnable`

 Enables automatic captcha detection AND solving. While enabled, the browser scans the frame tree after each navigation, emits `captchaDetected` for recognized challenges, and then immediately drives the solve. No-op if already enabled.

- **Parameters:** none
- **Returns:** empty object
 
### `Antibot.captchaDisable`

 Disables captcha detection. The session history of detected captchas (and their solve / error outcomes) is preserved. Retrieve it with `getSolvedCaptchas`. Events already in flight from `captchaEnable` may still arrive after the disable call.

- **Parameters:** none
- **Returns:** empty object
 
### `Antibot.solveCaptcha`

 Manually request a solve, either for a specific `detectionId` or, if omitted, for the most recent unsolved detection. Most integrations do not need this. `captchaEnable` already runs the solve automatically. Use `solveCaptcha` only when you need explicit control (e.g. waiting for user confirmation before spending an API credit on a token solve).

- **Parameters:**
    - `detectionId` *(string, optional)*: id from a prior `captchaDetected` event
    - `timeout` *(integer, optional, default 120)*: seconds to wait for a token-based solve to complete
- **Returns:** `{ detectionId, type, method, token? }`
 
### `Antibot.getSolvedCaptchas`

 Returns the full list of captchas seen this session, including failures and in-flight records. Preserved across `captchaDisable` so billing / telemetry can retrieve it at shutdown time.

 ```
{
    "records": [
        {
            "detectionId": "550e8400-e29b-41d4-a716-446655440000",
            "type": "turnstile_checkbox",
            "frameUrl": "https://example.com/",
            "status": "solved",
            "detectedAt": 1714000000000,
            "resolvedAt": 1714000002400,
            "method": "checkbox"
        },
        {
            "detectionId": "6a9f1d2b-8c1f-4ed4-9f11-2f0e5b7a0c3e",
            "type": "recaptcha",
            "frameUrl": "https://example.com/checkout",
            "status": "failed",
            "detectedAt": 1714000010500,
            "resolvedAt": 1714000130500,
            "errorMessage": "solver timeout"
        }
    ]
}
```

 

   

 

 See the [full `CaptchaRecord` schema](https://scrapfly.io/docs/cloud-browser-api/cdp-reference/Antibot#type-CaptchaRecord) for every field.

## Error Handling &amp; Retry Policy

 `captchaError` is the only failure signal you receive. The `errorMessage` field carries a human-readable reason that's safe to log and surface to operators:

 | Typical `errorMessage` | Likely cause | Suggested remediation |
|---|---|---|
| `element not found` / `DOM element disappeared` | Page mutated the captcha widget out of existence (SPA route change, overlay removed) before the solver could act. | Treat as a soft failure. Reload the page or restart the flow from a higher level. |
| `timeout after Ns` | The solve took longer than the configured timeout (default 120 seconds). | Open a fresh session. Slow challenges almost always indicate the page is already flagged. |
| `solver unavailable` | The built-in solver pipeline could not complete the challenge (transient internal condition). | Retry on a fresh session. If it persists across sessions, contact support. |

> **Do not loop on failure.** Repeatedly calling `solveCaptcha` on a failed detection, or re-submitting the form to re-trigger the challenge, increases your block score with most antibot vendors and *does not* increase your success rate. The correct recovery is a new session.

## Billing

 Each successfully solved captcha is billed as a flat number of API credits, added on top of the usual session-time and bandwidth charges. The per-type price is shown in the [Supported Captcha Types](#supported-captchas) table above. Session time and bandwidth continue to accrue while a solve is in progress, so a token-based solve will extend the session-time line on your invoice by the time it takes to complete.

See [Cloud Browser Billing](https://scrapfly.io/docs/cloud-browser-api/billing) for session-time and bandwidth pricing.

## When to use Unblock API vs Captcha Solver

 Both tools deal with anti-bot challenges but at different points in the session lifecycle. They are not alternatives. In most real-world flows you will use **both** on the same session.

### Use [Unblock API](https://scrapfly.io/docs/cloud-browser-api/unblock) when:

- The site shows a **full-page anti-bot wall** before rendering anything useful (Cloudflare interstitial, "Checking your browser...", JavaScript challenges).
- You need a browser that is **already past** the initial bot check when your code connects. You want to start clicking and filling forms immediately, not wait for a challenge to resolve.
- The bypass is a one-time front-door problem. Once you are in, you only interact with regular pages.
- You are on a heavily protected site where a residential IP is required for the bypass to succeed.
 
### Use the Captcha Solver when:

- A captcha widget **appears mid-session** in response to a specific action: submitting a form, adding an item to cart, logging in, hitting a rate-limited endpoint.
- The front door was clear (or already handled by Unblock) but a protected action triggers a step-up challenge.
- You run long-lived browser sessions where captchas can appear at any point and you do not want to orchestrate them manually.
- You want structured events (`captchaDetected` / `captchaSolved`) so your code can react to the outcome, for example, to pause UI, retry a form submit, or rotate sessions on failure.
 
### Use both together when:

- The site has *both* a front-door anti-bot wall *and* step-up captchas deeper in the flow (typical for e-commerce checkout, ticketing, streaming platforms).
- Open the session with Unblock API to land on a usable page, then call `Antibot.captchaEnable` once so any captcha that appears later is handled without extra wiring.
 
  **Rule of thumb:** If the challenge is *blocking page render*, use Unblock. If the challenge appears *after* the page has rendered, use the Captcha Solver. Not sure which one you will hit? Use both. Neither costs anything extra when nothing fires. 

### Full comparison

Three Scrapfly features interact with anti-bot challenges. They are complementary, not alternatives:

 | Feature | Runs on | Handles | Best for |
|---|---|---|---|
| [ASP](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) | Every scrape request | Fingerprinting, TLS, headers, background JS challenges (Cloudflare IUAM, Akamai) | Solving challenges *before* the page renders, on single-request scrapes |
| [Unblock API](https://scrapfly.io/docs/cloud-browser-api/unblock) | Cloud Browser open | Full ASP bypass + navigation through residential proxy, hands you a browser already past the wall | Post-bypass interaction (clicks, forms) on heavily protected sites |
| **Captcha Solver** (this page) | Any live Cloud Browser session | Interactive captcha widgets that appear *during* the session (Turnstile, reCAPTCHA, GeeTest, PerimeterX, and more) | Long-running sessions where a captcha can appear mid-flow (checkout, login, rate-limited navigation) |

  **Combine freely:** Open a session with `Unblock API` to clear the initial wall, then call `Antibot.captchaEnable` so any captcha that appears later (e.g. at checkout) is handled transparently. ASP, Unblock, and the Captcha Solver compose. They don't compete. 

## Related Documentation

- [Antibot CDP Reference](https://scrapfly.io/docs/cloud-browser-api/cdp-reference/Antibot): full method and event schemas
- [Unblock API](https://scrapfly.io/docs/cloud-browser-api/unblock): automatic bypass at session-open time
- [Native Browser MCP](https://scrapfly.io/docs/cloud-browser-api/mcp): captcha solver is auto-enabled for MCP sessions
- [Human-in-the-Loop](https://scrapfly.io/docs/cloud-browser-api/human-in-the-loop): take manual control when automated solving isn't an option
- [Billing](https://scrapfly.io/docs/cloud-browser-api/billing): understand session costs