# CaptchaSonic — Full LLM Reference (llms-full) > CaptchaSonic is an AI-powered CAPTCHA solving API for developers. It bypasses reCAPTCHA v2/v3/Enterprise, hCaptcha, Cloudflare Turnstile, GeeTest, AWS WAF, DataDome, and other anti-bot challenges via a single HTTP endpoint. Solve time depends on the method: image-recognition tasks (OCR, grid, slide) return in roughly 1–3s; token tasks that drive browser automation (reCAPTCHA, hCaptcha, Turnstile, DataDome) typically take ~3–29s end-to-end depending on the captcha (see per-captcha speeds in the Pricing & Benchmarks section below). API response latency for submitting a task is <0.5s. Official Python, Node.js, and Go SDKs (plus C#, Java, and PHP), an agent-native MCP server, an official Claude Code skill plugin (`/plugin install captchasonic`), drop-in 2Captcha/CapSolver migration, plus adapters for Selenium, Playwright, and Puppeteer. This file is the **expanded LLM grounding bundle**. Unlike `llms.txt` (which is a curated link index), `llms-full.txt` inlines the full markdown bodies of the SDK pages, the AI Agents / MCP page, and the agent-capability summary so an agent can answer almost any setup or integration question from this single fetch. For everything else, fetch the canonical pages linked from `/llms.txt` or any docs page (every docs URL is also reachable as `.md` for clean markdown). ## How to use this file - Drop the full text into your model's context, or fetch sections by heading. - Each `##
` below corresponds to a canonical docs page; the URL above each section points at the rendered HTML page, and the same content is available as raw markdown by appending `.md` (e.g. `https://captchasonic.com/en/docs/clients-sdks/python.md`). - Code blocks are copy-paste ready. Replace `YOUR_API_KEY` / `sonic_xxx` with a real key from the dashboard. ## Quick Facts - Auth: API key passed as the first SDK argument, or `clientKey` in REST bodies. - REST base: `https://api.captchasonic.com` — three-call lifecycle (`createTask`, `getTaskResult`, `getBalance`) plus `healthCheck`. - MCP packages: `@captchasonic/mcp-server` (Node, binary `sonic-mcp`), `captchasonic-mcp` (Python, run via `uvx captchasonic-mcp`). - SDK packages (separate from MCP): `captchasonic` on PyPI and npm. - Error IDs: 0=success, 1=InvalidApiKey, 2=InsufficientBalance, 3=DailyLimitExceeded, 4=MinuteLimitExceeded, 5=QuotaExceeded, 6=PlanExpired, 12=TaskUnsolvable, 17-19=RateLimit. ## Pricing & Benchmarks Per-captcha pricing and typical end-to-end solve speed. "Token price" is the USD price per 1,000 solves for the token / browser-automation method; "Image price" is the USD price per 1,000 solves for the image-recognition method. "Contact" means by-request pricing; "—" means that method is not offered for that captcha. Speed is the typical end-to-end solve time in seconds (API submit latency itself is <0.5s). | Captcha | Token price (USD / 1k) | Image price (USD / 1k) | Speed | | :--- | :--- | :--- | :--- | | reCAPTCHA v2 | $2.99 | $1.00 | ~12s | | reCAPTCHA v2 Invisible | $2.99 | $1.00 | ~8s | | reCAPTCHA v3 | $1.45 | — | ~3s | | reCAPTCHA Enterprise | $2.99 | $1.00 | ~8s | | hCaptcha | Contact | $0.20 | ~10s | | Cloudflare Turnstile | $1.45 | — | ~13s | | GeeTest | — | $2.99 | ~14s | | Amazon AWS WAF | — | $1.45 | ~21s | | MTCaptcha | $1.45 | — | ~9s | | DataDome | $1.45 | — | ~12s | | Image / Picture Captcha | — | $0.50 | ~3s | | Text / OCR Captcha | — | $0.50 | ~3s | ### CaptchaSonic vs competitors — price per 1k Headline token captchas, CaptchaSonic price vs the four most-mentioned alternatives: - reCAPTCHA v2 per 1k: CaptchaSonic $2.99 vs 2Captcha $2.99, CapSolver $0.90, Anti-Captcha $2.00, CapMonster Cloud $1.00. - hCaptcha per 1k: CaptchaSonic Contact vs 2Captcha $2.99, CapSolver $1.20, Anti-Captcha $2.00, CapMonster Cloud $1.50. - Cloudflare Turnstile per 1k: CaptchaSonic $1.45 vs 2Captcha $1.99, CapSolver $0.80, Anti-Captcha $1.50, CapMonster Cloud $0.80. Competitor figures are public-pricing estimates; verify with each provider. ## Capabilities — Agent Summary URL: https://captchasonic.com/en/docs/clients-sdks (capability matrix lives on the SDKs hub; a dedicated /capabilities page is planned). > Placeholder section — the dedicated `capabilities` page does not exist yet. The summary below is the agent-friendly view that should appear there. CaptchaSonic exposes a single solve surface to agents with two output shapes: - **Token CAPTCHAs** — agent supplies `website_url` + `website_key`; CaptchaSonic returns `result["token"]` ready to drop into the page's hidden `g-recaptcha-response` / `cf-turnstile-response` field. Examples: reCAPTCHA v2/v3/Enterprise, Cloudflare Turnstile, Cloudflare Challenge (needs proxy), hCaptcha (token mode), MTCaptcha (proxyless), GeeTest token. - **Image / interactive CAPTCHAs** — agent supplies image bytes (or URL) + a question prompt; CaptchaSonic returns `result["typed_solution"]` describing what to do: grid indices to click, slide offset in pixels, text answer (OCR), or x/y click coordinates. Examples: reCAPTCHA v2 image grid, hCaptcha image grid, AWS WAF grid, TikTok (click / whirl / slide), Binance (grid / slide), GeeTest v3/v4 (click / slide / nine-grid / match), BLS OCR, image-to-text, slide puzzle. Agent decision rule: if you have only the page URL + site key, use a **token** method; if you can screenshot or download the challenge image(s), use the matching **image** method and act on `typed_solution`. Account guards every agent should call before a batch: - `health_check` — no API key required, verifies connectivity. - `get_balance` — returns USD balance, gate jobs when balance is low. --- ## Python SDK URL: https://captchasonic.com/en/docs/clients-sdks/python Markdown: https://captchasonic.com/en/docs/clients-sdks/python.md The official **CaptchaSonic Python SDK** turns every supported CAPTCHA into a single function call. It ships with both a synchronous (`CaptchaSonic`) and an asynchronous (`AsyncCaptchaSonic`) client, talks to our infrastructure over **gRPC by default** (with an optional HTTP transport), and includes full type hints, automatic retries for transient errors, and built-in polling for token-style challenges. --- ### Installation ```bash pip install captchasonic ``` The gRPC transport is installed by default. To also use the optional HTTP/JSON transport, install the extra: ```bash pip install "captchasonic[http]" ``` > [!TIP] > The SDK supports **Python 3.10, 3.11, 3.12, and 3.13** and is published under the MIT license. --- ### Authentication You need a CaptchaSonic API key. Create an account and grab your key from the [dashboard](/app), then top up your balance from [Add funds](/docs/guides/add-funds). Pass the key as the first positional argument to the client: ```python from captchasonic import CaptchaSonic solver = CaptchaSonic("YOUR_API_KEY") ``` > [!WARNING] > Treat your API key like a password. Keep it out of source control — load it from an environment variable or a secrets manager instead of hard-coding it. ```python import os from captchasonic import CaptchaSonic solver = CaptchaSonic(os.environ["CAPTCHASONIC_API_KEY"]) ``` --- ### Quick Start Most token-style CAPTCHAs (reCAPTCHA, Turnstile, hCaptcha) are solved with a single call. The client polls for you and returns the token once the task is ready. ```python from captchasonic import CaptchaSonic solver = CaptchaSonic("YOUR_API_KEY") result = solver.solve_recaptcha_v2_token( website_url="https://example.com/login", website_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", ) print(result["token"]) ### 03AGdBq25SxXT... ← drop this into the g-recaptcha-response field ``` > Returns `result["token"]` — submit it as the page's `g-recaptcha-response`. Token-style methods poll for up to 120 seconds by default before timing out (see [Configuration](#configuration)). --- ### Supported CAPTCHA Types The SDK splits methods into two families: - **Token methods** (`*_token`, `solve_turnstile`, `solve_cloudflare`) — you supply a `website_url` / `website_key`, the SDK polls our infrastructure and returns a ready-to-submit `result["token"]`. - **Image / interactive methods** — you supply the challenge images yourself, and the SDK returns a `result["typed_solution"]` describing what to click, drag, or type. All image arguments accept the flexible `ImageInput` type — a file path (`str`), a `pathlib.Path`, raw `bytes`, or an open binary file object. ```python from pathlib import Path ### Any of these work as an item in an `images=[...]` list: Path("captcha.png") # pathlib.Path "./captcha.png" # str path open("captcha.png", "rb").read() # bytes ``` ### reCAPTCHA v2 (token) ```python result = solver.solve_recaptcha_v2_token( website_url="https://example.com", website_key="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", proxy="http://user:pass@host:port", # optional ) token = result["token"] ``` > Returns `result["token"]` — submit it as the page's `g-recaptcha-response`. ### reCAPTCHA v3 (token) ```python result = solver.solve_recaptcha_v3_token( website_url="https://example.com", website_key="6Lc_aCMTAAAAAB...", proxy="http://user:pass@host:port", # optional ) token = result["token"] ``` > Returns `result["token"]` — submit it as the page's `g-recaptcha-response`. ### reCAPTCHA v2 (image grid) When you already have the challenge tiles, solve the grid directly and receive the indices to click. ```python result = solver.solve_recaptcha_v2( images=[Path("tile.png")], # ImageInput list question="traffic lights", # label or /m/... entity id question_type="44", # "split_33" | "33" | "44" ) to_click = result["typed_solution"]["grid"]["objects"] # list[int] ``` > Returns `result["typed_solution"]["grid"]["objects"]` — the list of tile indices to click. ### Cloudflare Turnstile ```python result = solver.solve_turnstile( website_url="https://example.com", website_key="0x4AAAAAAA...", proxy="http://user:pass@host:port", # optional ) token = result["token"] ``` > Returns `result["token"]` — submit it as the form's `cf-turnstile-response`. ### Cloudflare Challenge The full Cloudflare challenge **requires** a proxy. ```python result = solver.solve_cloudflare( website_url="https://example.com", website_key="0x4AAAAAAA...", proxy="http://user:pass@host:port", # required ) token = result["token"] ``` > Returns `result["token"]` — the clearance token for the protected request. ### Popular CAPTCHA (hCaptcha-style image challenges) `solve_popular_captcha` handles the interactive image variants; `solve_popular_captcha_token` returns a token directly. ```python ### Image / interactive variant result = solver.solve_popular_captcha( images=[Path("challenge.png")], question="Select all traffic lights", question_type="grid", # "objectClassify" | "objectClick" | "objectDrag" | "grid" ) to_click = result["typed_solution"]["grid"]["objects"] # list[int] ### Token variant result = solver.solve_popular_captcha_token( website_url="https://example.com", website_key="00000000-0000-0000-0000-000000000000", proxy="http://user:pass@host:port", # optional ) token = result["token"] ``` > The image variant returns `result["typed_solution"]["grid"]["objects"]` (tile indices to click); the token variant returns `result["token"]`. ### GeeTest ```python result = solver.solve_geetest( geetest_type="nine", # "nine" | "click" | "slide" | "match" | "winlinze" question="Select all bicycles", # required for "nine" and "click" images=[Path("tile.png")], # required for "nine", "click", "slide" ) solution = result["typed_solution"] # structure varies by geetest_type ``` > Returns `result["typed_solution"]` — the action to perform, shaped by `geetest_type`. ### AWS WAF ```python result = solver.solve_aws_waf( images=[Path("grid.png")], question="grid:vehicles:cars", ) to_click = result["typed_solution"]["grid"]["objects"] # list[int] ``` > Returns `result["typed_solution"]["grid"]["objects"]` — the list of tile indices to click. ### Image-to-text (OCR) ```python result = solver.solve_ocr( images=[Path("captcha.png")], module="common", # "common" | "mtcaptcha" | "bls" | "morocco" numeric=False, # expect only digits case_sensitive=True, # preserve letter case min_length=4, max_length=8, ) text = result["typed_solution"]["text"]["texts"][0] # str ``` > Returns `result["typed_solution"]["text"]["texts"][0]` — the recognized text to type in. ### Slide puzzle Pass the background and the puzzle piece; you get back the horizontal pixel offset to slide. ```python result = solver.solve_slide_image( images=[Path("background.png"), Path("piece.png")], ) offset_x = result["typed_solution"]["slide"]["x"] # float (pixels) ``` > Returns `result["typed_solution"]["slide"]["x"]` — the horizontal pixel offset to drag the piece. ### TikTok ```python result = solver.solve_tiktok( type="whirl", # "click" | "whirl" | "slide" images=[Path("outer.png")], examples=[Path("inner.png")], # required for "whirl" and "slide" ) solution = result["typed_solution"] ``` > Returns `result["typed_solution"]` — the action to perform, shaped by `type`. ### Binance ```python result = solver.solve_binance( type="grid", # "grid" | "slide" question="Select all bicycles", # required for "grid" images=[Path("grid.png")], ) solution = result["typed_solution"] ``` > Returns `result["typed_solution"]` — the action to perform, shaped by `type`. --- ### Async Usage For high-concurrency workloads (FastAPI handlers, Scrapy spiders, asyncio pipelines) use `AsyncCaptchaSonic`. It mirrors the synchronous API exactly, but every solve method is awaitable. Use it as an async context manager so the underlying channel is cleaned up automatically. ```python import asyncio from captchasonic import AsyncCaptchaSonic async def main(): async with AsyncCaptchaSonic("YOUR_API_KEY") as solver: result = await solver.solve_turnstile( website_url="https://example.com", website_key="0x4AAAAAAA...", ) print(result["token"]) asyncio.run(main()) ``` The synchronous client supports the context-manager protocol too: ```python with CaptchaSonic("YOUR_API_KEY") as solver: result = solver.solve_ocr(images=[Path("captcha.png")]) print(result["typed_solution"]["text"]["texts"][0]) ``` --- ### Proxy Support Token methods accept an optional `proxy` argument (required for `solve_cloudflare`). Use a standard proxy URL: ```python proxy = "http://user:pass@host:port" result = solver.solve_recaptcha_v2_token( website_url="https://example.com", website_key="6Le-...", proxy=proxy, ) ``` > [!TIP] > Supplying a proxy lets our solver mirror your request's geographic location and IP reputation, which improves success rates on sites with strict anti-bot rules. --- ### Configuration All options are passed to the client constructor and apply to both the sync and async clients. ```python solver = CaptchaSonic( "YOUR_API_KEY", transport="grpc", # "grpc" (default) or "http" url="api.captchasonic.com:443", # endpoint override (optional) timeout=30.0, # per-call timeout, seconds polling_interval=2.0, # seconds between task polls polling_timeout=120.0, # max wait for a token task, seconds secure=True, # use TLS for gRPC ) ``` | Option | Default | Description | | :--- | :--- | :--- | | `transport` | `"grpc"` | Wire protocol. `"grpc"` sends images with zero base64 overhead; `"http"` (requires the `[http]` extra) sends REST/JSON with base64-encoded images. | | `url` | `api.captchasonic.com:443` | Override the API endpoint (e.g. for self-hosted or staging). | | `timeout` | `30.0` | Per-call network timeout, in seconds. | | `polling_interval` | `2.0` | Seconds between polls while waiting for a token task. | | `polling_timeout` | `120.0` | Maximum seconds to wait for a token task before raising. | | `secure` | `True` | Use TLS for the gRPC channel. | Transient gRPC errors are retried automatically (up to 3 attempts) with exponential backoff, so you only need to handle real business errors. --- ### Error Handling All SDK errors inherit from `SonicError`, so you can catch everything with one `except` clause or branch on the specific subclass. Each error also carries a numeric `error_id`. ```python from captchasonic.exceptions import ( SonicError, InvalidApiKeyError, InsufficientBalanceError, ) try: result = solver.solve_turnstile( website_url="https://example.com", website_key="0x4AAAAAAA...", ) except InsufficientBalanceError: print("Top up your balance to continue.") except InvalidApiKeyError: print("Check your API key.") except SonicError as err: print(f"Solve failed (error_id={err.error_id}): {err}") ``` | `error_id` | Exception | Cause | Action | | :--- | :--- | :--- | :--- | | 1 | `InvalidApiKeyError` | API key is missing or invalid. | Verify the key in your [dashboard](/app). | | 2 | `InsufficientBalanceError` | Account balance can't cover the task. | [Add funds](/docs/guides/add-funds). | | 3 | `DailyLimitExceededError` | Daily quota exhausted. | Wait for the daily reset or upgrade your plan. | | 4 | `MinuteLimitExceededError` | Per-minute rate limit hit. | Slow down requests / add backoff. | | 5 | `QuotaExceededError` | Plan quota exhausted. | Upgrade your plan. | | 6 | `PlanExpiredError` | Subscription has expired. | Renew your subscription. | --- ### Account Helpers ```python balance = solver.get_balance() # current balance in USD (float) print(f"Balance: ${balance:.2f}") health = solver.health_check() # HealthCheckResponse — verifies connectivity ``` Use `health_check()` as a lightweight readiness probe in services and `get_balance()` to gate jobs before you start spending credits. --- ### Troubleshooting > [!TIP] > **`ModuleNotFoundError` when using HTTP transport.** The HTTP client depends on `httpx`, which is an optional extra. Install it with `pip install "captchasonic[http]"` and set `transport="http"`. - **A token task raises after ~120 seconds.** That's the `polling_timeout`. Increase it for slow targets, e.g. `CaptchaSonic(key, polling_timeout=240.0)`. - **`solve_cloudflare` fails immediately.** The `proxy` argument is required for the Cloudflare challenge — supply a working proxy URL. - **gRPC connection errors behind a corporate proxy/firewall.** gRPC needs HTTP/2 over port 443. If your network blocks it, switch to `transport="http"`. - **Image methods return indices, not a token.** Interactive methods (`solve_recaptcha_v2`, `solve_popular_captcha`, `solve_aws_waf`, `solve_geetest`, etc.) return `result["typed_solution"]` describing the action to take; only `*_token`, `solve_turnstile`, and `solve_cloudflare` return `result["token"]`. --- ### Resources - [PyPI package](https://pypi.org/project/captchasonic/) - [REST API reference](/docs/api) --- ## Node.js SDK URL: https://captchasonic.com/en/docs/clients-sdks/nodejs Markdown: https://captchasonic.com/en/docs/clients-sdks/nodejs.md The CaptchaSonic Node.js SDK (`captchasonic`) is a modern, Promise-based, TypeScript-first library for solving CAPTCHAs at scale. Every method returns a `Promise`, ships full type definitions, and runs over three interchangeable transports — native **gRPC** (fastest, Node.js only), **ConnectRPC** (works in Node.js and browsers), and plain **HTTP/JSON**. Transient errors are retried automatically with exponential backoff. It works in **Node.js ≥ 18** and modern browsers, and is compatible with Express, Fastify, Next.js, React, Vue, and Vite. --- ### Installation ```bash npm install captchasonic ### or yarn add captchasonic ### or pnpm add captchasonic ``` **Requirements** | Requirement | Notes | |---|---| | Node.js | ≥ 18.0.0 (required for the `grpc` transport) | | Module format | ES Module — the package ships `"type": "module"` | | Browser | Any modern browser with `fetch`; use the `connect` or `http` transport | The package is published as **ESM only**. In an ESM project (`"type": "module"` in your `package.json`, or a `.mjs` file) import it directly: ```javascript import { CaptchaSonic } from "captchasonic"; ``` From a CommonJS file, load it with a dynamic `import()`: ```javascript // CommonJS (.cjs / "type": "commonjs") const { CaptchaSonic } = await import("captchasonic"); ``` > [!TIP] > If you are on TypeScript, set `"module": "NodeNext"` (or `"ESNext"`) and `"moduleResolution": "NodeNext"` in `tsconfig.json` so the bundled type definitions resolve correctly. --- ### Authentication Create an API key in the [CaptchaSonic dashboard](https://captchasonic.com) and pass it as the first argument to the constructor: ```javascript import { CaptchaSonic } from "captchasonic"; const solver = new CaptchaSonic("YOUR_API_KEY"); ``` Never hard-code keys in source control. Read the key from the environment instead: ```javascript import { CaptchaSonic } from "captchasonic"; const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY); ``` --- ### Quick Start Each captcha type has a dedicated `solve*` helper that submits the task and resolves with the result. There is no separate polling step for image tasks — the SDK handles it for you. ```javascript import { CaptchaSonic } from "captchasonic"; const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY); const result = await solver.solveRecaptchaV2({ images: tiles, // Uint8Array[] | Buffer[] | file-path[] question: "traffic lights", }); // Grid selections come back as tile indices console.log(result.typedSolution?.grid?.objects); // e.g. [2, 4, 7] ``` > **Returns:** image methods resolve a result whose answer lives under `typedSolution` (here `typedSolution.grid.objects`, the selected tile indices); token methods return the token in the `solution` map. > [!TIP] > Token-based methods (Turnstile, Cloudflare, reCAPTCHA v2/v3 token, popular-captcha token) submit a browser-automation task and poll internally until a token is ready — by default up to 120 seconds. --- ### Supported CAPTCHA Types All image methods take a single typed options object. Images may be `Uint8Array`, Node `Buffer`, or a string file path (file paths are Node.js only). ### reCAPTCHA v2 (image) ```javascript await solver.solveRecaptchaV2({ images: tiles, // typically 9 tiles for a 3×3 grid question: "traffic lights", // plain text, or a Google class code like "/m/015qff" }); // → result.typedSolution.grid.objects (number[] — selected tile indices) ``` ### PopularCaptcha (hCaptcha-style image) ```javascript await solver.solvePopularCaptcha({ images: tiles, // 1–64 tiles question: "Click each image with a cat", questionType: "objectClassify", // "objectClassify" | "grid" | "objectClick" | "objectDrag" examples, // optional reference images for objectClick websiteURL: "https://example.com", }); // objectClassify/grid → typedSolution.grid.objects // objectClick → typedSolution.click // objectDrag → typedSolution.drag ``` ### GeeTest ```javascript // nine-grid (question + images required) await solver.solveGeetest({ type: "nine", question: "Select all bicycles", images: tiles }); // click / icon (question + images required) await solver.solveGeetest({ type: "click", question: "the bear", images: tiles }); // slide puzzle (piece + background) await solver.solveGeetest({ type: "slide", images: [piece], examples: [background] }); // swap puzzles await solver.solveGeetest({ type: "match" }); await solver.solveGeetest({ type: "winlinze" }); ``` Returns: grid/click types land in `typedSolution.grid.objects` (or `typedSolution.click`); slide returns `typedSolution.slide.x`. Accepted `type` aliases: | Canonical | Aliases | |---|---| | nine-grid | `"nine"`, `"geetest_nine"`, `"9"` | | click / icon | `"click"`, `"geetest_click"`, `"icon"` | | slide | `"slide"`, `"geetest_slide"` | | match | `"match"`, `"geetest_match"` | | winlinze | `"winlinze"`, `"geetest_winlinze"` | ### OCR / image-to-text ```javascript await solver.solveOcr({ images: [img] }); // general OCR await solver.solveOcr({ images: [img], module: "mtcaptcha", maxLength: 4 }); await solver.solveOcr({ images: imgs, module: "bls", numeric: true, maxLength: 3 }); // → result.typedSolution.text.texts[0] ``` | Option | Type | Notes | |---|---|---| | `module` | `"common"` \| `"mtcaptcha"` \| `"bls"` \| `"morocco"` | Default `"common"` | | `numeric` | `boolean` | Digits only (auto-set for `"bls"`) | | `caseSensitive` | `boolean` | Preserve letter case | | `minLength` / `maxLength` | `number` | Length bounds | ### TikTok ```javascript await solver.solveTikTok({ type: "click", question: "Select the shape", images }); await solver.solveTikTok({ type: "whirl", question: "Rotate to match", images, examples }); // examples required await solver.solveTikTok({ type: "slide", question: "Slide to fit", images, examples }); // examples required ``` Returns: `click` lands in `typedSolution.click`; `whirl`/`slide` return `typedSolution.slide.x`. `type` accepts `"click"`/`"tiktok_click"`, `"whirl"`/`"tiktok_whirl"`, `"slide"`/`"tiktok_slide"`. ### Binance ```javascript await solver.solveBinance({ type: "grid", question: "Select the bicycle", images }); await solver.solveBinance({ type: "slide", images: [puzzle], examples: [background] }); ``` Returns: `grid` lands in `typedSolution.grid.objects`; `slide` returns `typedSolution.slide.x`. `type` accepts `"grid"`/`"binance_grid"` and `"slide"`/`"binance_slide"`. ### AWS WAF `solveAwsWaf` takes positional arguments. The `question` is formatted as `"type:category:target"`. ```javascript await solver.solveAwsWaf(tiles, "grid:vehicles:cars"); ``` Returns: selected tile indices in `typedSolution.grid.objects`. ### Slide image (local, no AI) Detects the slide offset locally using contour detection. Accepts one combined image, or `[background, piece]`. ```javascript const r = await solver.solveSlideImage({ images: ["slide_bg.png", "piece.png"] }); console.log(r.typedSolution?.slide?.x); // pixel offset, e.g. 142 ``` Returns: the slide offset in pixels at `typedSolution.slide.x`. ### Token methods (browser automation) These submit a task and poll internally until a token is returned (up to the polling timeout, 120s by default). ```javascript await solver.solveTurnstile({ websiteURL, websiteKey, proxy }); // proxy optional await solver.solveRecaptchaV2Token({ websiteURL, websiteKey, proxy }); // proxy optional await solver.solveRecaptchaV3Token({ websiteURL, websiteKey, proxy }); // proxy optional await solver.solvePopularCaptchaToken({ websiteURL, websiteKey, proxy, metadata }); // proxy optional await solver.solveCloudflare({ websiteURL, websiteKey, proxy }); // proxy REQUIRED ``` Returns: the token in the `solution` map of the response (for example `result.solution.token` or `result.solution.gRecaptchaResponse`, depending on the captcha). --- ### TypeScript Usage The SDK exports types for every option object and response. Import them with `import type`. ```typescript import { CaptchaSonic } from "captchasonic"; import type { SolveGeetestOptions, GetTaskResultResponse } from "captchasonic"; const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY!); const opts: SolveGeetestOptions = { type: "nine", question: "Select all bicycles", images: tiles, }; const result = await solver.solveGeetest(opts); console.log(result.typedSolution?.grid?.objects); ``` **Exported types** ```typescript import type { CaptchaSonicOptions, ImageInput, SolvePopularCaptchaOptions, SolveRecaptchaV2Options, SolveGeetestOptions, SolveOcrOptions, SolveTikTokOptions, SolveBinanceOptions, SolveTurnstileOptions, SolvePopularCaptchaTokenOptions, SolveRecaptchaV2TokenOptions, SolveRecaptchaV3TokenOptions, SolveCloudflareOptions, SolveSlideImageOptions, GeetestSubtype, TikTokSubtype, BinanceSubtype, Task, CreateTaskResponse, GetTaskResultResponse, } from "captchasonic"; ``` `ImageInput` is `Uint8Array | Buffer | string`. --- ### Proxy Support Token / browser-automation methods accept an optional `proxy` string in the form `http://user:pass@host:port`: ```javascript await solver.solveTurnstile({ websiteURL: "https://example.com", websiteKey: "0x4AAAAAAA...", proxy: "http://user:pass@1.2.3.4:8080", }); ``` > [!WARNING] > `solveCloudflare` **always requires** a proxy — the `proxy` field is mandatory for that method. Other token methods run proxyless when `proxy` is omitted. For enterprise hCaptcha you can also pass `metadata` (`rqdata`, `rqtoken`, `fingerprint`) to `solvePopularCaptchaToken`. --- ### Configuration Pass an options object as the second constructor argument. Only the options below are supported. ```typescript const solver = new CaptchaSonic("YOUR_API_KEY", { transport: "connect", // "grpc" (default) | "connect" | "http" timeout: 180_000, // max poll wait in ms (alias: timeoutMs); per-call default 30000 pollingInterval: 5_000, // polling frequency in ms (default 2000) baseUrl: "https://api.captchasonic.com", // override endpoint (alias: url) }); ``` | Option | Type | Default | Description | |---|---|---|---| | `transport` | `"grpc"` \| `"connect"` \| `"http"` | `"grpc"` | Wire protocol (see table below) | | `timeout` / `timeoutMs` | `number` | `30000` per call | Request timeout; `timeout` also caps polling wait | | `pollingInterval` | `number` | `2000` | How often token tasks are polled | | `url` / `baseUrl` | `string` | per-transport | Override the API endpoint | **Transports** | Transport | Environments | Protocol | |---|---|---| | `grpc` | Node.js only | gRPC binary over HTTP/2 — lowest latency, sends images as raw binary | | `connect` | Node.js and browsers | ConnectRPC over `fetch` | | `http` | Node.js and browsers | Plain REST/JSON over `fetch` | > [!TIP] > In the browser use `connect` (recommended) or `http`. Native gRPC requires Node.js. With `connect`/`http`, images are auto-encoded to base64 before sending; with `grpc` they are sent as raw binary with zero overhead. --- ### Error Handling All API-level failures throw a `SonicError`, which extends the built-in `Error`. It carries a numeric `errorId` and sets `name` to the matching error name. ```typescript import { CaptchaSonic, SonicError } from "captchasonic"; try { const result = await solver.solveGeetest({ type: "nine", question: "bicycles", images }); } catch (err) { if (err instanceof SonicError) { console.error(err.errorId); // 1–6 console.error(err.name); // e.g. "InvalidApiKeyError" console.error(err.message); } else { throw err; // network / unexpected } } ``` | `errorId` | `name` | Cause | Action | |---|---|---|---| | 1 | `InvalidApiKeyError` | API key missing or invalid | Check the key from your dashboard | | 2 | `InsufficientBalanceError` | Not enough credits | Top up your balance | | 3 | `DailyLimitExceededError` | Daily quota exceeded | Wait for daily reset or raise your plan | | 4 | `MinuteLimitExceededError` | Per-minute rate limit hit | Back off and retry shortly | | 5 | `QuotaExceededError` | Plan quota exhausted | Upgrade your plan | | 6 | `PlanExpiredError` | Subscription expired | Renew your subscription | > [!TIP] > Transient gRPC errors are retried automatically with exponential backoff (up to 3 attempts), so you usually only need to handle the `SonicError` cases above. --- ### Account Helpers ```javascript const balance = await solver.getBalance(); // → number (USD) const health = await solver.healthCheck(); // → { healthy: boolean, version: string } ``` Low-level task methods are available if you need direct control over submission and polling: ```javascript const created = await solver.createTask(task); // submit a Partial const result = await solver.getTaskResult(taskId); // poll for a result ``` --- ### Troubleshooting **`require is not defined` / `Cannot use import statement outside a module`** — the package is ESM only. Use `import` in an ESM project, or `await import("captchasonic")` from CommonJS. See [Installation](#installation). **`grpc` transport fails in the browser** — native gRPC is Node.js only. Switch to `transport: "connect"` or `transport: "http"`. **`InvalidApiKeyError` on every call** — confirm the key is passed as the first constructor argument and not accidentally `undefined` (e.g. a missing env var). **Token method times out** — token tasks poll up to `timeout` ms (default 120000). Increase `timeout` and verify the `websiteURL` / `websiteKey` match the target page. For Cloudflare, a valid `proxy` is required. **File-path images don't load** — string file paths are read synchronously and are Node.js only; in the browser pass a `Uint8Array` instead. --- ### Resources * [npm package](https://www.npmjs.com/package/captchasonic) * [API reference](/docs/api) * [CaptchaSonic dashboard & docs](https://captchasonic.com) --- ## Go SDK URL: https://captchasonic.com/en/docs/clients-sdks/go Markdown: https://captchasonic.com/en/docs/clients-sdks/go.md Our Go SDK is designed for developers building concurrent scrapers and distributed automation workers. It leverages Go's concurrency primitives to provide a safe and efficient interface to our API. --- ### Installation ```bash go get github.com/Captcha-Sonic/captchasonic-go ``` --- ### Implementation A robust example using context for timeout management. ```go package main import ( "context" "fmt" "time" "github.com/Captcha-Sonic/captchasonic-go" ) func main() { // 1. Create client client := captchasonic.NewClient("YOUR_API_KEY") // 2. Define task (proxyless or with proxy) task := captchasonic.RecaptchaV2TaskProxyless{ WebsiteURL: "https://example.com", WebsiteKey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", } // 3. Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() // 4. Submit & Wait taskID, err := client.CreateTask(ctx, task) if err != nil { panic(err) } result, err := client.WaitForResult(ctx, taskID) if err != nil { panic(err) } if result.Status == "ready" { fmt.Printf("Solved: %s\n", result.Solution.GRecaptchaResponse) } } ``` --- ### Advanced Features ### Custom HTTP Client You can inject a custom `http.Client` for specific proxy or TLS requirements. ```go customClient := &http.Client{Timeout: 30 * time.Second} client := captchasonic.NewClientWithHTTP("YOUR_API_KEY", customClient) ``` ### Supported Structs The library includes pre-defined structs for: * `RecaptchaV2Task` / `RecaptchaV3Task` * `HCaptchaTask` * `GeeTestTask` * `TurnstileTask` * `ImageToTextTask` --- ### Best Practices 1. **Context Usage**: Always use a context with a timeout to avoid hanging goroutines in case of network instability. 2. **Concurrency**: The `Client` is thread-safe. You can share a single client instance across multiple goroutines. 3. **Error Check**: Always check for `captchasonic.ErrInsufficientFunds` to trigger alerts for topping up your account. --- ### Links * [GoDoc Documentation](https://pkg.go.dev/github.com/Captcha-Sonic/captchasonic-go) * [Examples on GitHub](https://github.com/Captcha-Sonic/captchasonic-go/tree/main/examples) --- ## Java SDK URL: https://captchasonic.com/en/docs/clients-sdks/java Markdown: https://captchasonic.com/en/docs/clients-sdks/java.md Our Java SDK provides a type-safe, thread-safe interface for integrating CaptchaSonic into your Java applications. It is compatible with Java 8+ and integrates seamlessly with popular HTTP clients. --- ### Installation ### Maven Add the following dependency to your `pom.xml`: ```xml com.captchasonic captchasonic-java 1.0.0 ``` ### Gradle ```groovy implementation 'com.captchasonic:captchasonic-java:1.0.0' ``` --- ### Implementation ```java import com.captchasonic.CaptchaSonicClient; import com.captchasonic.models.TaskResult; import com.captchasonic.models.RecaptchaV2Task; public class Example { public static void main(String[] args) { // 1. Initialize Client CaptchaSonicClient client = new CaptchaSonicClient("YOUR_API_KEY"); try { // 2. Create Task RecaptchaV2Task task = new RecaptchaV2Task( "https://example.com", "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" ); // 3. Solve TaskResult result = client.solve(task); if (result.isReady()) { System.out.println("Solution: " + result.getGRecaptchaResponse()); } } catch (Exception e) { e.printStackTrace(); } } } ``` --- ### Links - [Javadoc](https://javadoc.io/doc/com.captchasonic/captchasonic-java) - [GitHub Repository](https://github.com/Captcha-Sonic/captchasonic-java) --- ## C# SDK URL: https://captchasonic.com/en/docs/clients-sdks/csharp Markdown: https://captchasonic.com/en/docs/clients-sdks/csharp.md The CaptchaSonic .NET SDK is a modern, async-first library compliant with .NET Standard 2.0+, making it compatible with .NET Core, .NET Framework, and Xamarin. --- ### Installation Install via NuGet Package Manager: ```bash Install-Package CaptchaSonic.Client ``` Or via .NET CLI: ```bash dotnet add package CaptchaSonic.Client ``` --- ### Implementation ```csharp using CaptchaSonic.Client; using CaptchaSonic.Models; using System; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // 1. Initialize Client var client = new CaptchaSonicClient("YOUR_API_KEY"); try { // 2. Create Task var task = new RecaptchaV2Task { WebsiteUrl = "https://example.com", WebsiteKey = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" }; // 3. Solve var result = await client.SolveAsync(task); if (result.IsReady) { Console.WriteLine($"Token: {result.GRecaptchaResponse}"); } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } ``` --- ### Links - [NuGet Package](https://www.nuget.org/packages/CaptchaSonic.Client) - [GitHub Repository](https://github.com/Captcha-Sonic/captchasonic-dotnet) --- ## PHP SDK URL: https://captchasonic.com/en/docs/clients-sdks/php Markdown: https://captchasonic.com/en/docs/clients-sdks/php.md Our PHP SDK streamlines CaptchaSonic integration for PHP applications. It handles HTTP requests, polling, and error management automatically. --- ### Installation Install using Composer: ```bash composer require captchasonic/captchasonic-php ``` --- ### Implementation ```php 'https://example.com', 'websiteKey' => '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-' ]); // 3. Solve (auto-polling) $solution = $client->solve($task); echo "Token: " . $solution->gRecaptchaResponse; } catch (Exception $e) { echo "Error: " . $e->getMessage(); } ``` --- ### Links - [Packagist](https://packagist.org/packages/captchasonic/captchasonic-php) - [GitHub Repository](https://github.com/Captcha-Sonic/captchasonic-php) --- ## AI Agents & MCP URL: https://captchasonic.com/en/docs/clients-sdks/ai-agents Markdown: https://captchasonic.com/en/docs/clients-sdks/ai-agents.md CaptchaSonic is **agent-native**. Any AI agent can solve CAPTCHAs through our **MCP server** — a single stdio binary that exposes three tools (`health_check`, `get_balance`, `solve_captcha`) over the [Model Context Protocol](https://modelcontextprotocol.io). Because MCP is a universal standard, the same server plugs into Claude Code, Antigravity, Cursor, Windsurf, and any other MCP-compatible client. If your agent can't speak MCP, you can always call the [direct SDK](#without-mcp-direct-sdk) instead. ### Golden Path for Agents Drop this snippet into any agent and it can solve CAPTCHAs in one round trip: ```bash ### Claude Code (or any MCP client): add the server once claude mcp add sonic --env SONIC_API_KEY=sonic_xxx -- sonic-mcp ### Or, with no MCP — same lifecycle via curl (replace TASK_ID after createTask): curl -s https://api.captchasonic.com/createTask -H 'content-type: application/json' -d '{"clientKey":"sonic_xxx","task":{"type":"TurnstileTaskProxyless","websiteURL":"https://example.com","websiteKey":"0x4AAAAAAA..."}}' curl -s https://api.captchasonic.com/getTaskResult -H 'content-type: application/json' -d '{"clientKey":"sonic_xxx","taskId":TASK_ID}' ``` > [!NOTE] > The MCP packages are published as `@captchasonic/mcp-server` (npm) and `captchasonic-mcp` (Python). These are distinct from the SDK packages (`captchasonic` on PyPI / npm). Always confirm the exact package name against the live registry before installing. --- ### Claude Code Add the MCP server with the `claude mcp add` command. Pass your API key through the environment so it never lands in source control: ```bash claude mcp add sonic --env SONIC_API_KEY=sonic_xxx -- sonic-mcp ``` This launches the `sonic-mcp` binary from `@captchasonic/mcp-server`. Install it first with `npm install -g @captchasonic/mcp-server` (or let your runner resolve it). Once added, three tools become available to the agent: - **`health_check`** — verify the API server is up (no API key required). - **`get_balance`** — return the current account balance in USD. - **`solve_captcha`** — submit a CAPTCHA (image, grid, slide, OCR, Geetest, TikTok, Binance, and more) and receive the typed solution. You can also install the **`/sonic:*` skills plugin** for slash-command workflows that wrap the same SDK: ```bash /sonic:solve # solve a CAPTCHA from an image path or URL /sonic:balance # check account credits /sonic:test-sdk # smoke-test the SDK against the live server ``` > [!TIP] > Use `get_balance` as a guard before a batch of solves so the agent can stop early if credits run low. --- ### Antigravity Antigravity speaks the standard MCP protocol, so register CaptchaSonic as a generic **stdio** server in its MCP configuration. Add the following entry: ```json { "mcpServers": { "sonic": { "command": "sonic-mcp", "env": { "SONIC_API_KEY": "sonic_xxx" } } } } ``` After saving, reload Antigravity's MCP servers and the `health_check`, `get_balance`, and `solve_captcha` tools appear in the agent's tool list. --- ### Cursor In Cursor, open **Settings → MCP** (or edit `~/.cursor/mcp.json`) and add the stdio server: ```json { "mcpServers": { "sonic": { "command": "sonic-mcp", "env": { "SONIC_API_KEY": "sonic_xxx" } } } } ``` Restart Cursor's MCP connection. The three CaptchaSonic tools are now callable from the agent. --- ### Windsurf In Windsurf, open **Settings → Cascade → MCP Servers** (or edit `~/.codeium/windsurf/mcp_config.json`) and add the same stdio block: ```json { "mcpServers": { "sonic": { "command": "sonic-mcp", "env": { "SONIC_API_KEY": "sonic_xxx" } } } } ``` Refresh the server list and CaptchaSonic's tools become available to Cascade. --- ### Generic MCP (stdio) Any MCP client accepts the same raw stdio config. Point `command` at the binary and pass `SONIC_API_KEY` via `env`. There are two interchangeable runtimes — pick whichever matches your environment. **Node (`@captchasonic/mcp-server`):** ```json { "mcpServers": { "sonic": { "command": "npx", "args": ["-y", "@captchasonic/mcp-server"], "env": { "SONIC_API_KEY": "sonic_xxx" } } } } ``` **Python (`captchasonic-mcp`):** ```json { "mcpServers": { "sonic": { "command": "uvx", "args": ["captchasonic-mcp"], "env": { "SONIC_API_KEY": "sonic_xxx" } } } } ``` > [!NOTE] > Set `SONIC_BASE_URL` in the same `env` block to point at a self-hosted or staging endpoint (default: `https://api.captchasonic.com`). --- ### n8n CaptchaSonic ships an n8n community node. In your n8n instance go to **Settings → Community Nodes**, install `n8n-nodes-captchasonic`, then create a CaptchaSonic credential with your API key. The node exposes solve and balance operations you can drop into any workflow. --- ### Without MCP (direct SDK) If your agent can't run an MCP server, call the SDK directly. A token-style CAPTCHA is a single function call. **Python:** ```python from captchasonic import CaptchaSonic solver = CaptchaSonic("YOUR_API_KEY") result = solver.solve_turnstile( website_url="https://example.com", website_key="0x4AAAAAAA...", ) print(result["token"]) ``` **Node:** ```javascript import { CaptchaSonic } from "captchasonic" const solver = new CaptchaSonic("YOUR_API_KEY") const result = await solver.solveTurnstile({ websiteUrl: "https://example.com", websiteKey: "0x4AAAAAAA...", }) console.log(result.token) ``` See the [Python SDK](/docs/clients-sdks/python) and [Node.js SDK](/docs/clients-sdks/nodejs) pages for the full method list, or the [REST API reference](/docs/api) for the raw three-call lifecycle.