# YesCaptcha Docs (full text) > YesCaptcha is a captcha recognition API. Send a JSON request with your clientKey and a task (reCAPTCHA v2/v3/Enterprise, hCaptcha, Cloudflare Turnstile, Cloudflare challenge, FunCaptcha, AWS WAF, image-to-text or image recognition) to https://api.yescaptcha.com/createTask, then poll /getTaskResult every 5 seconds (synchronous types return the solution directly). Prices are per task in points (1,000 points = CNY 1); failed and timed-out tasks are refunded. --- # Solve captchas with one JSON API > YesCaptcha is a captcha recognition API. Solve reCAPTCHA, hCaptcha, Cloudflare Turnstile, FunCaptcha, AWS WAF and image captchas through one JSON API, paid per task, with failed and timed-out tasks refunded automatically. Source: https://docs.yescaptcha.com/en/ · Last verified: 2026-10-15 YesCaptcha solves reCAPTCHA, hCaptcha, Cloudflare Turnstile, FunCaptcha, AWS WAF and alphanumeric image captchas. You pay per task in points (1,000 points = ¥1); failed and timed-out tasks are refunded automatically. A browser extension can also complete captchas on web pages for you. [Quickstart](https://docs.yescaptcha.com/en/getting-started/quickstart/)[Browser extension](https://docs.yescaptcha.com/en/extension/) Machine-readable versions:[`llms.txt`](https://docs.yescaptcha.com/llms.txt)[`llms-full.txt`](https://docs.yescaptcha.com/llms-full.txt)[`OpenAPI`](https://docs.yescaptcha.com/openapi.json)[`Markdown`](https://docs.yescaptcha.com/en/index.md) YesCaptcha may only be used for lawful purposes. Any illegal use is prohibited. ## Three steps 1. 1 **Create a task** Send the task type and site parameters to `createTask` to get a `taskId`. Synchronous types, such as image recognition and image-to-text, return the result right away. 2. 2 **Get the result** Call `getTaskResult` every 5 seconds. When `status` is `ready`, the result is in `solution`. 3. 3 **Submit it to the site** Put the token into the page form or request. Tokens are single use; submit within 60 seconds. POST /createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } } ``` POST /getTaskResult ```json { "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "03AGdBq25SxXT-pmSeBXjzScW-EiocHwwpwqtk1QXlJnGnU..." } } ``` ## Supported captchas [reCAPTCHAv2, v3, Enterprise, and v2 image recognitionFrom 6 points](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/)[hCaptchaGet a token, or recognize the images and click them yourselfFrom 8 points](https://docs.yescaptcha.com/en/tasks/hcaptcha/)[Cloudflare TurnstileTurnstile verification tokensFrom 25 points](https://docs.yescaptcha.com/en/tasks/turnstile/)[FunCaptchaArkose Labs tokens and image recognitionFrom 3 points](https://docs.yescaptcha.com/en/tasks/funcaptcha/)[AWS WAF / bCaptchaGrid image recognitionFrom 8 points](https://docs.yescaptcha.com/en/tasks/aws-bcaptcha-classification/)[Image to textAlphanumeric image captchas, returned synchronouslyFrom 2 points](https://docs.yescaptcha.com/en/tasks/image-to-text/) ## Popular pages - [**Task types and pricing**Prices and modes of every public task type](https://docs.yescaptcha.com/en/tasks/) - [**Error codes**What each error means and what to do](https://docs.yescaptcha.com/en/api/errors/) - [**Rate limits**Concurrency limits and automatic pauses](https://docs.yescaptcha.com/en/api/rate-limits/) - [**Billing and refunds**Points, pre-charging, refunds and report refunds](https://docs.yescaptcha.com/en/getting-started/billing/) - [**Contact us**WeChat, QQ, Telegram and email, 9:00–21:00 UTC+8](https://docs.yescaptcha.com/en/help/contact/) - [**Console**Sign up, copy your client key, top up](https://yescaptcha.com/) --- # Introduction > What YesCaptcha is. Solve reCAPTCHA, hCaptcha, Turnstile, FunCaptcha and image captchas through an API or a browser extension, paid per task, with failed tasks refunded automatically. Source: https://docs.yescaptcha.com/en/getting-started/introduction/ · Last verified: 2026-10-15 YesCaptcha is a captcha recognition service. You send the details of a captcha to the YesCaptcha API and get back either a token that you submit to the target site, or the recognition result for an image. It supports reCAPTCHA (v2, v3 and Enterprise), hCaptcha, Cloudflare Turnstile, the Cloudflare challenge page, FunCaptcha, AWS WAF, bCaptcha and alphanumeric image captchas. You pay per task in points (1,000 points = ¥1); failed and timed-out tasks are refunded automatically. YesCaptcha may only be used for lawful purposes. Any illegal use is prohibited. ## Two ways to use it | | API | Browser extension (YesCaptcha Assistant) | | --- | --- | --- | | For | Developers who process captchas in their own code | People who don’t write code and work in a browser | | How | Call `createTask` and `getTaskResult` with your `clientKey` | Install the extension, enter your `clientKey`; captchas are recognized and clicked automatically | | Supports | Every task type listed on this site | Image challenges of reCAPTCHA v2, hCaptcha, FunCaptcha, AWS WAF and bCaptcha, plus text captchas | | Cost | Points per task type | The extension is free; you pay for the API calls it makes | Both use the same account, the same `clientKey` and the same balance. ## Three kinds of results - **Tokens**: most reCAPTCHA, hCaptcha, Turnstile and FunCaptcha task types. You get a string to put into the page’s form or request to pass the check, with no clicking. These are asynchronous: create the task, then check for the result every 5 seconds. - **Image recognition results**: task types ending in `Classification`. You send the challenge images and get back which tiles or positions to click; your own code does the clicking in the browser. These are synchronous: one request returns the result. - **Text or cookies**: image-to-text returns the characters in the image; the Cloudflare challenge page task returns the cookies set after passing the check. All task types and prices: [Task types and pricing](https://docs.yescaptcha.com/en/tasks/). ## Start here [Quickstart](https://docs.yescaptcha.com/en/getting-started/quickstart/)Sign up, copy your clientKey, send your first request [Endpoints](https://docs.yescaptcha.com/en/getting-started/endpoints/)Global and China endpoints [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/)Points, pre-charging, refunds, report refunds [Browser extension](https://docs.yescaptcha.com/en/extension/)Solve captchas in the browser without code ## Community SDKs SDKs contributed by users (unofficial; review them before use) are listed in [Code samples and SDKs](https://docs.yescaptcha.com/en/samples/). --- # Quickstart > Send your first YesCaptcha request in 5 minutes. Sign up, copy your clientKey, top up, then read an image captcha with curl, Python or Node.js (ImageToTextTaskOcrBase, synchronous, 2 points per image). Source: https://docs.yescaptcha.com/en/getting-started/quickstart/ · Last verified: 2026-10-15 This page sends a first request with the simplest task type, `ImageToTextTaskOcrBase`, which reads the letters and digits in an image. It is synchronous (a single `createTask` request returns the result), costs 2 points (¥0.002) per image and needs no third-party site, so it is a good way to check that your account and code work. 1. **Create an account** Sign up and log in at [yescaptcha.com](https://yescaptcha.com/). 2. **Copy your clientKey** On the dashboard ([yescaptcha.com/dashboard.html](https://yescaptcha.com/dashboard.html)), find “Your ClientKey” and click copy. Copy the whole value. Every API request is authenticated with it, so keep it private; if it leaks, reset it in the same place. 3. **Top up** Your balance must be above 10 points to create tasks. Payment methods and VIP bonuses: [Top-up and VIP](https://docs.yescaptcha.com/en/account/recharge/). 4. **Check that the clientKey works** `getBalance` returns your balance and is free: ```bash curl -s https://api.yescaptcha.com/getBalance \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY"}' ``` If you get `{"errorId": 0, "balance": 12345, ...}`, you are ready; `balance` is your remaining points. `ERROR_KEY_DOES_NOT_EXIST` means the key was copied incorrectly. 5. **Read an image** Download the sample image [captcha.jpg](https://docs.yescaptcha.com/samples/captcha.jpg) (or use your own captcha image), put your client key in an environment variable and run one of the scripts: ```bash export YESCAPTCHA_CLIENT_KEY=your_client_key ``` **curl** quickstart.sh ```bash #!/usr/bin/env bash # First request: read an alphanumeric image captcha with ImageToTextTaskOcrBase (synchronous, 2 points per image) # Usage: YESCAPTCHA_CLIENT_KEY=your_client_key bash quickstart.sh captcha.png set -euo pipefail IMAGE="${1:-captcha.png}" BODY=$(base64 < "$IMAGE" | tr -d '\n') # no "data:" prefix, no line breaks curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d "{\"clientKey\": \"${YESCAPTCHA_CLIENT_KEY}\", \"task\": {\"type\": \"ImageToTextTaskOcrBase\", \"body\": \"${BODY}\"}}" echo ``` **Python** quickstart.py ```python """First request: read an alphanumeric image captcha with ImageToTextTaskOcrBase (synchronous, 2 points per image). Usage: export YESCAPTCHA_CLIENT_KEY=your_client_key python quickstart.py captcha.png """ import base64 import os import sys import requests CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] image_path = sys.argv[1] if len(sys.argv) > 1 else "captcha.png" with open(image_path, "rb") as f: body = base64.b64encode(f.read()).decode() # no "data:" prefix r = requests.post( "https://api.yescaptcha.com/createTask", json={ "clientKey": CLIENT_KEY, "task": {"type": "ImageToTextTaskOcrBase", "body": body}, }, timeout=30, ) data = r.json() if data.get("errorId"): raise SystemExit(f"{data.get('errorCode')}: {data.get('errorDescription')}") print("text:", data["solution"]["text"]) ``` **Node.js** quickstart.mjs ```js // First request: read an alphanumeric image captcha with ImageToTextTaskOcrBase (synchronous, 2 points per image). // Usage: YESCAPTCHA_CLIENT_KEY=your_client_key node quickstart.mjs captcha.png import { readFileSync } from 'node:fs'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; const body = readFileSync(process.argv[2] ?? 'captcha.png').toString('base64'); // no "data:" prefix const res = await fetch('https://api.yescaptcha.com/createTask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, task: { type: 'ImageToTextTaskOcrBase', body } }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); console.log('text:', data.solution.text); ``` Run `bash quickstart.sh captcha.jpg`, `python quickstart.py captcha.jpg` or `node quickstart.mjs captcha.jpg`. Python needs `pip install requests`; Node.js needs version 18 or later. 6. **Read the result** On success you get: ```json { "errorId": 0, "status": "ready", "solution": { "text": "LMResm" }, "taskId": "2376919c-1863-11ec-a012-94e6f7355a0b" } ``` `errorId` 0 means success, and the text is in `solution.text`. If `errorId` is 1, look up `errorCode` in [Error codes](https://docs.yescaptcha.com/en/api/errors/). ## Next steps - Token tasks such as reCAPTCHA and hCaptcha are **asynchronous**: `createTask` returns a `taskId`, then you call `getTaskResult` every 5 seconds. The full flow is in [Requests and responses](https://docs.yescaptcha.com/en/api/overview/); an example is [reCAPTCHA v2](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/). - Choose a task type: [Task types and pricing](https://docs.yescaptcha.com/en/tasks/). - A client you can copy into your project: [Python](https://docs.yescaptcha.com/en/samples/python/), [Node.js](https://docs.yescaptcha.com/en/samples/nodejs/). - No code: [Browser extension](https://docs.yescaptcha.com/en/extension/). --- # Endpoints > The two YesCaptcha API endpoints, global api.yescaptcha.com and China cn.yescaptcha.com. HTTPS POST with JSON only; create and query a task on the same endpoint. Source: https://docs.yescaptcha.com/en/getting-started/endpoints/ · Last verified: 2026-10-15 The YesCaptcha API has two endpoints with identical methods and parameters. Pick the one closer to your servers: | Endpoint | Address | Use it for | | --- | --- | --- | | Global | `https://api.yescaptcha.com` | Servers outside mainland China | | China | `https://cn.yescaptcha.com` | Servers in mainland China | A method URL is the endpoint plus the method name, for example creating a task: - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Rules - HTTPS only. - Every method except [`/useragent`](https://docs.yescaptcha.com/en/api/useragent/) uses `POST` with a JSON body and the header `Content-Type: application/json`. The body must be under 6 MB. - Authentication is the `clientKey` in the body; no other headers are needed. - Query a task with `getTaskResult` on the same endpoint you created it on. Don’t mix endpoints. ## All methods | Method | Purpose | Notes | | --- | --- | --- | | [`createTask`](https://docs.yescaptcha.com/en/api/create-task/) | Create a task | Synchronous types return the result directly | | [`getTaskResult`](https://docs.yescaptcha.com/en/api/get-task-result/) | Get the task result | Poll every 5 seconds for asynchronous types | | [`getBalance`](https://docs.yescaptcha.com/en/api/get-balance/) | Get the balance | Free | | [`getSoftID`](https://docs.yescaptcha.com/en/api/get-soft-id/) | Get your developer ID | For the developer revenue share | | [`report`](https://docs.yescaptcha.com/en/api/report/) | Report results | Image recognition types can be refunded | | [`useragent`](https://docs.yescaptcha.com/en/api/useragent/) | Get the recommended User-Agent | `GET`, used with hCaptcha | If you cannot connect, see [Connection troubleshooting](https://docs.yescaptcha.com/en/help/troubleshooting/). --- # Billing and refunds > How YesCaptcha charges. 1,000 points = ¥1, a fixed price per task type; failed and timed-out tasks are refunded, requests that return an error are free; the balance must be above 10 points; failed image recognition reports are refunded after about 24 hours. Source: https://docs.yescaptcha.com/en/getting-started/billing/ · Last verified: 2026-10-15 YesCaptcha charges per task. Each task type has a fixed price in points (1,000 points = ¥1); for example `NoCaptchaTaskProxyless` costs 15 points (¥0.015) per task. You only pay for successful tasks: failed and timed-out tasks are refunded automatically, and requests that return an error are not charged. Prices for every type: [Task types and pricing](https://docs.yescaptcha.com/en/tasks/). ## When points are charged - **Asynchronous types** (most token types): charged when the task is created. If it then fails (`ERROR_CAPTCHA_UNSOLVABLE` and similar) or times out (`ERROR_TASK_TIMEOUT`, usually after 110 seconds), the points are refunded automatically. - **Synchronous types** (image recognition, `ImageToTextTaskOcrBase`, `ImageToTextTaskMuggle`): charged when the result is returned. - Requests rejected at creation (bad parameters, insufficient balance, concurrency limit and so on) are not charged. ## Balance - Your balance must be **above 10 points** to create tasks; otherwise you get `ERROR_ZERO_BALANCE`. - Check it with [`getBalance`](https://docs.yescaptcha.com/en/api/get-balance/), which is free. - Top-ups and VIP bonuses: [Top-up and VIP](https://docs.yescaptcha.com/en/account/recharge/). Once your total top-up reaches a VIP level, every later top-up receives bonus points. ## Types priced by case - **reCAPTCHA v2 image recognition** (`ReCaptchaV2Classification`): a 1x1 tile costs less than a 3x3 or 4x4 image; see [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/). - **hCaptcha image recognition** (`HCaptchaClassification`): not charged when no target is found (empty result). ## Refunds after reporting a wrong result If an image recognition result was wrong, you can report it with [`report`](https://docs.yescaptcha.com/en/api/report/). Eligible tasks are refunded: - Only 5 image recognition types qualify: `FunCaptchaClassification`, `HCaptchaClassification`, `ReCaptchaV2Classification`, `AwsClassification` and `bCaptchaClassification`. - Report **within 1 hour** of creating the task. Each task is counted once. - Refunds are not immediate; they are settled **after about 24 hours**. - At settlement, your reported failure rate is compared with other users on the same questions in the same period. If yours is clearly higher, you are refunded at the period’s failure rate. - If you disagree with a settlement, [contact support](https://docs.yescaptcha.com/en/help/contact/). For token types (reCAPTCHA, hCaptcha, Turnstile and so on), whether a token passes is decided by the target site, so reports are not refunded. ## When you are not charged | Situation | Response | | --- | --- | | Bad parameters, unknown task type, wrong `clientKey` | The matching error code | | Balance not above 10 points | `ERROR_ZERO_BALANCE` | | Concurrency limit reached | `ERROR_THREADS_MAXIMUM`; see [Rate limits](https://docs.yescaptcha.com/en/api/rate-limits/) | | During an automatic pause | `ERROR_IP_BLOCKED_5MIN` | | A sitekey or domain already found invalid (while cached) | The original error code with `cached: true` | | Solving failed or timed out | Points already charged are refunded | ## Revenue share and rewards - When you use someone else’s software or extension, your tasks may carry their developer ID. The developer receives a share; your charge does not change. If you build software yourself, see [Developer revenue share](https://docs.yescaptcha.com/en/account/developer/). - Inviting other users: [Referral program](https://docs.yescaptcha.com/en/account/referral/). --- # Requests and responses > Common rules of the YesCaptcha API. POST JSON, clientKey authentication, the errorId response envelope, synchronous and asynchronous tasks, polling every 5 seconds, 110-second timeout, results kept about 10 minutes, message language by Accept-Language. Source: https://docs.yescaptcha.com/en/api/overview/ · Last verified: 2026-10-15 Every method takes an HTTPS `POST` with a JSON body (only `/useragent` is `GET`), is authenticated with the `clientKey` in the body, and returns JSON: `errorId` 0 means success, 1 means failure with an `errorCode`. Solving a captcha takes two steps: `createTask` creates a task and `getTaskResult` is polled every 5 seconds for the result. Synchronous types return the result from `createTask` directly. ## Request ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "task": {"type": "ImageToTextTaskOcrBase", "body": "BASE64_IMAGE"}}' ``` - Endpoint: `https://api.yescaptcha.com` (global) or `https://cn.yescaptcha.com` (China). See [Endpoints](https://docs.yescaptcha.com/en/getting-started/endpoints/). - The body is JSON, sent with `Content-Type: application/json`, under 6 MB. JSON cannot contain comments. - Every request includes `clientKey`, copied in full from the dashboard. - With Python requests use `json=data`, not `data=data` (the latter sends a form and returns `ERROR_TASK_ABSENT` or `ERROR_REQUIRED_FIELDS`). ## Response Success: ```json { "errorId": 0, "taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006" } ``` Failure: ```json { "errorId": 1, "errorCode": "ERROR_ZERO_BALANCE", "errorDescription": "帐户余额不足" } ``` | Field | Description | | --- | --- | | `errorId` | 0 success, 1 failure | | `errorCode` | The error code on failure; meanings and fixes in [Error codes](https://docs.yescaptcha.com/en/api/errors/) | | `errorDescription` | A text description of the failure (Chinese for most codes) | | `taskId` | The task ID | | `status` | `processing` or `ready` | | `solution` | The result; its fields depend on the task type (see each task type page) | Check `errorId` and `errorCode` in your code, not the wording of `errorDescription`, which may change. ## Synchronous and asynchronous | | Asynchronous | Synchronous | | --- | --- | --- | | Which types | Token types (reCAPTCHA, hCaptcha, Turnstile, FunCaptcha), the Cloudflare challenge page, `ImageToTextTask`, `ImageToTextTaskM1` | Image recognition (names ending in `Classification`), `ImageToTextTaskOcrBase`, `ImageToTextTaskMuggle` | | `createTask` returns | `taskId` | `status: "ready"` and `solution` | | Getting the result | Call `getTaskResult` every 5 seconds | Nothing more to do | The “Mode” column in [Task types and pricing](https://docs.yescaptcha.com/en/tasks/) shows which applies to each type. ## Polling 1. After `createTask` returns a `taskId`, wait 5 seconds and call `getTaskResult`. 2. On `status: "processing"`, wait another 5 seconds and try again; on `status: "ready"`, the result is in `solution`. 3. On `errorId: 1`, stop polling this task and handle the `errorCode`. - Repeated queries for the same `taskId` within 5 seconds return `processing` right away; polling faster does not get the result sooner. - A task runs for at most about 110 seconds (180 to 220 seconds for a few types); after that it returns `ERROR_TASK_TIMEOUT` and the points are refunded. - Results are kept for about 10 minutes; after that the `taskId` expires and queries return `ERROR_TASKID_INVALID`. - Queries are free; only creating a task is charged. ## Message language For automatic pauses, cached invalid parameters and stop-polling hints, `errorDescription` follows the `Accept-Language` request header: Chinese if it starts with `zh`, English for any other language, and both if the header is absent. Other error descriptions are unaffected. ## Next - [createTask](https://docs.yescaptcha.com/en/api/create-task/) - [getTaskResult](https://docs.yescaptcha.com/en/api/get-task-result/) - [Rate limits](https://docs.yescaptcha.com/en/api/rate-limits/): too many errors pause your key for a few minutes --- # createTask > POST /createTask creates a captcha task. Request fields (clientKey, task, softID), the order of checks, asynchronous types return a taskId and synchronous types return the solution; the balance must be above 10 points. Source: https://docs.yescaptcha.com/en/api/create-task/ · Last verified: 2026-10-15 `createTask` creates a recognition task; `task.type` says which captcha to solve. Asynchronous types return a `taskId` that you then pass to [`getTaskResult`](https://docs.yescaptcha.com/en/api/get-task-result/); synchronous types return the result directly. The task is charged when it is created successfully, and your balance must be above 10 points. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Request fields | Field | Type | Required | Description | | --- | --- | --- | --- | | `clientKey` | string | Yes | Your account key, copied from the [yescaptcha.com](https://yescaptcha.com/) dashboard | | `task` | object | Yes | The task object. It must contain `type`; other fields depend on the task type (see each task type page) | | `softID` | integer | No | A developer ID. Include yours when other people use your software to receive a revenue share; see [Developer revenue share](https://docs.yescaptcha.com/en/account/developer/) | ## Request examples Read an image captcha (synchronous): ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "ImageToTextTaskOcrBase", "body": "BASE64_IMAGE" } } ``` Get a reCAPTCHA v2 token (asynchronous): ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } } ``` The `task` fields of each type are on the pages under [Task types and pricing](https://docs.yescaptcha.com/en/tasks/). ## Response Asynchronous types: ```json { "errorId": 0, "taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006" } ``` Keep the `taskId` and start calling `getTaskResult` 5 seconds later. Synchronous types: ```json { "errorId": 0, "status": "ready", "taskId": "2376919c-1863-11ec-a012-94e6f7355a0b", "solution": { "text": "LMResm" } } ``` Failure: ```json { "errorId": 1, "errorCode": "ERROR_TASK_NOT_SUPPORTED", "errorDescription": "任务类型不正确或不受支持" } ``` ## Order of checks The server checks a request in this order and returns the first error it finds. None of these are charged: 1. The body is valid JSON: `ERROR_REQUEST_FORMATS` 2. `clientKey` is present: `ERROR_REQUIRED_FIELDS` 3. `clientKey` exists: `ERROR_KEY_DOES_NOT_EXIST` 4. The key is not paused: `ERROR_IP_BLOCKED_5MIN` (see [Rate limits](https://docs.yescaptcha.com/en/api/rate-limits/)) 5. The balance is above 10 points: `ERROR_ZERO_BALANCE` 6. `task` is present: `ERROR_TASK_ABSENT` 7. `task.type` exists: `ERROR_TASK_NOT_SUPPORTED` 8. All required fields are present: `ERROR_REQUIRED_FIELDS` (`errorDescription` names the missing field) 9. For image tasks, the image is valid: `ERROR_ZERO_CAPTCHA_FILESIZE`, `ERROR_IMAGE_TYPE_NOT_SUPPORTED` and others ## Complete example Create a task and poll for the result (asynchronous type): **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", }) print(solution["gRecaptchaResponse"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "NoCaptchaTaskProxyless", websiteURL: "https://www.google.com/recaptcha/api2/demo", websiteKey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", }); console.log(solution.gRecaptchaResponse); ``` --- # getTaskResult > POST /getTaskResult returns the result of an asynchronous task. Poll every 5 seconds, keep waiting on processing, read solution on ready, stop on errors; tasks run up to about 110 seconds, results are kept about 10 minutes, queries are free. Source: https://docs.yescaptcha.com/en/api/get-task-result/ · Last verified: 2026-10-15 `getTaskResult` returns the result of an asynchronous task. Call it every 5 seconds after creating the task: keep waiting on `processing`, read `solution` on `ready`, and stop on an error. Queries are free no matter how many you make. - POST `https://api.yescaptcha.com/getTaskResult` (Global endpoint) - POST `https://cn.yescaptcha.com/getTaskResult` (China endpoint) ## Request fields | Field | Type | Required | Description | | --- | --- | --- | --- | | `clientKey` | string | Yes | Your account key, the same one that created the task | | `taskId` | string | Yes | The task ID returned by [`createTask`](https://docs.yescaptcha.com/en/api/create-task/) | ```json { "clientKey": "YOUR_CLIENT_KEY", "taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006" } ``` ## Response | Situation | Response | What to do | | --- | --- | --- | | In progress | `{"errorId": 0, "status": "processing"}` | Check again in 5 seconds | | Done | `{"errorId": 0, "status": "ready", "solution": {...}}` | Read `solution`; its fields are on each task type page | | Not solved | `{"errorId": 1, "errorCode": "ERROR_CAPTCHA_UNSOLVABLE", ...}` | Already refunded; you can create a new task | | Timed out | `{"errorId": 1, "errorCode": "ERROR_TASK_TIMEOUT", ...}` | Already refunded; you can create a new task | | Unknown or expired task | `{"errorId": 1, "errorCode": "ERROR_TASKID_INVALID", ...}` | Stop querying this `taskId` | A finished task (reCAPTCHA v2): ```json { "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "03AGdBq25SxXT-pmSeBXjzScW-EiocHwwpwqtk1QXlJnGnU..." } } ``` ## Rules - **Poll every 5 seconds.** Repeated queries for the same `taskId` within 5 seconds return `processing` right away. - **A task runs for at most about 110 seconds** (180 to 220 seconds for a few types); then it returns `ERROR_TASK_TIMEOUT` and is refunded. Give up waiting in your code after about 3 minutes. - **Results are kept for about 10 minutes**, after which the `taskId` returns `ERROR_TASKID_INVALID`. Use results promptly: tokens expire sooner (about 120 seconds for reCAPTCHA). - **Stop on errors.** After `errorId: 1`, querying the same `taskId` again returns the same result; from the third query of a finished task, `errorDescription` ends with a hint to stop polling. `ERROR_TASKID_INVALID` counts toward the [automatic pause](https://docs.yescaptcha.com/en/api/rate-limits/) (only the first time per ID). - Query on the same endpoint you created the task on. - `getTaskResult` is not affected by automatic pauses: tasks created before a pause can still be queried. --- # getBalance > POST /getBalance returns your balance in points (1,000 points = ¥1) and your developer revenue share and referral reward balances. Free; a quick way to verify your clientKey. Source: https://docs.yescaptcha.com/en/api/get-balance/ · Last verified: 2026-10-15 `getBalance` returns your remaining points (1,000 points = ¥1) and your developer revenue share and referral reward balances (in CNY). It is free, so it is also the usual way to check that a `clientKey` is correct. - POST `https://api.yescaptcha.com/getBalance` (Global endpoint) - POST `https://cn.yescaptcha.com/getBalance` (China endpoint) ## Request fields | Field | Type | Required | Description | | --- | --- | --- | --- | | `clientKey` | string | Yes | Your account key | ```json { "clientKey": "YOUR_CLIENT_KEY" } ``` ## Response ```json { "errorId": 0, "balance": 1071810, "softBalance": 36.0098, "inviteBalance": 0, "inviteBy": 0 } ``` | Field | Type | Description | | --- | --- | --- | | `balance` | integer | Balance in points (1,000 points = ¥1). Must be above 10 points to create tasks | | `softBalance` | number | Developer revenue share balance in CNY; see [Developer revenue share](https://docs.yescaptcha.com/en/account/developer/) | | `inviteBalance` | number | Referral reward balance in CNY; see [Referral program](https://docs.yescaptcha.com/en/account/referral/) | | `inviteBy` | integer | User ID of the person who invited you, 0 if none | A wrong `clientKey` returns `ERROR_KEY_DOES_NOT_EXIST`. `getBalance` is affected by [automatic pauses](https://docs.yescaptcha.com/en/api/rate-limits/): during a pause it returns `ERROR_IP_BLOCKED_5MIN`. ## Examples **curl** get-balance.sh ```bash #!/usr/bin/env bash # Check the balance. getBalance is free and is a quick way to verify your clientKey set -euo pipefail curl -s https://api.yescaptcha.com/getBalance \ -H 'Content-Type: application/json' \ -d "{\"clientKey\": \"${YESCAPTCHA_CLIENT_KEY}\"}" echo ``` **Python** get_balance.py ```python """Check the balance. getBalance is free and is a quick way to verify your clientKey.""" import os import requests CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] r = requests.post( "https://api.yescaptcha.com/getBalance", json={"clientKey": CLIENT_KEY}, timeout=30, ) data = r.json() if data.get("errorId"): # e.g. ERROR_KEY_DOES_NOT_EXIST when the clientKey is wrong print("error:", data.get("errorCode"), data.get("errorDescription")) else: print("balance (points):", data["balance"]) ``` **Node.js** get-balance.mjs ```js // Check the balance. getBalance is free and is a quick way to verify your clientKey. Node.js 18+ const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; const res = await fetch('https://api.yescaptcha.com/getBalance', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY }), }); const data = await res.json(); if (data.errorId) { // e.g. ERROR_KEY_DOES_NOT_EXIST when the clientKey is wrong console.log('error:', data.errorCode, data.errorDescription); } else { console.log('balance (points):', data.balance); } ``` --- # getSoftID > POST /getSoftID returns your developer ID (softID) and accumulated revenue share. Put the softID in the createTask requests your software sends for other users to earn a share. Source: https://docs.yescaptcha.com/en/api/get-soft-id/ · Last verified: 2026-10-15 `getSoftID` returns your developer ID (`softID`) and your accumulated developer revenue share (in CNY). When other people use your software or extension, include this ID in their `createTask` requests and you earn a share of what they spend. Rules and withdrawals: [Developer revenue share](https://docs.yescaptcha.com/en/account/developer/). - POST `https://api.yescaptcha.com/getSoftID` (Global endpoint) - POST `https://cn.yescaptcha.com/getSoftID` (China endpoint) ## Request fields | Field | Type | Required | Description | | --- | --- | --- | --- | | `clientKey` | string | Yes | Your own (the developer’s) account key | ```json { "clientKey": "YOUR_CLIENT_KEY" } ``` ## Response ```json { "errorId": 0, "softID": 3, "balance": 0.004 } ``` | Field | Type | Description | | --- | --- | --- | | `softID` | integer | Your developer ID | | `balance` | number | Accumulated developer revenue share in CNY | ## How to use it In the `createTask` requests sent by your software’s users, add the top-level field `softID` (next to `clientKey` and `task`; it is case-sensitive): ```json { "clientKey": "THE_USERS_CLIENT_KEY", "task": { "type": "ImageToTextTaskOcrBase", "body": "BASE64_IMAGE" }, "softID": 3 } ``` `clientKey` is the user’s own key, and the points are charged to the user; `softID` is your developer ID. --- # report > POST /report tells YesCaptcha whether task results were correct. Failed image recognition tasks reported within 1 hour are settled for refunds after about 24 hours; please report correct results too. Source: https://docs.yescaptcha.com/en/api/report/ · Last verified: 2026-10-15 `report` tells us whether a group of task results was right. Image recognition tasks reported as wrong are refunded after about 24 hours if they qualify, and reports also help improve recognition. Please report correct results as well. - POST `https://api.yescaptcha.com/report` (Global endpoint) - POST `https://cn.yescaptcha.com/report` (China endpoint) ## Request fields | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | array of string | Yes | Task IDs; you can report several at once | | `isSuccess` | boolean | Yes | `true` if the result was correct, `false` if it was wrong | No `clientKey` is needed; the task IDs identify the tasks. ```json { "id": ["610ff5e0-68eb-11ef-95a6-22e70a0b794d", "65b88c06-68eb-11ef-8e9a-52540023ccb3"], "isSuccess": false } ``` When one challenge takes several images (for example five rounds of FunCaptcha) and the final submission fails without telling you which round was wrong, report the whole group of task IDs together. ## Response ```json { "errorId": 0, "status": "success" } ``` ## Refunds for failed reports - Only 5 image recognition types are refunded: `FunCaptchaClassification`, `HCaptchaClassification`, `ReCaptchaV2Classification`, `AwsClassification` and `bCaptchaClassification`. - Only reports made **within 1 hour** of creating the task count, and each task is refunded at most once. - Refunds are settled **after about 24 hours**, not immediately. - At settlement, your reported failure rate is compared with other users on the same questions in the same period; if yours is clearly higher, you are refunded at the period’s failure rate. - If you disagree with a settlement, [contact support](https://docs.yescaptcha.com/en/help/contact/). For token types (reCAPTCHA, hCaptcha, Turnstile, FunCaptcha and so on), the target site decides whether a token passes, so reports are not refunded. All billing rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). --- # useragent > GET https://api.yescaptcha.com/useragent returns the browser User-Agent to use (plain text). The userAgent field of hCaptcha tasks accepts only this value. Source: https://docs.yescaptcha.com/en/api/useragent/ · Last verified: 2026-10-15 `/useragent` returns the browser User-Agent we currently recommend, as plain text. It needs no `clientKey` and is free. The `userAgent` field of [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/) tasks accepts only this value, and using it when you visit the target site also helps tokens pass. - GET `https://api.yescaptcha.com/useragent` (Global endpoint) - GET `https://cn.yescaptcha.com/useragent` (China endpoint) ## Example ```bash curl -s https://api.yescaptcha.com/useragent ``` Response (value on 2026-10-15; it changes with browser releases): ```text Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 ``` - The value changes over time. Don’t hard-code it; fetch it when your program starts. - If a result contains a `userAgent`, submit the token with that value. --- # Error codes > Every YesCaptcha API error code with its meaning and what to do, grouped by request format, account and balance, concurrency and pauses, tasks, site parameters, images, proxies and server. Requests that return an error are not charged. Source: https://docs.yescaptcha.com/en/api/errors/ · Last verified: 2026-10-15 On failure the API returns `errorId: 1`, an error code in `errorCode` and a text description in `errorDescription`. Requests that return an error are not charged: errors at creation are never charged, and tasks that fail or time out after creation are refunded automatically. Branch on `errorCode` in your code, not on the wording of `errorDescription`. ```json { "errorId": 1, "errorCode": "ERROR_ZERO_BALANCE", "errorDescription": "帐户余额不足" } ``` `errorDescription` is in Chinese for most codes; see [Message language](https://docs.yescaptcha.com/en/api/overview/#message-language). ## How to handle errors 1. **Parameter errors** (request format, key, task type, site parameters, images) won’t change if you resend; fix the request first. 2. **Solving failures and timeouts** (`ERROR_CAPTCHA_UNSOLVABLE`, `ERROR_TASK_TIMEOUT`) can be retried by creating a new task. 3. After an error, **stop polling** that `taskId`. Don’t resend the same request at a high rate. 4. Errors marked “Counts toward pause” pause task creation for 5 minutes once one `clientKey` gets 100 of them within a minute. Errors marked “Cached” don’t count, but identical requests return the same error while cached. See [Rate limits](https://docs.yescaptcha.com/en/api/rate-limits/). ## All error codes ### Request format | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_REQUIRED_FIELDS` | A required field is missing (such as `clientKey`, or `websiteURL` / `websiteKey` for the task type), or the body is not JSON | Add the missing fields listed on the task type page, and send JSON with `POST` and `Content-Type: application/json` | | `ERROR_REQUEST_FORMATS` (Counts toward pause) | The request body is not valid JSON | Build the body with a JSON library instead of string concatenation; JSON must not contain `//` comments | | `ERROR_TASK_ABSENT` (Counts toward pause) | The `task` field is missing in a `createTask` call | Put the task parameters in a `task` object. With Python requests use `json=data`, not `data=data` | | `ERROR_TASK_NOT_SUPPORTED` (Counts toward pause) | `task.type` is misspelled or the type has been retired | Copy the type name from "Task types and pricing"; names are case-sensitive | | `ERROR_PAGE_NOT_FOUND` | The requested path does not exist | Check the endpoint URL, e.g. `https://api.yescaptcha.com/createTask`; method names are case-sensitive | | `ERROR_BAD_REQUEST` | The request cannot be processed, usually because of a wrong HTTP method (GET instead of POST) or invalid parameter values | Send JSON with `POST`, and check the parameter types and values | ### Account and balance | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_KEY_DOES_NOT_EXIST` (Counts toward pause) | The `clientKey` does not exist: characters were added or lost when copying, or the key was reset in the dashboard | Copy the key again from the yescaptcha.com dashboard, without spaces or line breaks | | `ERROR_ZERO_BALANCE` | Insufficient balance. The balance must be above 10 points to create a task | Top up and retry. Use `getBalance` to check the balance | ### Concurrency and pauses | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_THREADS_MAXIMUM` (Sometimes counts toward pause) | Too many tasks of this type are in progress for the account. `limit` in the response is the current limit. The request was not processed and not charged | Wait for in-flight requests to return, or wait 1–2 seconds and retry; cap the number of requests waiting at the same time | | `ERROR_IP_BLOCKED_5MIN` | This `clientKey` produced too many errors in a short time and was automatically paused. `retryAfter` is the remaining seconds and `blockReason` is the error that caused it | Fix the request according to `blockReason` and wait `retryAfter` seconds; sending during the pause does not extend it | | `ERROR_NO_SLOT_AVAILABLE` | The solving service is temporarily overloaded | Retry after a few seconds | ### Tasks and results | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_TASKID_INVALID` (Counts toward pause) | The `taskId` does not exist, has expired (results are kept for about 10 minutes), belongs to another `clientKey`, or was created on the other endpoint | Stop polling this task. Query with the same endpoint and `clientKey` that created it | | `ERROR_TASK_TIMEOUT` | The task did not finish in time (usually 110 seconds); the points were refunded automatically | Create a new task; if it keeps timing out, try another task type for the same captcha | | `ERROR_CAPTCHA_UNSOLVABLE` | The captcha could not be solved this time; the points were refunded. This does not count toward the automatic pause | Create a new task. If it keeps failing, check `websiteURL`, `websiteKey` and other parameters, or try another task type for the same captcha | | `ERROR_SETTLEMENT_FAILED` (Counts toward pause) | The balance was insufficient at settlement, so no result was returned | Top up and create a new task | | `ERROR_NO_SUCH_CAPCHA_ID` | The task is no longer valid | Stop polling this task and create a new one | | `ERROR_RECAPTCHA_TIMEOUT` | Solving the captcha timed out; the points were refunded | Create a new task | ### Target site parameters | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_RECAPTCHA_INVALID_SITEKEY` (Cached, no pause) | The `websiteKey` is invalid | Find the sitekey on the page again (see the guides on finding parameters). Identical requests return this error directly during the cache period, with `cached: true` | | `ERROR_RECAPTCHA_INVALID_DOMAIN` (Cached, no pause) | The domain of `websiteURL` does not match the `websiteKey` | Set `websiteURL` to the page that shows the captcha | | `ERROR_INVALID_KEY_TYPE` (Cached, no pause) | The sitekey belongs to a different captcha, e.g. a v3 key used with a v2 task type | Identify the captcha first (see "Identify the captcha type") and choose the matching task type; for invisible v2 set `isInvisible` | | `ERROR_DOMAIN_NOT_ALLOWED` (Cached, no pause) | This site is not supported | Try another task type for the same captcha, or contact support | | `ERROR_HIGH_DEMAND_DOMAIN` (Counts toward pause) | This site is not supported | Stop sending tasks for this site and contact support | | `ERROR_FAILED_LOADING_WIDGET` | The captcha could not be loaded with the given parameters | Check `websiteURL` and `websiteKey`; for task types with your own proxy, check that the proxy can reach the site | ### Images | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_ZERO_CAPTCHA_FILESIZE` (Counts toward pause) | The image is empty or too small | Check that the Base64 data is complete and has no `data:image/...;base64,` prefix | | `ERROR_TOO_BIG_CAPTCHA_FILESIZE` (Counts toward pause) | The image is too large | Compress or resize the image; the whole request body must stay under 6 MB | | `ERROR_IMAGE_TYPE_NOT_SUPPORTED` (Counts toward pause) | The image format is not supported, or the image is not one this task type can handle. A single occurrence pauses the key for 30 minutes | Use JPG or PNG and make sure the image matches the task type, e.g. reCAPTCHA image recognition needs 100x100, 300x300 or 450x450 | | `ERROR_ILLEGAL_IMAGE` (Counts toward pause) | The image size does not meet the requirements of this task type | Resize the image as described on the task type page | | `ERROR_PARSE_IMAGE_FAIL` | The image could not be decoded, often because the Base64 is truncated or has a prefix | Check the Base64 encoding and remove the `data:` prefix and line breaks | | `ERROR_UNKNOWN_QUESTION` | The `question` is wrong, or this question is not supported yet | Check it against the question list on the task type page. For unsupported questions contact support; new questions are usually supported within 3 business days | | `ERROR_UNKNOW_450x450_QUESTION` | This question is not supported for 4x4 (450x450) images yet | Reload the challenge on the page to get another question | ### Proxies | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_PROXY_CONNECT_REFUSED` | The proxy refused the connection | Check the proxy address, port and protocol, and make sure it accepts external connections (not a local address such as 127.0.0.1) | | `ERROR_PROXY_CONNECT_TIMEOUT` | Connecting to the proxy timed out | Use a more reliable proxy | | `ERROR_PROXY_READ_TIMEOUT` | Reading through the proxy timed out | Use a faster proxy | | `ERROR_PROXY_BANNED` | The proxy is unavailable, or its IP is blocked by the target site | Use another proxy | | `ERROR_PROXY_INCORRECT` | The proxy parameters are malformed | Check the format of `proxyType`, `proxyAddress`, `proxyPort` (or the `proxy` string) | | `ERROR_PROXY_TRANSPARENT` | The proxy is transparent and exposes the real IP | Use an anonymous (elite) proxy | | `ERROR_PROXY_NOT_AUTHORISED` | The proxy username or password is wrong | Check `proxyLogin` and `proxyPassword` | | `ERROR_PROXY_TLS_ERROR` | The TLS handshake with the proxy failed, often because `proxyType` is wrong (e.g. https set for an http proxy) | Check the proxy protocol | | `ERROR_PROXY_CONNECTION_FAILED` | Could not connect to the proxy server | Check the proxy address and port and make sure the proxy is working | ### Server | Error code | Meaning | What to do | | --- | --- | --- | | `ERROR_SERVICE_UNAVALIABLE` | The service is temporarily unavailable (the code is spelled `UNAVALIABLE`) | Retry later; contact support if it persists | | `ERROR_INTERNAL_SERVER_ERROR` | An internal server error occurred | Retry later; if it persists, contact support with the `taskId` | | `ERROR_UNKNOWN` | An unclassified error | Retry later; if it persists, contact support with the `taskId` | ## Extra fields Some error responses carry extra fields: | Field | Returned with | Description | | --- | --- | --- | | `retryAfter` | `ERROR_IP_BLOCKED_5MIN`, cached errors | Seconds left to wait | | `blockReason` | `ERROR_IP_BLOCKED_5MIN` | The error code that caused the pause | | `blockDetail` | `ERROR_IP_BLOCKED_5MIN` | Type, URL and sitekey of the requests that caused the pause | | `cached` | Cached errors | `true` means this is a cached answer; nothing was solved | | `badRequest` | Cached errors | The parameters that hit the cache | | `limit` | `ERROR_THREADS_MAXIMUM` | Your current concurrency limit | --- # Rate limits > YesCaptcha concurrency limits (ERROR_THREADS_MAXIMUM, not charged, no pause), automatic pauses after too many errors (100 in a minute pauses for 5 minutes, ERROR_IP_BLOCKED_5MIN) and the cache of invalid parameters (cached). Source: https://docs.yescaptcha.com/en/api/rate-limits/ · Last verified: 2026-10-15 To keep recognition fast for everyone, YesCaptcha has three protections: a limit on **how many tasks an account has in progress at once** (concurrency limit); a **short pause** for a `clientKey` that produces too many errors (automatic pause); and a **cache of parameters already found invalid**, which returns the original error for a while. None of these are charged. ## Concurrency limit We limit the number of tasks each account has in progress at the same time, per task type. It is a limit on concurrency, not on requests per minute. - A task is in progress from the moment you call `createTask` until that call returns. Image recognition types return the result from `createTask`, so **concurrency ≈ tasks sent per second × seconds per task**. For example, 40 tasks per second at 0.5 seconds each is a concurrency of about 20. - Requests from the same account are counted together; each task type is counted separately. - Requests over the limit return `ERROR_THREADS_MAXIMUM` right away, with your current limit in `limit`. **They are not charged and do not count toward the automatic pause.** - When the solvers are overloaded, the account using the most solving time has its limit for that task type **temporarily halved, restored automatically after 10 minutes**. This only slows you down; it never pauses the account. - If you need a higher limit, [contact support](https://docs.yescaptcha.com/en/help/contact/). The default limits for each type will be published on this page and in the [Service changelog](https://docs.yescaptcha.com/en/changelog/) once finalized. ```json { "errorId": 1, "errorCode": "ERROR_THREADS_MAXIMUM", "errorDescription": "This account already has 30 tasks of this type in progress, which is the limit. Lower the concurrency and wait for pending requests to return before sending more; rejected requests are not charged and do not lead to a block.", "limit": 30 } ``` (The number in the example is only an illustration.) ### Recommended practice 1. Limit the number of requests waiting for a result at the same time, for example with a semaphore or a fixed-size thread pool, rather than only limiting requests per second. 2. After `ERROR_THREADS_MAXIMUM`, wait for in-flight requests to return before sending new ones, or wait 1 to 2 seconds and retry. Don’t retry in a tight loop. 3. Spread batches out instead of sending thousands of tasks at once. A Python (asyncio) example: ```python import asyncio import os import aiohttp CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] LIMIT = 15 # below your concurrency limit sem = asyncio.Semaphore(LIMIT) async def solve(session, task): async with sem: # at most LIMIT requests in progress at a time result = {} for attempt in range(5): async with session.post( "https://api.yescaptcha.com/createTask", json={"clientKey": CLIENT_KEY, "task": task}, ) as resp: result = await resp.json() if result.get("errorCode") != "ERROR_THREADS_MAXIMUM": return result await asyncio.sleep(1 + attempt) # over the limit: wait and retry return result ``` ## Automatic pause A `clientKey` that sends many failing requests in a short time is paused from creating tasks: | Trigger | Pause | | --- | --- | | 100 of the errors listed below within one calendar minute | 5 minutes | | A single `ERROR_IMAGE_TYPE_NOT_SUPPORTED` | 30 minutes | | 1,000 hits on the invalid-parameter cache within one calendar minute | 5 minutes | Errors that count toward the pause: - [`ERROR_REQUEST_FORMATS`](https://docs.yescaptcha.com/en/api/errors/#ERROR_REQUEST_FORMATS) - [`ERROR_TASK_ABSENT`](https://docs.yescaptcha.com/en/api/errors/#ERROR_TASK_ABSENT) - [`ERROR_TASK_NOT_SUPPORTED`](https://docs.yescaptcha.com/en/api/errors/#ERROR_TASK_NOT_SUPPORTED) - [`ERROR_KEY_DOES_NOT_EXIST`](https://docs.yescaptcha.com/en/api/errors/#ERROR_KEY_DOES_NOT_EXIST) - [`ERROR_TASKID_INVALID`](https://docs.yescaptcha.com/en/api/errors/#ERROR_TASKID_INVALID) - [`ERROR_SETTLEMENT_FAILED`](https://docs.yescaptcha.com/en/api/errors/#ERROR_SETTLEMENT_FAILED) - [`ERROR_HIGH_DEMAND_DOMAIN`](https://docs.yescaptcha.com/en/api/errors/#ERROR_HIGH_DEMAND_DOMAIN) - [`ERROR_ZERO_CAPTCHA_FILESIZE`](https://docs.yescaptcha.com/en/api/errors/#ERROR_ZERO_CAPTCHA_FILESIZE) - [`ERROR_TOO_BIG_CAPTCHA_FILESIZE`](https://docs.yescaptcha.com/en/api/errors/#ERROR_TOO_BIG_CAPTCHA_FILESIZE) - [`ERROR_IMAGE_TYPE_NOT_SUPPORTED`](https://docs.yescaptcha.com/en/api/errors/#ERROR_IMAGE_TYPE_NOT_SUPPORTED) - [`ERROR_ILLEGAL_IMAGE`](https://docs.yescaptcha.com/en/api/errors/#ERROR_ILLEGAL_IMAGE) `ERROR_THREADS_MAXIMUM` returned by the account concurrency limit (with a `limit` field) does not count; the same code returned when the solvers are overloaded (without `limit`) does. Solving failures (`ERROR_CAPTCHA_UNSOLVABLE`), insufficient balance (`ERROR_ZERO_BALANCE`), missing fields (`ERROR_REQUIRED_FIELDS`), unsupported questions (`ERROR_UNKNOWN_QUESTION`) and others do not count. During a pause: - Only `createTask` and `getBalance` are affected; they return `ERROR_IP_BLOCKED_5MIN`. `getTaskResult` still works, so tasks created before the pause can be queried. - The response includes `retryAfter` (seconds left), `blockReason` (the error that caused the pause) and `blockDetail` (type, URL and sitekey of those requests) so you can fix your program. - Sending more requests does not extend the pause. It ends automatically; there is no need to contact support. - The dashboard at [yescaptcha.com](https://yescaptcha.com/) shows pauses from the last 24 hours. ```json { "errorId": 1, "errorCode": "ERROR_IP_BLOCKED_5MIN", "errorDescription": "...", "retryAfter": 182, "blockReason": "ERROR_TASK_NOT_SUPPORTED" } ``` ## Invalid-parameter cache Some errors are determined by the request parameters, so resending gives the same answer: - [`ERROR_RECAPTCHA_INVALID_SITEKEY`](https://docs.yescaptcha.com/en/api/errors/#ERROR_RECAPTCHA_INVALID_SITEKEY) - [`ERROR_RECAPTCHA_INVALID_DOMAIN`](https://docs.yescaptcha.com/en/api/errors/#ERROR_RECAPTCHA_INVALID_DOMAIN) - [`ERROR_INVALID_KEY_TYPE`](https://docs.yescaptcha.com/en/api/errors/#ERROR_INVALID_KEY_TYPE) - [`ERROR_DOMAIN_NOT_ALLOWED`](https://docs.yescaptcha.com/en/api/errors/#ERROR_DOMAIN_NOT_ALLOWED) These don’t count toward the pause; instead they are cached site-wide: for 2 minutes after the first decision, and for 10 minutes if confirmed again within an hour. While cached, identical requests (same task type and `websiteKey`, or same site domain) return the original error immediately, are not charged, and carry `"cached": true`, `retryAfter` (seconds left in the cache) and `badRequest` (the matching parameters). Fixing the `websiteKey` or switching task type takes effect immediately. ## Concurrency limit vs automatic pause | | Concurrency limit | Automatic pause | | --- | --- | --- | | Cause | Too many tasks in progress at once | Too many failing requests in a short time | | Effect | Only the excess requests are rejected with `ERROR_THREADS_MAXIMUM` | The `clientKey` cannot create tasks; `ERROR_IP_BLOCKED_5MIN` | | Recovery | Send more as soon as requests finish; a halved limit returns after 10 minutes | Ends automatically | | Charged | No | No | --- # Task types and pricing > Prices (points; 1,000 points = ¥1) and modes of every public YesCaptcha task type. Tokens for reCAPTCHA, hCaptcha, Turnstile and FunCaptcha, cookies for the Cloudflare challenge page, and recognition results for image-to-text and image recognition. Source: https://docs.yescaptcha.com/en/tasks/ · Last verified: 2026-10-15 Each task is charged a fixed number of points for its type (1,000 points = ¥1); failed and timed-out tasks are refunded automatically. The table lists every public task type and can be searched by name. Machine-readable version: [/data/task-types.json](https://docs.yescaptcha.com/data/task-types.json). | Captcha | Task type | Price | Mode | | --- | --- | --- | --- | | [reCAPTCHA v2](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/) | `NoCaptchaTaskProxyless` | 15 points (¥0.015) | Asynchronous | | reCAPTCHA v2 | `RecaptchaV2TaskProxyless` | 20 points (¥0.02) | Asynchronous | | reCAPTCHA v2 | `NoCaptchaTask` Own proxy | 15 points (¥0.015) | Asynchronous | | reCAPTCHA v2 | `RecaptchaV2EnterpriseTaskProxyless` | 20 points (¥0.02) | Asynchronous | | reCAPTCHA v2 | `RecaptchaV2EnterpriseTask` Own proxy | 20 points (¥0.02) | Asynchronous | | [reCAPTCHA v3](https://docs.yescaptcha.com/en/tasks/recaptcha-v3/) | `RecaptchaV3TaskProxyless` | 20 points (¥0.02) | Asynchronous | | reCAPTCHA v3 | `RecaptchaV3TaskProxylessM1` | 25 points (¥0.025) | Asynchronous | | reCAPTCHA v3 | `RecaptchaV3TaskProxylessM1S7` | 30 points (¥0.03) | Asynchronous | | reCAPTCHA v3 | `RecaptchaV3TaskProxylessM1S9` | 35 points (¥0.035) | Asynchronous | | reCAPTCHA v3 | `RecaptchaV3EnterpriseTask` | 20 points (¥0.02) | Asynchronous | | reCAPTCHA v3 | `RecaptchaV3EnterpriseTaskM1` | 25 points (¥0.025) | Asynchronous | | [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/) | `HCaptchaTaskProxyless` | 30 points (¥0.03) | Asynchronous | | hCaptcha | `HCaptchaTaskProxylessM1` | 30 points (¥0.03) | Asynchronous | | hCaptcha | `HCaptchaTask` Own proxy | 15 points (¥0.015) | Asynchronous | | [Cloudflare Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/) | `TurnstileTaskProxyless` | 25 points (¥0.025) | Asynchronous | | Cloudflare Turnstile | `TurnstileTaskProxylessM1` | 30 points (¥0.03) | Asynchronous | | Cloudflare Turnstile | `TurnstileTask` Own proxy | 25 points (¥0.025) | Asynchronous | | [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/) | `CloudFlareTaskS2` Not recommendedOwn proxy | 25 points (¥0.025) | Asynchronous | | Cloudflare challenge page | `CloudFlareTaskS3` Not recommendedOwn proxy | 20 points (¥0.02) | Asynchronous | | [FunCaptcha (Arkose)](https://docs.yescaptcha.com/en/tasks/funcaptcha/) | `FunCaptchaTaskProxyless` | 30 points (¥0.03) | Asynchronous | | FunCaptcha (Arkose) | `FunCaptchaTaskProxylessM1` | 110 points (¥0.11) | Asynchronous | | FunCaptcha (Arkose) | `FunCaptchaTask` Own proxy | 15 points (¥0.015) | Asynchronous | | [Image to text](https://docs.yescaptcha.com/en/tasks/image-to-text/) | `ImageToTextTaskOcrBase` | 2 points (¥0.002) | Synchronous | | Image to text | `ImageToTextTaskMuggle` | 2 points (¥0.002) | Synchronous | | Image to text | `ImageToTextTask` | 4 points (¥0.004) | Asynchronous | | Image to text | `ImageToTextTaskM1` | 15 points (¥0.015) | Asynchronous | | [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/) | `ReCaptchaV2Classification` | 6 points (¥0.006) | Synchronous | | [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/) | `HCaptchaClassification` | 8 points (¥0.008) | Synchronous | | [FunCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/funcaptcha-classification/) | `FunCaptchaClassification` | 3 points (¥0.003) | Synchronous | | [AWS WAF / bCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/aws-bcaptcha-classification/) | `AwsClassification` | 8 points (¥0.008) | Synchronous | | AWS WAF / bCaptcha image recognition | `bCaptchaClassification` | 8 points (¥0.008) | Synchronous | ## Which one do I need? | You want to | Use | You get | | --- | --- | --- | | Get a token and submit it without clicking | [reCAPTCHA v2](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/), [reCAPTCHA v3](https://docs.yescaptcha.com/en/tasks/recaptcha-v3/), [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/), [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/), [FunCaptcha](https://docs.yescaptcha.com/en/tasks/funcaptcha/) | A token, asynchronously | | Get past Cloudflare’s “Just a moment…” page | [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/) (not recommended) | Cookies and User-Agent, asynchronously | | Click the images yourself in a browser | [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/), [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/), [FunCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/funcaptcha-classification/), [AWS WAF / bCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/aws-bcaptcha-classification/) | Which tiles or positions to click, synchronously | | Read the characters in an image | [Image to text](https://docs.yescaptcha.com/en/tasks/image-to-text/) | Text, mostly synchronously | Not sure which captcha you have? See [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/). ## Naming - **`Proxyless`**: the captcha is loaded from our network; no proxy needed. Types without `Proxyless` (such as `NoCaptchaTask`, `HCaptchaTask`) use your own proxy and need the proxy fields; use them when the target site checks the visitor’s IP. - **Suffixes like `M1`**: another route for the same captcha, with the same parameters and a different price. If one doesn’t pass often enough, try the other; they also work as fallbacks for each other. - **`Classification`**: image recognition; returns where to click, not a token. - **`Enterprise`**: reCAPTCHA Enterprise. ## Notes - Types marked “Not recommended” still work, but quality varies; test before relying on them. - reCAPTCHA v2 image recognition is priced by image size, and hCaptcha image recognition is free when no target is found; see their pages. - This page is the reference for prices. Only creating tasks is charged; queries are free. Billing rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). --- # reCAPTCHA v2 > Get reCAPTCHA v2 tokens (checkbox, invisible and Enterprise) with YesCaptcha. Task types and prices, request parameters, curl/Python/Node.js examples and the result format. Source: https://docs.yescaptcha.com/en/tasks/recaptcha-v2/ · Last verified: 2026-10-15 A reCAPTCHA v2 task returns a token (`gRecaptchaResponse`) that you submit to the target site to pass the check, without clicking any images. The most common type, `NoCaptchaTaskProxyless`, costs 15 points (¥0.015) per task and is asynchronous: create the task with `createTask`, then call `getTaskResult` every 5 seconds for the result. Failed and timed-out tasks are refunded automatically. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON and is authenticated with your `clientKey` (copy it from the [yescaptcha.com](https://yescaptcha.com/) dashboard). Query results on the same endpoint you created the task on. ## When to use - The page shows an “I’m not a robot” checkbox: the checkbox version. - There is no checkbox, and an image challenge appears only after you click a submit button: the invisible version. Add `"isInvisible": true`. - The page loads `recaptcha/enterprise.js`, or the request URLs contain `enterprise`: reCAPTCHA Enterprise. Use a type with `Enterprise` in its name. If you are not sure which one you have, see [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/). If tokens do not pass often enough, try [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/): the API tells you which tiles to click, and you click them in the browser. ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `NoCaptchaTaskProxyless` | 15 points (¥0.015) | Asynchronous | | | `RecaptchaV2TaskProxyless` | 20 points (¥0.02) | Asynchronous | Same parameters as NoCaptchaTaskProxyless on a different route; use either as a fallback | | `NoCaptchaTask` | 15 points (¥0.015) | Asynchronous | Own proxy | | `RecaptchaV2EnterpriseTaskProxyless` | 20 points (¥0.02) | Asynchronous | | | `RecaptchaV2EnterpriseTask` | 20 points (¥0.02) | Asynchronous | Own proxy | - `NoCaptchaTaskProxyless` and `RecaptchaV2TaskProxyless` take the same parameters on different routes. If one does not pass often enough, try the other. - Types without `Proxyless` in the name (`NoCaptchaTask`, `RecaptchaV2EnterpriseTask`) load the captcha through your own proxy and need `proxyType`, `proxyAddress`, `proxyPort` and related fields. Use them when the target site checks the visitor’s IP. ## Request parameters Fields of the `task` object in `createTask`: | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `websiteKey` | string | Yes | The site key (sitekey), found in the page source or network requests; usually does not change | | `isInvisible` | boolean | No | Set to true for the invisible variant; omit otherwise | | `proxyType` | string | Required for NoCaptchaTask, RecaptchaV2EnterpriseTask | Proxy protocol: `http`, `https`, `socks4` or `socks5` | | `proxyAddress` | string | Required for NoCaptchaTask, RecaptchaV2EnterpriseTask | Proxy IP address or hostname. Local or private addresses such as 127.0.0.1 or 192.168.x.x will not work because our servers cannot reach them | | `proxyPort` | integer | Required for NoCaptchaTask, RecaptchaV2EnterpriseTask | Proxy port | | `proxyLogin` | string | No | Proxy username, if the proxy requires authentication (NoCaptchaTask, RecaptchaV2EnterpriseTask only) | | `proxyPassword` | string | No | Proxy password, if the proxy requires authentication (NoCaptchaTask, RecaptchaV2EnterpriseTask only) | | `userAgent` | string | No | Browser User-Agent. If the result contains a `userAgent`, use that value when you submit the token (NoCaptchaTask, RecaptchaV2EnterpriseTask only) | | `enterprisePayload` | object | No | Extra enterprise parameters, such as the reCAPTCHA Enterprise `s` value: `{"s": "..."}`. Omit if the page does not use it (RecaptchaV2EnterpriseTaskProxyless, RecaptchaV2EnterpriseTask only) | To find `websiteURL` and `websiteKey`, see [Find reCAPTCHA parameters](https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/). ## Request example Using Google’s official demo page: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } } ``` Complete code that creates the task, polls every 5 seconds and prints the token. Put your client key in the environment variable `YESCAPTCHA_CLIENT_KEY` before running it: **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "NoCaptchaTaskProxyless", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", }) print(solution["gRecaptchaResponse"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "NoCaptchaTaskProxyless", websiteURL: "https://www.google.com/recaptcha/api2/demo", websiteKey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", }); console.log(solution.gRecaptchaResponse); ``` For reCAPTCHA Enterprise, if the page passes an `s` value to reCAPTCHA, put it in `enterprisePayload`: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "RecaptchaV2EnterpriseTaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "SITE_KEY_OF_THE_PAGE", "enterprisePayload": { "s": "S_VALUE_FROM_THE_PAGE" } } } ``` With your own proxy: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "NoCaptchaTask", "websiteURL": "https://www.google.com/recaptcha/api2/demo", "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", "proxyType": "http", "proxyAddress": "proxy.example.com", "proxyPort": 8080, "proxyLogin": "user", "proxyPassword": "pass" } } ``` ## Result `createTask` returns a task ID: ```json { "errorId": 0, "taskId": "61138bb6-19fb-11ec-a9c8-0242ac110006" } ``` Call `getTaskResult` with it. While the task is in progress you get `{"errorId": 0, "status": "processing"}`; check again 5 seconds later. When it is done: ```json { "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "03AGdBq25SxXT-pmSeBXjzScW-EiocHwwpwqtk1QXlJnGnU..." } } ``` | Field | Type | Description | | --- | --- | --- | | `gRecaptchaResponse` | string | The token to submit to the target site. Single use, valid for about 120 seconds; use it within 60 seconds | A task runs for at most about 110 seconds; after that it returns `ERROR_TASK_TIMEOUT` and the points are refunded. On errors `errorId` is 1; handle them by `errorCode` as described in [Error codes](https://docs.yescaptcha.com/en/api/errors/). For how to submit the token, see [Submit a reCAPTCHA token](https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/). ## FAQ ### Why do tokens for the same site sometimes pass and sometimes fail? The target site decides. It scores each verification against a threshold that it can change at any time, so pass rates differ between sites and not every token passes. Compare another task type for the same captcha, or switch to [image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/). ### How long is a token valid? Tokens are single use and valid for about 120 seconds. Submit within 60 seconds. Google sets this limit. ### Am I charged when solving fails? No. Tasks that return `ERROR_CAPTCHA_UNSOLVABLE` or time out are refunded automatically. See [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). ## Related guides - [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/) - [Find reCAPTCHA parameters](https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/) - [Submit a reCAPTCHA token](https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/) - [reCAPTCHA image clicking with Selenium](https://docs.yescaptcha.com/en/guides/recaptcha-click-selenium/) --- # reCAPTCHA v3 > Get reCAPTCHA v3 (and v3 Enterprise) tokens with YesCaptcha. How to fill pageAction, the fixed 0.7 and 0.9 score types, task types and prices, parameters, examples and the result format. Source: https://docs.yescaptcha.com/en/tasks/recaptcha-v3/ · Last verified: 2026-10-15 reCAPTCHA v3 has no checkbox and no images; the page scores visitors in the background. YesCaptcha returns a token (`gRecaptchaResponse`) that you submit to the target site. `RecaptchaV3TaskProxyless` costs 20 points (¥0.02) per task and is asynchronous: `createTask`, then `getTaskResult` every 5 seconds. Failed and timed-out tasks are refunded automatically. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON authenticated with your `clientKey`. Query results on the same endpoint you created the task on. ## When to use - The page source contains `grecaptcha.execute(...)`, or it loads `recaptcha/api.js?render=SITE_KEY`: reCAPTCHA v3. - It calls `grecaptcha.enterprise.execute(...)` or loads `recaptcha/enterprise.js`: reCAPTCHA v3 Enterprise. Use `RecaptchaV3EnterpriseTask` or `RecaptchaV3EnterpriseTaskM1`. How to tell: [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/). ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `RecaptchaV3TaskProxyless` | 20 points (¥0.02) | Asynchronous | | | `RecaptchaV3TaskProxylessM1` | 25 points (¥0.025) | Asynchronous | | | `RecaptchaV3TaskProxylessM1S7` | 30 points (¥0.03) | Asynchronous | Requests a score of 0.7; no extra parameter needed | | `RecaptchaV3TaskProxylessM1S9` | 35 points (¥0.035) | Asynchronous | Requests a score of 0.9; no extra parameter needed | | `RecaptchaV3EnterpriseTask` | 20 points (¥0.02) | Asynchronous | | | `RecaptchaV3EnterpriseTaskM1` | 25 points (¥0.025) | Asynchronous | | - `RecaptchaV3TaskProxyless` and `RecaptchaV3TaskProxylessM1` take the same parameters on different routes; use either as a fallback for the other. - If the target site requires a high score, use `RecaptchaV3TaskProxylessM1S7` (0.7) or `RecaptchaV3TaskProxylessM1S9` (0.9); no extra parameter is needed. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `websiteKey` | string | Yes | The site key (sitekey), found in the page source or network requests; usually does not change | | `pageAction` | string | No | The reCAPTCHA v3 action; it must match the value the page passes to `grecaptcha.execute`, or the token may be rejected | `pageAction` must match the `action` the page passes to `grecaptcha.execute(SITE_KEY, {action: '...'})`, or the site may reject the token. How to find it: [Find reCAPTCHA parameters](https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/). ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "RecaptchaV3TaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "SITE_KEY_OF_THE_PAGE", "pageAction": "login" } } ``` **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "RecaptchaV3TaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "SITE_KEY_OF_THE_PAGE", "pageAction": "login" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "RecaptchaV3TaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "SITE_KEY_OF_THE_PAGE", "pageAction": "login", }) print(solution["gRecaptchaResponse"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "RecaptchaV3TaskProxyless", websiteURL: "https://example.com/login", websiteKey: "SITE_KEY_OF_THE_PAGE", pageAction: "login", }); console.log(solution.gRecaptchaResponse); ``` Replace `websiteURL`, `websiteKey` and `pageAction` with the target site’s values. ## Result ```json { "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "03AGdBq25SxXT-pmSeBXjzScW-EiocHwwpwqtk1QXlJnGnU..." } } ``` | Field | Type | Description | | --- | --- | --- | | `gRecaptchaResponse` | string | The token to submit to the target site. Single use, valid for about 120 seconds; use it within 60 seconds | While in progress you get `{"errorId": 0, "status": "processing"}`; check again 5 seconds later. Handle errors by `errorCode` as described in [Error codes](https://docs.yescaptcha.com/en/api/errors/). To submit the token, see [Submit a reCAPTCHA token](https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/). ## FAQ ### Why are some tokens rejected by the site? With v3 the target site decides based on the score, and it can change its threshold at any time, so not every token passes. Make sure `pageAction` is correct, try `M1S7` or `M1S9` if the site needs a high score, or compare other types. ### How do I fill in v3 Enterprise? The same as v3: `websiteURL`, `websiteKey`, `pageAction`, with the type `RecaptchaV3EnterpriseTask` or `RecaptchaV3EnterpriseTaskM1`. ### How long is a token valid? Single use, valid for about 120 seconds. Submit within 60 seconds. ## Related guides - [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/) - [Find reCAPTCHA parameters](https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/) (including `pageAction`) - [Submit a reCAPTCHA token](https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/) --- # hCaptcha > Get hCaptcha tokens with YesCaptcha. HCaptchaTaskProxyless, HCaptchaTaskProxylessM1 and HCaptchaTask with your own proxy, how to fill userAgent and rqdata, and how to use the returned respKey. Source: https://docs.yescaptcha.com/en/tasks/hcaptcha/ · Last verified: 2026-10-15 An hCaptcha task returns a token (`gRecaptchaResponse`). Submit it to the target site together with the returned `userAgent` (and `respKey`, when present) to pass the check. `HCaptchaTaskProxyless` costs 30 points (¥0.03) per task and `HCaptchaTask` (your own proxy) costs 15 points (¥0.015); both are asynchronous: `createTask`, then `getTaskResult` every 5 seconds. Failed and timed-out tasks are refunded automatically. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON authenticated with your `clientKey`. Query results on the same endpoint you created the task on. ## When to use The page shows an hCaptcha “I am human” checkbox or an hCaptcha image challenge. Use the types on this page to get a token; to click the images yourself in a browser, use [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/). hCaptcha pass rates vary a lot between sites; test with a small batch first. ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `HCaptchaTaskProxyless` | 30 points (¥0.03) | Asynchronous | | | `HCaptchaTaskProxylessM1` | 30 points (¥0.03) | Asynchronous | Same parameters as HCaptchaTaskProxyless on a different route; use either as a fallback | | `HCaptchaTask` | 15 points (¥0.015) | Asynchronous | Own proxy | - `HCaptchaTaskProxyless` and `HCaptchaTaskProxylessM1` take the same parameters on different routes; use either as a fallback for the other. - `HCaptchaTask` loads the captcha through your own proxy and needs the proxy fields; use it when the site checks the visitor’s IP. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `websiteKey` | string | Yes | The hCaptcha site key (sitekey), usually a UUID | | `userAgent` | string | No | Browser User-Agent. Recommended, but only the value returned by `GET https://api.yescaptcha.com/useragent` is accepted; submit the token with the `userAgent` from the result | | `isInvisible` | boolean | No | Set to true for the invisible variant; omit otherwise | | `rqdata` | string | No | rqdata for enterprise hCaptcha; required by some sites and usually found in the request that loads the captcha | | `proxyType` | string | Required for HCaptchaTask | Proxy protocol: `http`, `https`, `socks4` or `socks5` | | `proxyAddress` | string | Required for HCaptchaTask | Proxy IP address or hostname. Local or private addresses such as 127.0.0.1 or 192.168.x.x will not work because our servers cannot reach them | | `proxyPort` | integer | Required for HCaptchaTask | Proxy port | | `proxyLogin` | string | No | Proxy username, if the proxy requires authentication (HCaptchaTask only) | | `proxyPassword` | string | No | Proxy password, if the proxy requires authentication (HCaptchaTask only) | - `websiteURL` is the page that shows the captcha, **not** hcaptcha.com. - `userAgent` is recommended, but only the value returned by [`/useragent`](https://docs.yescaptcha.com/en/api/useragent/) is accepted. - `rqdata`: required by sites using hCaptcha Enterprise (some social and chat sites) and usually found in the request that loads the captcha. Omit it for ordinary sites. How to find them: [Find hCaptcha parameters](https://docs.yescaptcha.com/en/guides/find-hcaptcha-parameters/). ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "HCaptchaTaskProxyless", "websiteURL": "https://accounts.hcaptcha.com/demo", "websiteKey": "a5f74b19-9e45-40e0-b45d-47ff91b7a6c2" } } ``` **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "HCaptchaTaskProxyless", "websiteURL": "https://accounts.hcaptcha.com/demo", "websiteKey": "a5f74b19-9e45-40e0-b45d-47ff91b7a6c2" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "HCaptchaTaskProxyless", "websiteURL": "https://accounts.hcaptcha.com/demo", "websiteKey": "a5f74b19-9e45-40e0-b45d-47ff91b7a6c2", }) print(solution["gRecaptchaResponse"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "HCaptchaTaskProxyless", websiteURL: "https://accounts.hcaptcha.com/demo", websiteKey: "a5f74b19-9e45-40e0-b45d-47ff91b7a6c2", }); console.log(solution.gRecaptchaResponse); ``` With your own proxy: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "HCaptchaTask", "websiteURL": "https://accounts.hcaptcha.com/demo", "websiteKey": "a5f74b19-9e45-40e0-b45d-47ff91b7a6c2", "proxyType": "http", "proxyAddress": "proxy.example.com", "proxyPort": 8080, "proxyLogin": "user", "proxyPassword": "pass" } } ``` ## Result ```json { "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36", "respKey": "E0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } } ``` | Field | Type | Description | | --- | --- | --- | | `gRecaptchaResponse` | string | The token to submit to the target site. Single use, valid for about 120 seconds; use it within 60 seconds | | `userAgent` | string | The User-Agent used to obtain the token. Use this value when you submit the token, even if it differs from the one you sent | | `respKey` | string | A value some sites require together with the token; submit it if present | To submit: 1. Put the token in the page’s `h-captcha-response` field (and `g-recaptcha-response`, if present), or in whatever field the site’s API expects. 2. Send the submission with the returned `userAgent` as the User-Agent. 3. If a `respKey` was returned, submit it too as the site requires. While in progress you get `{"errorId": 0, "status": "processing"}`; check again 5 seconds later. Handle errors by `errorCode` as described in [Error codes](https://docs.yescaptcha.com/en/api/errors/). ## FAQ ### Why is the pass rate inconsistent? hCaptcha decides based on the site’s settings, the visitor’s IP and browser environment, so pass rates vary by site. Use the returned `userAgent`; for IP-sensitive sites, use `HCaptchaTask` with your own proxy and submit through the same proxy; or compare with `HCaptchaTaskProxylessM1`. ### How long is a token valid? Single use, valid for about 120 seconds. Submit it as soon as possible. ## Related guides - [Find hCaptcha parameters](https://docs.yescaptcha.com/en/guides/find-hcaptcha-parameters/) - [hCaptcha image clicking with Selenium](https://docs.yescaptcha.com/en/guides/hcaptcha-click-selenium/) --- # Cloudflare Turnstile > Get Cloudflare Turnstile tokens with YesCaptcha. TurnstileTaskProxyless, TurnstileTaskProxylessM1 and TurnstileTask with your own proxy, parameters, examples and the result format, and how Turnstile differs from the Cloudflare challenge page. Source: https://docs.yescaptcha.com/en/tasks/turnstile/ · Last verified: 2026-10-15 A Cloudflare Turnstile task returns a token (`token`) that you submit to the target site to pass the check. `TurnstileTaskProxyless` costs 25 points (¥0.025) per task and is asynchronous: `createTask`, then `getTaskResult` every 5 seconds. Failed and timed-out tasks are refunded automatically. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON authenticated with your `clientKey`. Query results on the same endpoint you created the task on. ## When to use A Cloudflare verification widget (“Verify you are human”) is embedded in a form on the page, and the page loads a script from `challenges.cloudflare.com/turnstile`. If the whole page is replaced by Cloudflare’s “Just a moment…” / “Checking your browser” screen, that is the challenge page, not Turnstile; use [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/). See [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/). ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `TurnstileTaskProxyless` | 25 points (¥0.025) | Asynchronous | | | `TurnstileTaskProxylessM1` | 30 points (¥0.03) | Asynchronous | | | `TurnstileTask` | 25 points (¥0.025) | Asynchronous | Own proxy | - `TurnstileTaskProxyless` and `TurnstileTaskProxylessM1` take the same parameters on different routes; use either as a fallback for the other. - `TurnstileTask` loads the captcha through your own proxy and needs the proxy fields. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `websiteKey` | string | Yes | The Turnstile site key (sitekey), usually starting with 0x | | `proxyType` | string | Required for TurnstileTask | Proxy protocol: `http`, `https`, `socks4` or `socks5` | | `proxyAddress` | string | Required for TurnstileTask | Proxy IP address or hostname. Local or private addresses such as 127.0.0.1 or 192.168.x.x will not work because our servers cannot reach them | | `proxyPort` | integer | Required for TurnstileTask | Proxy port | | `proxyLogin` | string | No | Proxy username, if the proxy requires authentication (TurnstileTask only) | | `proxyPassword` | string | No | Proxy password, if the proxy requires authentication (TurnstileTask only) | | `userAgent` | string | No | Browser User-Agent. If the result contains a `userAgent`, use that value when you submit the token (TurnstileTask only) | `websiteKey` usually starts with `0x`. How to find it: [Find Turnstile parameters](https://docs.yescaptcha.com/en/guides/find-turnstile-parameters/). ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "TurnstileTaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "0x4AAAAAAA_SITE_KEY" } } ``` **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "TurnstileTaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "0x4AAAAAAA_SITE_KEY" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "TurnstileTaskProxyless", "websiteURL": "https://example.com/login", "websiteKey": "0x4AAAAAAA_SITE_KEY", }) print(solution["token"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "TurnstileTaskProxyless", websiteURL: "https://example.com/login", websiteKey: "0x4AAAAAAA_SITE_KEY", }); console.log(solution.token); ``` Replace `websiteURL` and `websiteKey` with the target site’s values. ## Result ```json { "errorId": 0, "status": "ready", "solution": { "token": "0.ufq5RgSVZd11DPSX1brdrxnEs28KcVlKj2ORchqxSy2q9yAW6ciq3hriXDF4x...", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36" } } ``` | Field | Type | Description | | --- | --- | --- | | `token` | string | The token to submit to the target site. Single use; submit it as soon as possible | | `userAgent` | string | The User-Agent used to obtain the token. Use this value when you submit the token, even if it differs from the one you sent | Put the `token` in the page’s `cf-turnstile-response` field (or the field the site’s API expects) and submit, using the returned `userAgent` as the User-Agent. While in progress you get `{"errorId": 0, "status": "processing"}`; check again 5 seconds later. Handle errors by `errorCode` as described in [Error codes](https://docs.yescaptcha.com/en/api/errors/). ## FAQ ### How long is a token valid? Single use. Submit it as soon as possible; Turnstile tokens usually expire within a few minutes (Cloudflare decides). ### The site still rejects the submission Check that `websiteURL` is the page with the widget and `websiteKey` is correct, and submit with the returned `userAgent`. If the site also checks the IP, use `TurnstileTask` and submit through the same proxy. ## Related guides - [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/) - [Find Turnstile parameters](https://docs.yescaptcha.com/en/guides/find-turnstile-parameters/) --- # Cloudflare challenge page > Get past Cloudflare's "Just a moment..." challenge page with YesCaptcha and receive cf_clearance and other cookies plus the User-Agent. CloudFlareTaskS2 and CloudFlareTaskS3 (not recommended), proxy requirements and how to use the result. Source: https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/ · Last verified: 2026-10-15 The Cloudflare challenge page replaces a whole site with “Just a moment…” / “Checking your browser” before letting you in. YesCaptcha opens the page through the proxy you provide, passes the check, and returns the cookies (such as `cf_clearance`) and the User-Agent it used. `CloudFlareTaskS3` costs 20 points (¥0.02) per task and is asynchronous. Failed and timed-out tasks are refunded automatically. > **Not recommended:** Cloudflare updates its checks frequently, and some sites may not pass or may not return `cf_clearance`. Test with a small batch first, and contact support if you run into problems. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## When to use - The page source contains `__cf_chl_rt_tk` or `cdn-cgi/challenge-platform`, and the title is `Just a moment...`: this is the challenge page. - If only a Cloudflare widget is embedded in a form, it is [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/) instead. - If your HTTP library gets a 403 with “Just a moment…” but a browser opens the page directly, you are probably only being blocked by TLS fingerprinting. A library that imitates a browser’s TLS fingerprint (such as curl\_cffi) usually fixes it without solving anything. ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `CloudFlareTaskS2` | 25 points (¥0.025) | Asynchronous | Not recommendedOwn proxy | | `CloudFlareTaskS3` | 20 points (¥0.02) | Asynchronous | Not recommendedOwn proxy | ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `proxy` | string | Yes | Proxy as one string, e.g. `http://user:pass@proxy.example.com:8080` or `socks5://proxy.example.com:1080`. SOCKS5 with a password is not supported; local or private addresses will not work | | `waitLoad` | boolean | No | Wait until the page has fully loaded before returning. Set to true if you need the full page content; it takes longer | | `requiredCookies` | array | No | Cookie names you want returned, default `["cf_clearance"]`. You can list several, but they are not guaranteed | | `blockImage` | boolean | No | Skip loading images to save proxy traffic | | `postData` | object | No | If set, the target URL is opened with a POST request carrying this object, e.g. `{"name": "hi"}` | > **Proxy:** `proxy` is required. Cloudflare is strict about proxies, so use a good-quality proxy outside mainland China; on `ERROR_CAPTCHA_UNSOLVABLE`, change the proxy and try again. Local or private addresses (`127.0.0.1`, `192.168.x.x`) won’t work because our servers cannot reach them, and SOCKS5 proxies with a password are not supported. Don’t send a custom User-Agent; use the `user_agent` the API returns for later requests. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "CloudFlareTaskS3", "websiteURL": "https://example.com/", "proxy": "http://user:pass@proxy.example.com:8080", "waitLoad": false, "requiredCookies": [ "cf_clearance" ] } } ``` Then call `getTaskResult` every 5 seconds as for any asynchronous task; see [getTaskResult](https://docs.yescaptcha.com/en/api/get-task-result/). ## Result ```json { "errorId": 0, "status": "ready", "solution": { "cookies": { "cf_clearance": "zqKrlel6E6_SM2707VdArsu2c5.bYqLKU3DOl4tlkCE-1691687641-0-1-8d7f630c..." }, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "request_headers": { "accept-language": "en-US,en;q=0.9", "user-agent": "Mozilla/5.0 ..." }, "headers": { "server": "cloudflare" }, "content": "..." } } ``` | Field | Type | Description | | --- | --- | --- | | `cookies` | object | Cookies obtained after passing the check, usually including `cf_clearance`. Use them together with the returned `user_agent` and the proxy you supplied | | `user_agent` | string | The User-Agent used to pass the check; use it for all follow-up requests | | `request_headers` | object | Request headers sent when passing the check; reuse them in follow-up requests | | `headers` | object | Response headers from the target site | | `content` | string | HTML source of the target page | ## Using the result 1. Make later requests with the returned cookies, the returned `user_agent` **and** the same proxy you used for the task. Cloudflare expects all three to match. 2. Send the `request_headers` too where possible, and use a browser-like TLS fingerprint (for example curl\_cffi’s `impersonate` option). 3. `cf_clearance` stays valid for a while (up to an hour on some sites), so you don’t need to solve again within that time, but sending requests too fast may get the IP blocked by Cloudflare. --- # FunCaptcha > Get FunCaptcha (Arkose Labs) tokens with YesCaptcha. FunCaptchaTaskProxylessM1, FunCaptchaTask with your own proxy and FunCaptchaTaskProxyless; how to fill websitePublicKey, the API subdomain and blob data. Source: https://docs.yescaptcha.com/en/tasks/funcaptcha/ · Last verified: 2026-10-15 A FunCaptcha (Arkose Labs) task returns a token (`token`) that you submit to the target site to pass the check, with no puzzles to solve. `FunCaptchaTaskProxylessM1` costs 110 points (¥0.11) per task and `FunCaptchaTask` (your own proxy) costs 15 points (¥0.015); both are asynchronous: `createTask`, then `getTaskResult` every 5 seconds. Failed and timed-out tasks are refunded automatically. > **FunCaptchaTaskProxyless is being repaired:** The `FunCaptchaTaskProxyless` route has not produced successful results since around 2026-09-10 and is being repaired; its tasks fail and are refunded automatically. Until it is fixed, use `FunCaptchaTaskProxylessM1` or `FunCaptchaTask`. The fix will be announced in the [Service changelog](https://docs.yescaptcha.com/en/changelog/). - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON authenticated with your `clientKey`. Query results on the same endpoint you created the task on. ## When to use The page loads an Arkose Labs check (`arkoselabs.com`, `funcaptcha.com`), common on sign-up and login pages. Use this page to get a token; to solve the image puzzles yourself in a browser, use [FunCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/funcaptcha-classification/). ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `FunCaptchaTaskProxyless` | 30 points (¥0.03) | Asynchronous | | | `FunCaptchaTaskProxylessM1` | 110 points (¥0.11) | Asynchronous | | | `FunCaptchaTask` | 15 points (¥0.015) | Asynchronous | Own proxy | - `FunCaptchaTask` loads the captcha through your own proxy and needs the proxy fields and `userAgent`. - The three types take essentially the same parameters; compare pass rates and choose. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `websiteURL` | string | Yes | Full URL of the page that shows the captcha. Use the site you see the captcha on, not the captcha vendor's domain | | `websitePublicKey` | string | Yes | The FunCaptcha public key, the `data-pkey` value in the page or the part after `pkey=` in the request URL, e.g. `B7D8911C-5CC8-A9A3-35B0-554ACEE604DA` | | `funcaptchaApiJSSubdomain` | string | No | The subdomain that serves FunCaptcha; some sites use a custom one. Take it from the iframe URL, e.g. `client-api.arkoselabs.com` | | `data` | string | No | Extra blob data as a JSON string such as `{"blob":"..."}`. Pass it as is without URL encoding; omit if the page does not use it | | `userAgent` | string | Required for FunCaptchaTask | Browser User-Agent; must match the one you use to visit the target site | | `proxyType` | string | Required for FunCaptchaTask | Proxy protocol: `http`, `https`, `socks4` or `socks5` | | `proxyAddress` | string | Required for FunCaptchaTask | Proxy IP address or hostname. Local or private addresses such as 127.0.0.1 or 192.168.x.x will not work because our servers cannot reach them | | `proxyPort` | integer | Required for FunCaptchaTask | Proxy port | | `proxyLogin` | string | No | Proxy username, if the proxy requires authentication (FunCaptchaTask only) | | `proxyPassword` | string | No | Proxy password, if the proxy requires authentication (FunCaptchaTask only) | - `websiteURL`: the site where you see the captcha, not `funcaptcha.com` or `arkoselabs.com`. - `websitePublicKey`: the page’s `data-pkey` value, or the `pkey` value in a request such as `…/fc/api/nojs/?pkey=…`. - `funcaptchaApiJSSubdomain`: some sites load FunCaptcha from a custom subdomain; take it from the iframe URL, for example `client-api.arkoselabs.com`. - `data`: blob data the site passes to the captcha, as a JSON string like `{"blob":"..."}`. Pass it **exactly** as is; don’t encode or decode characters such as `%3D` and `%2B`. Omit it if you can’t find one. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "FunCaptchaTaskProxylessM1", "websiteURL": "https://example.com/signup", "websitePublicKey": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA", "funcaptchaApiJSSubdomain": "client-api.arkoselabs.com" } } ``` **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "FunCaptchaTaskProxylessM1", "websiteURL": "https://example.com/signup", "websitePublicKey": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA", "funcaptchaApiJSSubdomain": "client-api.arkoselabs.com" } }' curl -s https://api.yescaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "YOUR_CLIENT_KEY", "taskId": "TASK_ID"}' ``` **Python** solve.py ```python import os import time import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # Poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"] raise TimeoutError(task_id) solution = solve({ "type": "FunCaptchaTaskProxylessM1", "websiteURL": "https://example.com/signup", "websitePublicKey": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA", "funcaptchaApiJSSubdomain": "client-api.arkoselabs.com", }) print(solution["token"]) ``` **Node.js** solve.mjs ```js const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { taskId } = await call('createTask', { task }); for (let i = 0; i < 36; i++) { // Poll every 5 seconds, for up to about 3 minutes await new Promise((r) => setTimeout(r, 5000)); const result = await call('getTaskResult', { taskId }); if (result.status === 'ready') return result.solution; } throw new Error(`timeout: ${taskId}`); } const solution = await solve({ type: "FunCaptchaTaskProxylessM1", websiteURL: "https://example.com/signup", websitePublicKey: "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA", funcaptchaApiJSSubdomain: "client-api.arkoselabs.com", }); console.log(solution.token); ``` With your own proxy and blob data: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "FunCaptchaTask", "websiteURL": "https://example.com/signup", "websitePublicKey": "B7D8911C-5CC8-A9A3-35B0-554ACEE604DA", "data": "{\"blob\":\"BLOB_VALUE_FROM_THE_PAGE\"}", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36", "proxyType": "http", "proxyAddress": "proxy.example.com", "proxyPort": 8080, "proxyLogin": "user", "proxyPassword": "pass" } } ``` ## Result ```json { "errorId": 0, "status": "ready", "solution": { "token": "36859d1086acb06e7.08293101|r=ap-southeast-1|metabgclr=%23ffffff|..." } } ``` | Field | Type | Description | | --- | --- | --- | | `token` | string | The token to submit to the target site. Single use; submit it as soon as possible | While in progress you get `{"errorId": 0, "status": "processing"}`; check again 5 seconds later. Handle errors by `errorCode` as described in [Error codes](https://docs.yescaptcha.com/en/api/errors/). ## FAQ ### How long is a token valid? Single use. Submit it as soon as possible. ### Every task fails Check `websitePublicKey` and `funcaptchaApiJSSubdomain`. If the site requires blob data, `data` must be included and must not be re-encoded. `FunCaptchaTaskProxyless` keeps failing (and refunding) until it is repaired; use the other two types. --- # Image to text > Read the letters and digits in an image with YesCaptcha. ImageToTextTaskOcrBase and ImageToTextTaskMuggle return synchronously; ImageToTextTask and ImageToTextTaskM1 are asynchronous and support case, digits-only, math and length options; custom models available. Source: https://docs.yescaptcha.com/en/tasks/image-to-text/ · Last verified: 2026-10-15 Send a text captcha image as Base64 and get back the letters and digits in it (`solution.text`). `ImageToTextTaskOcrBase` costs 2 points (¥0.002) per image and is synchronous: a single `createTask` request returns the result. If you need options such as case sensitivity, digits only or math, use the asynchronous `ImageToTextTask`. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) The request body is JSON authenticated with your `clientKey`. ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `ImageToTextTaskOcrBase` | 2 points (¥0.002) | Synchronous | | | `ImageToTextTaskMuggle` | 2 points (¥0.002) | Synchronous | Does not support case/numeric options; use project\_name to select a custom model | | `ImageToTextTask` | 4 points (¥0.004) | Asynchronous | | | `ImageToTextTaskM1` | 15 points (¥0.015) | Asynchronous | | | You need | Use | | --- | --- | | Ordinary alphanumeric captchas, cheapest and fastest | `ImageToTextTaskOcrBase`, `ImageToTextTaskMuggle` (synchronous) | | A model trained for you | `ImageToTextTaskMuggle` with `project_name` | | Case sensitivity, digits only, math, length limits | `ImageToTextTask`, `ImageToTextTaskM1` (asynchronous) | The types use different models and routes, so results on the same kind of image may differ; test them and pick the best. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `body` | string | Yes | Base64-encoded image without the `data:image/...;base64,` prefix and without line breaks | | `project_name` | string | No | Name of a custom model, supported only by `ImageToTextTaskMuggle`. Omit to use the general alphanumeric model. Contact support for a custom model (ImageToTextTaskMuggle only) | | `phrase` | boolean | No | true means the answer contains at least one space (ImageToTextTask, ImageToTextTaskM1 only) | | `case` | boolean | No | true means the answer is case-sensitive (ImageToTextTask, ImageToTextTaskM1 only) | | `numeric` | integer | No | 0 no requirement; 1 digits only; 2 no digits (ImageToTextTask, ImageToTextTaskM1 only) | | `math` | boolean | No | true means the image is a math expression and the answer is its result (ImageToTextTask, ImageToTextTaskM1 only) | | `minLength` | integer | No | Minimum answer length; 0 means no limit (ImageToTextTask, ImageToTextTaskM1 only) | | `maxLength` | integer | No | Maximum answer length; 0 means no limit (ImageToTextTask, ImageToTextTaskM1 only) | `body` is the Base64 of the image file, without a `data:image/...;base64,` prefix and without line breaks. WebP images are converted automatically. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "ImageToTextTaskOcrBase", "body": "BASE64_IMAGE" } } ``` Complete code (reads `captcha.png` from the current directory): **curl** ```bash curl -s https://api.yescaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "ImageToTextTaskOcrBase", "body": "BASE64_IMAGE" } }' ``` **Python** solve.py ```python import os import base64 import requests API = "https://api.yescaptcha.com" CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] # Read the clientKey from an environment variable def call(method, payload): r = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30) data = r.json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def solve(task): return call("createTask", {"task": task})["solution"] # Base64-encode the image (no data: prefix) with open("captcha.png", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() solution = solve({ "type": "ImageToTextTaskOcrBase", "body": image_b64, }) print(solution["text"]) ``` **Node.js** solve.mjs ```js import { readFileSync } from 'node:fs'; const API = 'https://api.yescaptcha.com'; const CLIENT_KEY = process.env.YESCAPTCHA_CLIENT_KEY; // Read the clientKey from an environment variable async function call(method, payload) { const res = await fetch(`${API}/${method}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientKey: CLIENT_KEY, ...payload }), }); const data = await res.json(); if (data.errorId) throw new Error(`${data.errorCode}: ${data.errorDescription}`); return data; } async function solve(task) { const { solution } = await call('createTask', { task }); return solution; } // Base64-encode the image (no data: prefix) const imageB64 = readFileSync('captcha.png').toString('base64'); const solution = await solve({ type: "ImageToTextTaskOcrBase", body: imageB64, }); console.log(solution.text); ``` An asynchronous task with options: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "ImageToTextTask", "body": "BASE64_IMAGE", "case": true, "numeric": 0, "minLength": 4, "maxLength": 6 } } ``` ## Result Synchronous types return directly from `createTask`: ```json { "errorId": 0, "status": "ready", "solution": { "text": "LMResm" }, "taskId": "2376919c-1863-11ec-a012-94e6f7355a0b" } ``` Asynchronous types (`ImageToTextTask`, `ImageToTextTaskM1`) first return a `taskId`; poll `getTaskResult` every 5 seconds until the same `solution` arrives. | Field | Type | Description | | --- | --- | --- | | `text` | string | The recognized text | ## Custom models The general model works on any alphanumeric captcha but is slightly less accurate than a model trained for one style. If your images always look the same, [contact support](https://docs.yescaptcha.com/en/help/contact/) for a custom model and then select it with `ImageToTextTaskMuggle` and `project_name`. ## FAQ ### Am I charged when the text is wrong? Synchronous types are charged whenever a result is returned, even if it is wrong. Compare other types or ask for a custom model. ### I get `ERROR_ZERO_CAPTCHA_FILESIZE` or `ERROR_PARSE_IMAGE_FAIL` The Base64 is incomplete, or contains a `data:` prefix or line breaks. Check the encoding; see [Error codes](https://docs.yescaptcha.com/en/api/errors/). ## Related - [Quickstart](https://docs.yescaptcha.com/en/getting-started/quickstart/): a first request with `ImageToTextTaskOcrBase` - [Python samples](https://docs.yescaptcha.com/en/samples/python/) --- # reCAPTCHA v2 image recognition > Recognize reCAPTCHA v2 image challenges with YesCaptcha (ReCaptchaV2Classification). Upload a 3x3, 4x4 or 1x1 image with the question ID and get the tiles to click synchronously; priced by image size; question ID table. Source: https://docs.yescaptcha.com/en/tasks/recaptcha-classification/ · Last verified: 2026-10-15 `ReCaptchaV2Classification` recognizes the image challenges of reCAPTCHA v2: send the image and the question ID, and get back which tiles to click; your code does the clicking in the browser. It **does not return a token**. It is synchronous (one `createTask` request returns the result); a 3x3 or 4x4 image costs 6 points (¥0.006), and a 1x1 tile costs less (see the table). > **Tip:** If you’d rather not write clicking code, the [browser extension](https://docs.yescaptcha.com/en/extension/) does it automatically using this same API. - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `ReCaptchaV2Classification` | 6 points (¥0.006) | Synchronous | 2 points for a 1x1 tile (100x100); 6 points for 3x3 (300x300) and 4x4 (450x450) | ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `image` | string | Yes | Base64-encoded challenge image without the `data:` prefix | | `question` | string | Yes | Question ID such as `/m/0k4j`; see "Question IDs" on this page | | `confidence` | number | No | Confidence threshold from 0 to 1, only used for 3x3 images. If set (0.5 is a good start), every tile above it is returned; if omitted, the top 3 tiles are returned | Scale the image to a standard size; the server determines the challenge type from it: | Challenge | Image size | Returns | | --- | --- | --- | | 3x3 grid (“Select all images with …”) | 300 × 300 | `objects`: tiles to click | | 4x4 grid (“Select all squares with …”) | 450 × 450 | `objects`: tiles to click | | 1x1 tile (a single replacement image after clicking in a 3x3 grid) | 100 × 100 | `hasObject`: whether to click it | With screenshots, tell them apart by the wording: 3x3 says “Select all images with …”, 4x4 says “Select all squares with …”. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "ReCaptchaV2Classification", "image": "BASE64_IMAGE", "question": "/m/0k4j" } } ``` ## Result 3x3 and 4x4: ```json { "errorId": 0, "status": "ready", "solution": { "objects": [1, 5, 8], "type": "multi" }, "taskId": "3a9e8cb8-3871-11ec-9794-94e6f7355a0b" } ``` 1x1 tile: ```json { "errorId": 0, "status": "ready", "solution": { "hasObject": true, "type": "single" } } ``` | Field | Type | Description | | --- | --- | --- | | `objects` | array | Indexes of the tiles to click, starting at 0, left to right and top to bottom | | `hasObject` | boolean | Returned for a 1x1 tile; whether the tile contains the target | | `type` | string | Challenge type: `multi` (3x3 or 4x4 image, see `objects`), `single` (1x1 tile, see `hasObject`); `drag` for hCaptcha drag questions | Tiles are numbered from 0, left to right and top to bottom:   ## confidence: get every matching tile at once After you click a 3x3 grid, reCAPTCHA usually fades in new 1x1 tiles that also need checking. If those are hard to capture (for example in mobile apps), send `confidence`: - Without it, a 3x3 image returns the 3 highest-scoring tiles (reCAPTCHA requires at least 3 clicks). - With it (try `0.5`), every tile scoring above the value is returned, which may be more or fewer than 3; an empty array if none match. You no longer need to send the 1x1 tiles. - It has no effect on 4x4 and 1x1 images. ## Question IDs `question` is the question ID (starting with `/m/`), not the question text. The ID comes with the image in the response of the request reCAPTCHA uses to load the challenge (`reload` or `userverify`). Common questions: 16 in total | Question ID | Question (English) | | --- | --- | | `/m/0pg52` | `taxis` | | `/m/01bjv` | `bus` | | `/m/04_sv` | `motorcycles` | | `/m/013xlm` | `tractors` | | `/m/01jk_4` | `chimneys` | | `/m/014xcs` | `crosswalks` | | `/m/015qff` | `traffic lights` | | `/m/0199g` | `bicycles` | | `/m/015qbp` | `parking meters` | | `/m/0k4j` | `cars` | | `/m/015kr` | `bridges` | | `/m/019jd` | `boats` | | `/m/0cdl1` | `palm trees` | | `/m/09d_r` | `mountains or hills` | | `/m/01pns0` | `fire hydrant` | | `/m/01lynh` | `stairs` | No matching questions `ERROR_UNKNOWN_QUESTION` means the ID is wrong or not supported yet. `ERROR_UNKNOW_450x450_QUESTION` means the question isn’t supported on 4x4 images yet; reload the challenge on the page to get another one. ## Reports and refunds If the site rejects your clicks, report the tasks with [`report`](https://docs.yescaptcha.com/en/api/report/) within 1 hour; refunds are settled after about 24 hours. Rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). ## Related guides - [reCAPTCHA image clicking with Selenium](https://docs.yescaptcha.com/en/guides/recaptcha-click-selenium/) - [reCAPTCHA v2 (tokens)](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/) --- # hCaptcha image recognition > Recognize hCaptcha image challenges with YesCaptcha (HCaptchaClassification). Grid selection, click-a-position, drag-to-position and animated questions; synchronous, and free when no target is found. Source: https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/ · Last verified: 2026-10-15 `HCaptchaClassification` recognizes hCaptcha image challenges: send the question and images, and get back which images to select, which position to click, or where to drag from and to; your code performs the action in the browser. It **does not return a token**. It is synchronous, costs 8 points (¥0.008) per request, and is free when no target is found (empty result). > **Tip:** If you’d rather not write clicking code, the [browser extension](https://docs.yescaptcha.com/en/extension/) handles all of these question styles. For a token instead of click positions, use [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/). - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `HCaptchaClassification` | 8 points (¥0.008) | Synchronous | Not charged when no target is found | ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `queries` | array | Yes | List of Base64-encoded challenge images in page order (9 tiles for a 3×3 grid) | | `question` | string | No | The full question as shown on the page (Simplified Chinese or English recommended), e.g. `Please click each image containing a bicycle`. Send at least one of `question` and `anchors`; sending both is recommended | | `anchors` | array | No | Base64-encoded example images shown next to the question; required for questions that have them | - Send `question` exactly as shown on the page; there is no need to translate it, but switching hCaptcha to English or Simplified Chinese is recommended. New wordings are supported quickly; brand-new categories within 3 business days. - If the question shows example images next to it, send them in `anchors`. Questions that can only be answered from the example images fail without `anchors`. ## Grid selection The question reads “Please click each image containing …” above 9 images. Put the 9 images in `queries`, in page order: POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "HCaptchaClassification", "question": "Please click each image containing a bicycle", "queries": [ "BASE64_IMAGE_1", "BASE64_IMAGE_2" ] } } ``` Result: ```json { "errorId": 0, "status": "ready", "solution": { "objects": [true, false, false, true, true, false, true, true, false], "top_k": [0, 3, 4, 6, 7], "confidences": [1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0] } } ``` `objects` and `top_k` carry the same information: the first says for each image whether it is a target, the second lists the target indexes (from 0). Click those images. ## Click a position The question reads “Please click on …” above one large image, and you click one or more positions on it. 1. Take `question` from the page; put any example images in `anchors`. 2. Put one image in `queries`: ideally the original exported from the canvas (JPG recommended). If you can only screenshot, capture exactly the large image area, no more and no less. 3. `box` in the result lists the coordinates to click as x1, y1, x2, y2, …, from the top-left of the uploaded image. 4. If the uploaded image’s size differs from its size on the page, scale: page x = returned x × displayed width ÷ uploaded width (same for y). For example, x = 769 on a 1000-px-wide upload shown 350 px wide is 769 × 350 ÷ 1000 ≈ 269 on the page. POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "HCaptchaClassification", "question": "Please click on the entity present in the sample image.", "anchors": [ "BASE64_ANCHOR_1", "BASE64_ANCHOR_2", "BASE64_ANCHOR_3" ], "queries": [ "BASE64_OF_THE_BIG_IMAGE" ] } } ``` Result: ```json { "errorId": 0, "status": "ready", "solution": { "box": ["221", "213"] } } ``` When several targets need clicking, `box` holds several coordinate pairs: `["221", "213", "340", "118", ...]`. ## Drag to a position The question reads “Drag … to …”, and you drag pieces on the right to their place in the picture. 1. Take `question` from the page. 2. Put one screenshot in `queries` that shows **both** the pieces and their destinations, with each side at least 260 px. 3. Each item of `box` in the result is one drag: `start` is where the piece is, `end` is where to drop it. With several pieces, drag them one by one. ```json { "errorId": 0, "status": "ready", "solution": { "type": "drag", "box": [{ "start": [644, 218], "end": [239, 315] }] } } ```  If you have protocol data (piece images, piece coordinates and the background) instead of a screenshot, paste the pieces onto the background at their coordinates to make an image that looks like the screenshot, then send it. ## Animated questions For animated challenge images, send the animation (GIF or similar) Base64-encoded in `queries`. An animation of at least 3 seconds, ideally 5 to 6, at about 12 FPS works best. ## Reports and refunds If the site rejects your clicks, report the tasks with [`report`](https://docs.yescaptcha.com/en/api/report/) within 1 hour; refunds are settled after about 24 hours. Rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). ## Related guides - [hCaptcha image clicking with Selenium](https://docs.yescaptcha.com/en/guides/hcaptcha-click-selenium/) --- # FunCaptcha image recognition > Recognize FunCaptcha (Arkose Labs) image puzzles with YesCaptcha (FunCaptchaClassification). Upload the 6-tile image and the English question, and get the image to pick synchronously; examples of supported questions. Source: https://docs.yescaptcha.com/en/tasks/funcaptcha-classification/ · Last verified: 2026-10-15 `FunCaptchaClassification` recognizes FunCaptcha (Arkose Labs) image puzzles: send the puzzle image and the English question, and get back which image to pick; your code clicks it in the browser. It **does not return a token**. It is synchronous and costs 3 points (¥0.003) per request. > **Tip:** For a token instead of click positions, use [FunCaptcha](https://docs.yescaptcha.com/en/tasks/funcaptcha/). Without code, use the [browser extension](https://docs.yescaptcha.com/en/extension/). - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `FunCaptchaClassification` | 3 points (¥0.003) | Synchronous | | ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `image` | string | Yes | Base64-encoded challenge image without the `data:` prefix | | `question` | string | Yes | The question text in English (e.g. `Pick the image that is the correct way up`); supported questions are listed on this page | - `image` contains only the puzzle images (usually a 6-tile grid), without the title or buttons above it. Make sure screenshots are complete; a missing part hurts accuracy. Vertical 6-tile layouts can be uploaded as they are. - `question` is the full English question exactly as shown, with correct capitalization; don’t translate it yourself. If the page is in another language, switch the captcha to English first. The server picks the puzzle type from the question, so it must be exact. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "FunCaptchaClassification", "image": "BASE64_IMAGE", "question": "Pick the bread" } } ``` ## Result ```json { "errorId": 0, "status": "ready", "solution": { "objects": [4], "labels": ["parrot", "panda", "octopus", "owl", "bread", "dog"] }, "taskId": "04a3fa76-11a0-11ed-a58c-0ef20f419382" } ``` | Field | Type | Description | | --- | --- | --- | | `objects` | array | Index of the image to select, starting at 0, left to right and top to bottom | | `labels` | array | Recognized labels | `objects: [4]` means pick the 5th image (indexes start at 0, left to right and top to bottom). A challenge often has several rounds in a row; capture and send each round separately. ## Supported questions These are examples. **Questions not listed are supported too**; just send the question from the page. If a new question returns `ERROR_UNKNOWN_QUESTION`, [contact support](https://docs.yescaptcha.com/en/help/contact/). 103 in total | Example | Question (English) | | --- | --- | |  | `Pick the bread` | |  | `Pick one square that shows two identical objects` | |  | `Pick one square that shows two identical objects` | |  | `Pick the penguin` | |  | `Pick the shadow with a different object silhouette` | |  | `Pick the dice pair with the same icon facing up` | |  | `Pick the dice pair whose top sides add up to 14` | |  | `Pick the matching cards` | |  | `Pick the animal looking at the shape that matches the shape it's standing on` | |  | `Pick one square that shows three of the same object.` | |  | `Pick the mouse that can reach all the cheese in the maze` | |  | `Pick the mouse that can't reach the cheese` | |  | `Pick the image where the darts add up to 10` | |  | `Pick the image that is the correct way up` | |  | `Pick the dice pair whose top sides add up to 5` | |  | `Pick the wrong shadow` | |  | `Select the animal with the wrong head` | |  | `Pick the shadow that mathes the icons at the top of the image` | |  | `Pick the spiral galaxy` | |  | `Pick the image where all animals are walking in the same direction as the arrow` | |  | `Select the image with the icon order Chair then Fence` | |  | `Select the image where the total fingers add up to 4` | |  | `Select the image where the total fingers add up to 3` | |  | `Pick any square` | |  | `Select an image of three circles in any direction on a straight line` | |  | `Pick the image with 3 crosses in a row in any direction` | |  | `Pick the image where the number matches the amount of animals` | |  | `Pick the distorted object` | |  | `Pick the object that is not distorted` | |  | `Select the animal with the wrong head` | |  | `Pick the image with only one rope` | |  | `Pick the image where the darts add up to 8` | |  | `Pick the image of the brick cube and the striped heart` | |  | `Pick the image of the brick cube and the striped sphere` | |  | `Pick the image of the brick heart and the striped heart` | |  | `Pick the image of the brick sphere and the checkered heart` | |  | `Pick the image of the checkered cone and the checkered sphere` | |  | `Pick the image of the fuzzy cone and the brick sphere` | |  | `Pick the image of the fuzzy cube and the checkered cube` | |  | `Pick the image of the fuzzy heart and the brick heart` | |  | `Pick the image of the fuzzy heart and the striped heart` | |  | `Pick the image of the fuzzy cube and the striped cube` | |  | `Pick the image of the striped cone and the checkered cube` | |  | `Pick the image of the brick cone and the striped cone` | |  | `Pick the image of the striped cube and the checkered cube` | |  | `Pick the image of the fuzzy sphere and the striped cone` | |  | `Pick the image of the striped cube and the checkered sphere` | |  | `Pick the image of the striped cube and the checkered heart` | |  | `Pick the image of the brick cone and the checkered cube` | |  | `Pick the image of the striped heart and the checkered cube` | |  | `Pick the image of the brick cone and the checkered sphere` | |  | `Pick the image of the fuzzy sphere and the striped cube` | |  | `Pick the image of 2 striped shapes` | |  | `Pick the image of 2 checkered shapes` | |  | `Pick the image with the matching reflection` | |  | `Pick the image of the person walking up the stairs` | |  | `Pick the image of the person walking down the stairs` | |  | `Pick the cube with icons split in half` | |  | `Pick the puzzle with the wrong pieces` | |  | `Use the arrows to rotate the animal to face in the direction of the hand` | |  | `Change the dice until the count matches the image on the left` | |  | `Use the arrows to change the number of objects until it matches the left image` | |  | `Use the arrows to place the train on the coordinate point shown in the picture on the left` | |  | `Use the arrows to move the train to the coordinates shown in the picture on the left` | |  | `Using the arrows, move the person to the indicated seat` | |  | `Use the arrows to move the person to the spot indicated by the cross` | |  | `Use the arrows to move the person to the icon indicated by the colored circle` | |  | `Using the arrows, connect the same two icons with the dotted line as shown on the left` | |  | `Use the arrows to move the train into the position indicated in the left image` | |  | `Use the buttons to place the indicated car, in the correct position in the race` | |  | `Use the arrows to rotate the animal with the same icon to face where the hand is pointing` | |  | `Use the arrows to rotate the object to face in the direction of the hand` | |  | `Use the arrows to find the room that matches the left image` | |  | `Using the arrows, pick the group of rocks that has the amount indicated on the left` | |  | `using the arrows, find the image where one of the towers of rocks contains the exact amount shown on the left` | |  | `Use the arrows to rotate the object to face in the direction of the hand` | |  | `use the arrows to find the distance between the two cars that matches the left image` | |  | `use the arrows to choose the image where all the darts add up to the number in the left image` | |  | `use the arrows to find the image where the number on each ring adds up to the number on the left` | |  | `use the arrows to move the icon into the indicated orbit` | |  | `click on the arrows to view different images when the image matches the example on the left, click submit!` | |  | `use the arrows to find the jigsaw puzzle that is missing the puzzle piece shown on the left` | |  | `use the arrows to pick the image where the object directly below the arrow matches the left image` | |  | `match the icon on the left with the icon on the top of the dice` | |  | `find the image that has the prize on the left held by the claw in the machine on the right` | |  | `click on the arrows to view different images when the image matches the example on the left, click submit!` | |  | `find the image where the rat can reach the exact amount of cheese as the image on the left.` | |  | `use the arrows to find the basket picture with the same content as shown on the left` | |  | `use the arrows to match the number of pins that fall with the number shown on the left` | |  | `use the arrows to choose the image where the winner has the icon shown in the image on the left` | |  | `use the arrows to select the image where the character is pointing to the shortest route, as shown in the leftmost image` | |  | `select the constellation that most closely resembles the image shown on the left` | |  | `use the arrows to select the image that has the icons in the same order as in the leftmost image` | |  | `use the arrows to select the image where all the lines are connected to the matching icon` | |  | `use the arrows to find the image where the red striped pins completely overlap with the boat on the left` | |  | `use the arrows to match the symbol on the left with the cup containing the most liquid` | |  | `use the arrows to move the characters until they are standing on the same icons as in the picture on the left` | |  | `use arrows to find the shape whose number of sides equals the number shown on the left` | |  | `use the arrows to choose the image where the falling balloon has the same icon as shown on the left` | |  | `use the arrows to move the character across tiles that have the same icons as shown on the left` | |  | `use the arrows to find the image where the number of symbols on the tops of the dice exactly matches the image on the left` | |  | `use the arrows to match the icon inside the bubble with the one shown on the left` | |  | `using the arrows, find the group of icons that the icon on the left would best fit in` | No matching questions ## Reports and refunds If the final submission fails and you don’t know which round was wrong, report the whole group of task IDs with [`report`](https://docs.yescaptcha.com/en/api/report/) within 1 hour; refunds are settled after about 24 hours. Rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). --- # AWS WAF / bCaptcha image recognition > Recognize AWS WAF CAPTCHA and bCaptcha 3x3 image challenges with YesCaptcha (AwsClassification, bCaptchaClassification). Upload the whole image and the question, and get the cells to click synchronously. Source: https://docs.yescaptcha.com/en/tasks/aws-bcaptcha-classification/ · Last verified: 2026-10-15 `AwsClassification` recognizes AWS WAF CAPTCHA 3x3 image challenges and `bCaptchaClassification` recognizes bCaptcha 3x3 image challenges: send the whole image and the question, and get back which cells to click; your code clicks them in the browser. They **do not return a token**. They are synchronous and cost 8 points (¥0.008) per request. Without code, use the [browser extension](https://docs.yescaptcha.com/en/extension/). - POST `https://api.yescaptcha.com/createTask` (Global endpoint) - POST `https://cn.yescaptcha.com/createTask` (China endpoint) ## Task types and pricing | Task type | Price | Mode | Notes | | --- | --- | --- | --- | | `AwsClassification` | 8 points (¥0.008) | Synchronous | | | `bCaptchaClassification` | 8 points (¥0.008) | Synchronous | | The two types take the same parameters and return the same format; choose by where the captcha comes from: `AwsClassification` for AWS WAF, `bCaptchaClassification` for bCaptcha. ## Request parameters | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | Yes | Task type; see "Task types and pricing" on this page | | `queries` | string | Yes | Base64 of the whole 3×3 grid image (a single image) | | `question` | string | No | The full question as shown on the page, e.g. `Select all hats`; other languages are translated automatically | `queries` is the **whole** 3x3 image (one image, not 9 tiles). Take `question` from the page as is; English and Chinese both work, and other languages are translated automatically. ## Request example POST https://api.yescaptcha.com/createTask ```json { "clientKey": "YOUR_CLIENT_KEY", "task": { "type": "AwsClassification", "queries": "BASE64_IMAGE", "question": "Select all hats" } } ``` ## Result ```json { "errorId": 0, "status": "ready", "solution": { "label": "Select All Hats", "objects": [false, true, false, false, true, true, true, true, false], "top_k": [1, 4, 5, 6, 7], "confidences": [0.0, 1.0, 0.0, 0.255, 1.0, 1.0, 0.9637, 0.9999, 0.0] }, "taskId": "2053f690-3c3b-11f0-8ffb-d2c180657082" } ``` | Field | Type | Description | | --- | --- | --- | | `label` | string | The recognized target of the question | | `objects` | array | Whether each of the 9 cells is a target (true / false), left to right and top to bottom | | `top_k` | array | Indexes (from 0) of the images that are targets; same meaning as `objects`, use either | | `confidences` | array | Confidence of each result | The 9 cells are numbered 0 to 8, left to right and top to bottom. `objects` and `top_k` carry the same information; use either: click the cells where `objects` is `true`, or the indexes in `top_k`. ## Reports and refunds If the site rejects your clicks, report the tasks with [`report`](https://docs.yescaptcha.com/en/api/report/) within 1 hour; refunds are settled after about 24 hours. Rules: [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). --- # YesCaptcha Assistant > YesCaptcha Assistant, the browser extension for Chrome and Firefox that recognizes and clicks reCAPTCHA, hCaptcha, FunCaptcha, AWS WAF and other captchas. The extension is free; you pay for the API calls it makes. Store links and package downloads. Source: https://docs.yescaptcha.com/en/extension/ · Last verified: 2026-10-15 YesCaptcha Assistant is a browser extension for Chrome and Firefox. When a page shows a captcha, it sends the challenge to YesCaptcha for recognition and clicks automatically, with no code. The extension is free; recognition is charged at the price of the API types it uses, from the same account and balance as the API. ## What it does - Recognizes and clicks the image challenges of reCAPTCHA v2, hCaptcha, FunCaptcha, AWS WAF and bCaptcha. - Text captchas: right-click the image and choose “Mark as captcha source”, then right-click the input box and choose “Put captcha answer here”; the extension reads the image and fills in the answer. - Each captcha type can be switched on or off in the settings, and click speed and retries can be adjusted. - Not every site can be passed; try it first. ## Install **From the store (recommended; updates automatically):** - Chrome (and Chromium-based browsers such as Edge): [Chrome Web Store](https://chromewebstore.google.com/detail/yescaptcha-assistant/jiofmdifioeejeilfkpegipdjiopiekl) - Firefox: [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/yescaptcha-assistant/) **If you can’t reach the store, download the package:** Chrome Version 1.4.9 Size 1.1 MB Updated 2026-10-05 [Download](https://docs.yescaptcha.com/downloads/yescaptcha-assistant-chrome-1.4.9.zip)[Chrome Web Store](https://chromewebstore.google.com/detail/yescaptcha-assistant/jiofmdifioeejeilfkpegipdjiopiekl) Firefox Version 0.4.6 Size 0.9 MB [Download](https://docs.yescaptcha.com/downloads/yescaptcha-assistant-firefox-0.4.6.xpi)[Firefox Add-ons](https://addons.mozilla.org/firefox/addon/yescaptcha-assistant/) The Firefox store may lag behind the package here; use the package for the latest version. ### Installing the Chrome package 1. Download the zip and extract it to a permanent folder (don’t delete or move it afterwards). 2. Open `chrome://extensions` and turn on “Developer mode” in the top right. 3. Click “Load unpacked” and choose the extracted folder. 4. Click the extension icon in the toolbar and enter your `clientKey`. Packages installed this way don’t update automatically; download the new version when one is released. ### Installing the Firefox package 1. Download the `.xpi` file. 2. Open `about:addons`, click the gear icon and choose “Install Add-on From File…”, then select the file. 3. Click the extension icon in the toolbar and enter your `clientKey`. ## Set up 1. Sign up and top up at [yescaptcha.com](https://yescaptcha.com/), then copy your `clientKey` from the dashboard; see [Quickstart](https://docs.yescaptcha.com/en/getting-started/quickstart/). 2. Click the extension icon and enter the key in the settings panel. When your balance appears, you’re set. 3. Open a page with a captcha; recognition starts automatically. ## Cost The extension is free. Recognition is charged per the task types used: reCAPTCHA image challenges at [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/) prices, hCaptcha at [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/) prices, and so on. Wrong results can be reported for refunds; see [Billing and refunds](https://docs.yescaptcha.com/en/getting-started/billing/). --- # Identify the captcha type > How to tell which captcha a page uses (reCAPTCHA v2, invisible v2, v3, Enterprise, hCaptcha, Cloudflare Turnstile vs the challenge page) and which YesCaptcha task type to use. Source: https://docs.yescaptcha.com/en/guides/identify-captcha/ · Last verified: 2026-10-15 Choosing the right task type starts with recognizing the captcha. The most reliable way is to open the browser’s developer tools (F12) and see in the Network panel which captcha script the page loads; you can also tell by appearance. ## Quick reference | What you see | What it is | Task type | | --- | --- | --- | | An “I’m not a robot” checkbox | reCAPTCHA v2 | [reCAPTCHA v2](https://docs.yescaptcha.com/en/tasks/recaptcha-v2/) | | No checkbox; an image challenge appears after you click submit; a small reCAPTCHA badge in the corner | Invisible reCAPTCHA v2 (or v3) | See “reCAPTCHA versions” below | | No interaction at all; only the reCAPTCHA badge | reCAPTCHA v3 | [reCAPTCHA v3](https://docs.yescaptcha.com/en/tasks/recaptcha-v3/) | | An “I am human” checkbox; image challenges branded hCaptcha | hCaptcha | [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/) | | A Cloudflare widget inside a form; the page stays put after the check | Cloudflare Turnstile | [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/) | | The whole page shows “Just a moment…” / “Checking your connection” and then redirects | Cloudflare challenge page | [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/) | | Arkose Labs puzzles (such as “Pick the image that is the correct way up”) | FunCaptcha | [FunCaptcha](https://docs.yescaptcha.com/en/tasks/funcaptcha/) | | An image of distorted letters and digits | Text captcha | [Image to text](https://docs.yescaptcha.com/en/tasks/image-to-text/) | ## reCAPTCHA versions Search the Network panel for `api.js` or `enterprise.js`: | Script loaded | Version | | --- | --- | | `recaptcha/api.js` with no `render` parameter or `render=explicit` | v2 | | As above, and the `anchor` request URL contains `size=invisible` | Invisible v2: add `"isInvisible": true` | | `recaptcha/api.js?render=SITE_KEY` (`render` is not `explicit`) | v3 | | `recaptcha/enterprise.js` with no `render` parameter or `render=explicit` | v2 Enterprise | | `recaptcha/enterprise.js?render=SITE_KEY` | v3 Enterprise | Examples: ```text https://www.google.com/recaptcha/api.js?onload=onloadcallback&render=explicit → v2 https://www.google.com/recaptcha/api.js?render=6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696 → v3 https://www.google.com/recaptcha/enterprise.js?render=explicit → v2 Enterprise ``` Invisible v2 sometimes passes only with a v3 type; try both. You can also run this in the browser console. It lists every reCAPTCHA on the page with its version, site key, page URL and callback: find-recaptcha-clients.js ```js // Paste into the browser DevTools console on a page with reCAPTCHA, then run findRecaptchaClients(). // Lists every reCAPTCHA on the page: version (V2/V3), sitekey, page URL and the callback function. function findRecaptchaClients() { if (typeof ___grecaptcha_cfg === 'undefined') return []; return Object.entries(___grecaptcha_cfg.clients).map(([cid, client]) => { const data = { id: cid, version: cid >= 10000 ? 'V3' : 'V2' }; const objects = Object.entries(client).filter(([, value]) => value && typeof value === 'object'); objects.forEach(([toplevelKey, toplevel]) => { const found = Object.entries(toplevel).find( ([, value]) => value && typeof value === 'object' && 'sitekey' in value && 'size' in value, ); if (toplevel instanceof HTMLElement && toplevel.tagName === 'DIV') data.pageurl = toplevel.baseURI; if (found) { const [sublevelKey, sublevel] = found; data.sitekey = sublevel.sitekey; const callbackKey = data.version === 'V2' ? 'callback' : 'promise-callback'; const callback = sublevel[callbackKey]; if (!callback) { data.callback = null; data.function = null; } else { data.function = callback; const keys = [cid, toplevelKey, sublevelKey, callbackKey].map((key) => `['${key}']`).join(''); data.callback = `___grecaptcha_cfg.clients${keys}`; } } }); return data; }); } findRecaptchaClients(); ``` Example output: ```json [ { "id": "0", "version": "V2", "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", "function": "onSuccess", "callback": "___grecaptcha_cfg.clients['0']['l']['l']['callback']", "pageurl": "https://www.google.com/recaptcha/api2/demo" } ] ``` Google’s demo pages are useful for comparison: v2 `https://www.google.com/recaptcha/api2/demo`, invisible v2 `https://www.google.com/recaptcha/api2/demo?invisible=true`. ## Turnstile vs the challenge page Both come from Cloudflare, but they are different: - **Turnstile** is a widget embedded in a page’s form. After verification it shows a check mark and the page stays where it is. The page loads `challenges.cloudflare.com/turnstile/v0/api.js`. Use [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/). - **The challenge page** replaces the whole page with Cloudflare’s “Just a moment…” / “example.com needs to review the security of your connection” screen, which may also contain a widget; after passing, it redirects to the real page. The source contains `__cf_chl_rt_tk` or `cdn-cgi/challenge-platform`. Use [Cloudflare challenge page](https://docs.yescaptcha.com/en/tasks/cloudflare-challenge/). If your program gets a 403 with “Just a moment…” but a browser opens the page directly, you’re probably only being blocked by TLS fingerprinting. A library that imitates a browser’s TLS fingerprint (such as curl\_cffi) usually fixes it without solving anything. --- # Find reCAPTCHA parameters > How to find reCAPTCHA's websiteKey (sitekey), websiteURL, the v3 pageAction and the callback function in the browser's Network, Sources and Console panels, with a script that finds them automatically. Source: https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/ · Last verified: 2026-10-15 A reCAPTCHA task needs `websiteURL` (the page showing the captcha) and `websiteKey` (the site key); v3 also needs `pageAction`. When you drive a browser with Selenium or similar, you also need the callback function. All of these can be found with the browser’s developer tools (F12). ## The fastest way: a lookup script Open the page with the captcha, open the Console (F12), paste this and run it: find-recaptcha-clients.js ```js // Paste into the browser DevTools console on a page with reCAPTCHA, then run findRecaptchaClients(). // Lists every reCAPTCHA on the page: version (V2/V3), sitekey, page URL and the callback function. function findRecaptchaClients() { if (typeof ___grecaptcha_cfg === 'undefined') return []; return Object.entries(___grecaptcha_cfg.clients).map(([cid, client]) => { const data = { id: cid, version: cid >= 10000 ? 'V3' : 'V2' }; const objects = Object.entries(client).filter(([, value]) => value && typeof value === 'object'); objects.forEach(([toplevelKey, toplevel]) => { const found = Object.entries(toplevel).find( ([, value]) => value && typeof value === 'object' && 'sitekey' in value && 'size' in value, ); if (toplevel instanceof HTMLElement && toplevel.tagName === 'DIV') data.pageurl = toplevel.baseURI; if (found) { const [sublevelKey, sublevel] = found; data.sitekey = sublevel.sitekey; const callbackKey = data.version === 'V2' ? 'callback' : 'promise-callback'; const callback = sublevel[callbackKey]; if (!callback) { data.callback = null; data.function = null; } else { data.function = callback; const keys = [cid, toplevelKey, sublevelKey, callbackKey].map((key) => `['${key}']`).join(''); data.callback = `___grecaptcha_cfg.clients${keys}`; } } }); return data; }); } findRecaptchaClients(); ``` In the output, `sitekey` is the `websiteKey`, `pageurl` is the `websiteURL`, `version` tells v2 from v3, and `function` and `callback` are the callback: ```json [ { "id": "0", "version": "V2", "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", "function": "onSuccess", "callback": "___grecaptcha_cfg.clients['0']['l']['l']['callback']", "pageurl": "https://www.google.com/recaptcha/api2/demo" } ] ``` An empty array means reCAPTCHA hasn’t loaded yet; run it again once the captcha appears. ## websiteKey and websiteURL In the Network panel, search for `anchor` and find a request like: ```text https://www.google.com/recaptcha/api2/anchor?ar=1&k=6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9&co=...&hl=en&size=normal ``` - The value after `k=` is the `websiteKey`. - `websiteURL` is the full URL of the page showing the captcha (usually this request’s `Referer`). You can also search the page source for `data-sitekey`. ## pageAction (v3) `pageAction` is the `action` the page passes in `grecaptcha.execute(SITE_KEY, {action: '...'})`, and it must match. **Method 1: search the source.** In the Sources panel, right-click and choose “Search in all files”. Search `.execute(` for v3, or `.enterprise.execute` for v3 Enterprise, and look at the `action` that follows: ```js grecaptcha.ready(function () { grecaptcha.execute('6LdpS-gUAAAAAL3Qr2yP7rkrQjkKBVvEY_48JS5l', { action: 'login' }).then(function (token) { // ... }); }); ``` Here `pageAction` is `login`. **Method 2: a breakpoint.** If the code is obfuscated and search finds nothing, run `debug(grecaptcha.execute)` in the console (`debug(grecaptcha.enterprise.execute)` for Enterprise), then do whatever triggers verification on the page (for example click “Log in”). When the debugger stops, read `action` in the Scope panel. A site may use different actions at different steps (for example `signup/submit_email` and then `signup/success`); use the one for the step you need to pass. Press F8 to continue to the next call. ## Callback function When you put a token into a page with Selenium or similar, you then call the page’s callback to tell it verification is complete: - Search the Elements panel for `data-callback`; its value is the function name, for example `data-callback="onSuccess"`. - Or search for `grecaptcha.render` and read the `callback` option. - Or inspect `___grecaptcha_cfg.clients` in the console, or use the lookup script above. Calling it: ```python driver.execute_script("onSuccess(arguments[0])", g_recaptcha_response) ``` Some pages have no callback; put the token into the `g-recaptcha-response` textarea and submit the form. The full flow: [Submit a reCAPTCHA token](https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/). --- # Find hCaptcha parameters > How to find hCaptcha's websiteKey (sitekey), websiteURL and the Enterprise rqdata. Search the page source for data-sitekey, or the Network panel for checksiteconfig requests. Source: https://docs.yescaptcha.com/en/guides/find-hcaptcha-parameters/ · Last verified: 2026-10-15 An [hCaptcha](https://docs.yescaptcha.com/en/tasks/hcaptcha/) task needs `websiteURL` (the page showing the captcha) and `websiteKey` (the site key, a UUID); Enterprise sites sometimes also need `rqdata`. All can be found with the browser’s developer tools (F12). ## websiteKey **Method 1: page source.** In the Elements panel press Ctrl+F (Cmd+F on Mac) and search for `data-sitekey`: ```html
``` The `data-sitekey` value is the `websiteKey`. **Method 2: network requests.** In the Network panel search for `hcaptcha` and find the `checksiteconfig` request; the value after `sitekey=` is the `websiteKey`: ```text https://api.hcaptcha.com/checksiteconfig?v=...&host=example.com&sitekey=51829642-2cda-4b09-896c-594f89d700cc&sc=1&swa=1 ``` ## websiteURL The full URL of the page that shows the captcha, **not** `hcaptcha.com`. The `host=` in the request above is that page’s domain. ## rqdata (Enterprise) Some sites use hCaptcha Enterprise and issue an `rqdata` value each time the captcha loads; without it the token won’t pass. It usually appears in a response from the site’s own API (for example a `captcha_rqdata` field returned by a login call), or is passed to `hcaptcha.render` / `hcaptcha.setData`. Put it in the task’s `rqdata` field. It is usually single use, so fetch a fresh one each time. ## userAgent `userAgent` must be the value returned by [`/useragent`](https://docs.yescaptcha.com/en/api/useragent/); submit the token with the `userAgent` returned in the result. --- # Find Turnstile parameters > How to find Cloudflare Turnstile's websiteKey (sitekey, starting with 0x) and websiteURL. Search the page source for data-sitekey or turnstile.render, or check challenges.cloudflare.com requests in the Network panel. Source: https://docs.yescaptcha.com/en/guides/find-turnstile-parameters/ · Last verified: 2026-10-15 A [Turnstile](https://docs.yescaptcha.com/en/tasks/turnstile/) task needs `websiteURL` (the page showing the widget) and `websiteKey` (the site key, usually starting with `0x`). First make sure it is Turnstile and not the challenge page; see [Identify the captcha type](https://docs.yescaptcha.com/en/guides/identify-captcha/). ## websiteKey **Method 1: page source.** In the Elements panel of the developer tools (F12), search for `data-sitekey`: ```html ``` **Method 2: scripts.** If the widget is rendered with JavaScript, right-click in the Sources panel, choose “Search in all files”, search for `turnstile.render`, and read `sitekey` in its options: ```js turnstile.render('#container', { sitekey: '0x4AAAAAAAxxxxxxxxxxxxxx', callback: onDone }); ``` **Method 3: network requests.** Search the Network panel for `challenges.cloudflare.com`; the widget’s iframe URL contains the site key starting with `0x`. ## websiteURL The full URL of the page that shows the widget, for example `https://example.com/login`. ## Submitting the token When the task is done, put `token` into the form’s hidden field named `cf-turnstile-response` (if the page uses `turnstile.render` with a `callback`, call that callback with the token), then submit the form. Use the result’s `userAgent` as the User-Agent of the submission. --- # Submit a reCAPTCHA token > What to do with a reCAPTCHA token (gRecaptchaResponse). How it works, submitting it with a plain HTTP request (the g-recaptcha-response field), or filling it into the page and calling the callback, with complete Python examples on Google's demo page. Source: https://docs.yescaptcha.com/en/guides/submit-recaptcha-token/ · Last verified: 2026-10-15 The `gRecaptchaResponse` YesCaptcha returns is the same value Google hands to a page after someone completes the captcha. Once you have it, you must submit it **to the target site** (not to Google or YesCaptcha) the same way a browser would; the site verifies it with Google and lets you through. There are two ways: send the request yourself, or put the token into the page in a real browser and submit. ## How it works Normally: 1. The page loads reCAPTCHA and the user completes it; 2. Google gives the page a token, which the page puts in the `g-recaptcha-response` textarea (or passes to a callback); 3. The user submits the form and the token goes to the site’s server with it; 4. The site’s server verifies the token with Google and lets the user through. With YesCaptcha, steps 1 and 2 are done for you: create a task with `websiteURL` and `websiteKey`, get the token, and continue from step 3. Tokens are single use and valid for about 120 seconds; submit within 60 seconds. ## Method 1: send the request yourself (recommended) 1. Do it once by hand in a browser: open the Network panel (F12), complete the captcha, submit, and find the request that submits the form. 2. In its Payload (or Form Data), find the field carrying the token, usually `g-recaptcha-response`, with a value starting with `03A`. Some sites rename it, for example `grecaptcharesponse` or `captcha`. 3. Send the same request from your program with that field set to the YesCaptcha token. The other fields, cookies and headers must also match the browser’s, since sites often check them too. A complete example on Google’s demo page: get a token, then post it back to the demo page in the `g-recaptcha-response` field: recaptcha_requests.py ```python """Solve reCAPTCHA v2 on Google's demo page and submit the token with plain HTTP (no browser). Run: pip install requests export YESCAPTCHA_CLIENT_KEY=your_client_key python recaptcha_requests.py Each run creates one NoCaptchaTaskProxyless task (charged per the price list). """ import os import time import requests CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] API = "https://api.yescaptcha.com" WEBSITE_URL = "https://www.google.com/recaptcha/api2/demo" WEBSITE_KEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-" def call(method, payload): data = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30).json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def get_token(): task = {"type": "NoCaptchaTaskProxyless", "websiteURL": WEBSITE_URL, "websiteKey": WEBSITE_KEY} task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): # poll every 5 seconds, for up to about 3 minutes time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"]["gRecaptchaResponse"] raise TimeoutError(task_id) token = get_token() print("token:", token[:40], "...") # Submit the token the same way the browser does: the demo form posts the field # "g-recaptcha-response" back to the page. Check your own site's request in DevTools > Network. page = requests.post(WEBSITE_URL, data={"g-recaptcha-response": token}, timeout=30) print("passed" if "Verification Success" in page.text else "not passed", page.status_code) ``` ## Method 2: fill it into the page (Selenium and similar) When you drive a real browser with Selenium, Playwright and similar tools: 1. Read `data-sitekey` from the page and create a task with it to get a token. 2. Write the token into the page’s `g-recaptcha-response` textarea. 3. If the page has a callback (`data-callback="..."`), call it with the token; on some sites the submit button only becomes clickable after the callback runs. 4. Submit the form. ```js // Step 2: write the token (run in the page) document.getElementById('g-recaptcha-response').value = 'TOKEN'; // Step 3: call the callback if there is one, e.g. data-callback="onSuccess" onSuccess('TOKEN'); ``` With several reCAPTCHAs on a page the textarea may be `g-recaptcha-response-1` and so on. If you can’t find it, complete the captcha by hand once and search the Elements panel for `03A` to see where the result is stored. How to find the callback: [Find reCAPTCHA parameters](https://docs.yescaptcha.com/en/guides/find-recaptcha-parameters/#callback-function). A complete example (Selenium 4): recaptcha_selenium.py ```python """Solve reCAPTCHA v2 on Google's demo page in a real browser with Selenium 4: get a token from YesCaptcha, put it into the page, then submit the form. Run: pip install requests selenium export YESCAPTCHA_CLIENT_KEY=your_client_key python recaptcha_selenium.py Each run creates one NoCaptchaTaskProxyless task (charged per the price list). """ import os import time import requests from selenium import webdriver from selenium.webdriver.common.by import By CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] API = "https://api.yescaptcha.com" WEBSITE_URL = "https://www.google.com/recaptcha/api2/demo" def call(method, payload): data = requests.post(f"{API}/{method}", json={"clientKey": CLIENT_KEY, **payload}, timeout=30).json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data def get_token(website_url, website_key): task = {"type": "NoCaptchaTaskProxyless", "websiteURL": website_url, "websiteKey": website_key} task_id = call("createTask", {"task": task})["taskId"] for _ in range(36): time.sleep(5) result = call("getTaskResult", {"taskId": task_id}) if result.get("status") == "ready": return result["solution"]["gRecaptchaResponse"] raise TimeoutError(task_id) driver = webdriver.Chrome() # Selenium 4 downloads a matching chromedriver automatically try: driver.get(WEBSITE_URL) site_key = driver.find_element(By.CSS_SELECTOR, "[data-sitekey]").get_attribute("data-sitekey") token = get_token(WEBSITE_URL, site_key) # Put the token where reCAPTCHA keeps it ... driver.execute_script( "document.getElementById('g-recaptcha-response').value = arguments[0];", token ) # ... and, if the page uses a callback (data-callback="..."), call it: callback = driver.find_element(By.CSS_SELECTOR, "[data-sitekey]").get_attribute("data-callback") if callback: driver.execute_script(f"window[{callback!r}](arguments[0]);", token) driver.find_element(By.ID, "recaptcha-demo-submit").click() time.sleep(2) print("passed" if "Verification Success" in driver.page_source else "not passed") finally: driver.quit() ``` ## reCAPTCHA v3 v3 has no checkbox. The page calls `grecaptcha.execute(SITE_KEY, {action: '...'})` when it needs a token and puts the token into its own request (the field name is up to the site; common ones are `g-recaptcha-response`, `token` and `recaptchaToken`). Use Method 1: find the request carrying the token in the Network panel and reproduce it. The task’s `pageAction` must match the page’s `action`. ## Still not passing? - The token expired: submit right away, within 60 seconds. - You submitted the wrong field, or missed other fields or cookies: compare with the browser’s request field by field. - The site also checks IP and User-Agent: use a type with your own proxy (such as `NoCaptchaTask`) and submit through the same proxy. - v3 score too low: check `pageAction`, or use a fixed high-score type; see [reCAPTCHA v3](https://docs.yescaptcha.com/en/tasks/recaptcha-v3/). - The site’s risk checks look at other behaviour signals. If tokens pass too rarely, switch to [image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/) and click in a real browser, or use the [browser extension](https://docs.yescaptcha.com/en/extension/). --- # reCAPTCHA image clicking with Selenium > Use Python, Selenium 4 and ReCaptchaV2Classification to click through reCAPTCHA v2 image challenges in a real browser. Trigger the captcha, read the question and image, call the API, click the tiles and submit; complete example code. Source: https://docs.yescaptcha.com/en/guides/recaptcha-click-selenium/ · Last verified: 2026-10-15 This guide opens Google’s reCAPTCHA demo page with Selenium 4 and completes the image challenge in a real browser: it reads the question and image, asks [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/) (`ReCaptchaV2Classification`) which tiles to click, and clicks them. Unlike the token approach, the check is completed in the browser itself, which helps on sites where tokens rarely pass. Without code, the [browser extension](https://docs.yescaptcha.com/en/extension/) does the same thing using the same API. ## Setup ```bash pip install requests selenium pillow export YESCAPTCHA_CLIENT_KEY=your_client_key ``` Chrome must be installed. Selenium 4 downloads a matching chromedriver automatically. ## Steps 1. **Click the checkbox.** It is inside the iframe titled “reCAPTCHA”; switch into it and click `#recaptcha-anchor`. 2. **Switch to the challenge iframe.** The challenge is in another iframe whose title contains “challenge”. 3. **Read the question.** The bold text in `.rc-imageselect-desc-wrapper strong` is the target, for example “traffic lights”. The API needs the question ID, so map the name to an ID (`/m/015qff`) using the table in [Question IDs](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/#question-ids). An English browser UI makes the mapping easiest. 4. **Get the image.** The tiles are slices of one large image; download the `src` of `td.rc-imageselect-tile img`. Scale 9-tile (3x3) images to 300×300 and 16-tile (4x4) images to 450×450, then Base64-encode. 5. **Recognize.** Call `createTask` with type `ReCaptchaV2Classification`, `image` and `question`. Adding `"confidence": 0.5` makes 3x3 images return every matching tile at once, so you don’t need to handle the 1x1 tiles that fade in after clicking. 6. **Click.** `objects` lists tile indexes from 0, left to right and top to bottom; click the matching `td` elements. 7. **Verify.** Click `#recaptcha-verify-button`. If a new round appears, go back to step 3; when the challenge window closes, you have passed. 8. **Submit the form** on the main page. ## Complete code recaptcha_click_selenium.py ```python """Click through a reCAPTCHA v2 image challenge with Selenium 4 and ReCaptchaV2Classification. Flow: open the page -> click the checkbox -> read the target name and the grid image -> ask YesCaptcha which tiles to click -> click them -> press Verify. Repeat if a new challenge appears. Run: pip install requests selenium pillow export YESCAPTCHA_CLIENT_KEY=your_client_key python recaptcha_click_selenium.py Each recognized image is charged (see the price list). reCAPTCHA's page structure can change; adjust the selectors below if a step stops working. """ import base64 import io import os import time import requests from PIL import Image from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] PAGE_URL = "https://www.google.com/recaptcha/api2/demo" # Target names shown in the challenge (English UI) -> question IDs. # Full list: https://docs.yescaptcha.com/en/tasks/recaptcha-classification/ QUESTION_IDS = { "taxis": "/m/0pg52", "bus": "/m/01bjv", "buses": "/m/01bjv", "motorcycles": "/m/04_sv", "tractors": "/m/013xlm", "chimneys": "/m/01jk_4", "crosswalks": "/m/014xcs", "traffic lights": "/m/015qff", "bicycles": "/m/0199g", "parking meters": "/m/015qbp", "cars": "/m/0k4j", "bridges": "/m/015kr", "boats": "/m/019jd", "palm trees": "/m/0cdl1", "mountains or hills": "/m/09d_r", "fire hydrants": "/m/01pns0", "a fire hydrant": "/m/01pns0", "stairs": "/m/01lynh", } def classify(image_b64, question): task = {"type": "ReCaptchaV2Classification", "image": image_b64, "question": question, "confidence": 0.5} data = requests.post( "https://api.yescaptcha.com/createTask", json={"clientKey": CLIENT_KEY, "task": task}, timeout=30, ).json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data["solution"] # synchronous: the solution comes back right away def grid_image_b64(url, size): """Download the challenge image and scale it to the standard size (300 for 3x3, 450 for 4x4).""" img = Image.open(io.BytesIO(requests.get(url, timeout=30).content)).convert("RGB") img = img.resize((size, size)) buf = io.BytesIO() img.save(buf, format="JPEG") return base64.b64encode(buf.getvalue()).decode() driver = webdriver.Chrome() wait = WebDriverWait(driver, 15) try: driver.get(PAGE_URL) # 1. Click the checkbox (inside the "reCAPTCHA" iframe) wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, 'iframe[title="reCAPTCHA"]'))) wait.until(EC.element_to_be_clickable((By.ID, "recaptcha-anchor"))).click() driver.switch_to.default_content() # 2. Switch to the challenge iframe and solve rounds until it closes wait.until(EC.frame_to_be_available_and_switch_to_it( (By.XPATH, '//iframe[contains(@title, "challenge")]'))) for _ in range(5): target = wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, ".rc-imageselect-desc-wrapper strong"))).text.strip().lower() question = QUESTION_IDS.get(target) if not question: print("unsupported target, reloading:", target) driver.find_element(By.ID, "recaptcha-reload-button").click() time.sleep(2) continue tiles = driver.find_elements(By.CSS_SELECTOR, "td.rc-imageselect-tile") size = 450 if len(tiles) == 16 else 300 url = driver.find_element(By.CSS_SELECTOR, "td.rc-imageselect-tile img").get_attribute("src") solution = classify(grid_image_b64(url, size), question) for index in solution.get("objects", []): tiles[index].click() time.sleep(0.3) time.sleep(1) driver.find_element(By.ID, "recaptcha-verify-button").click() time.sleep(3) driver.switch_to.default_content() frame = driver.find_element(By.XPATH, '//iframe[contains(@title, "challenge")]') if not frame.is_displayed(): # challenge closed: passed break driver.switch_to.frame(frame) driver.switch_to.default_content() driver.find_element(By.ID, "recaptcha-demo-submit").click() time.sleep(2) print("passed" if "Verification Success" in driver.page_source else "not passed") finally: driver.quit() ``` ## Notes - reCAPTCHA’s page structure changes over time; adjust the selectors if a step stops working. - Every recognized image is charged (prices on [reCAPTCHA v2 image recognition](https://docs.yescaptcha.com/en/tasks/recaptcha-classification/)). Tasks whose clicks were rejected can be [reported](https://docs.yescaptcha.com/en/api/report/) within 1 hour for a refund. - If a target isn’t in the mapping table, click the reload button for another challenge, or ask support to add it. --- # hCaptcha image clicking with Selenium > Use Python, Selenium 4 and HCaptchaClassification to complete hCaptcha 3x3 image challenges in a real browser. Click the checkbox, read the question and the 9 images, call the API, click and submit; complete example code. Source: https://docs.yescaptcha.com/en/guides/hcaptcha-click-selenium/ · Last verified: 2026-10-15 This guide opens hCaptcha’s demo page with Selenium 4 and completes the 3x3 image challenge in a real browser: it reads the question and the 9 images, asks [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/) (`HCaptchaClassification`) which ones are targets, and clicks them. hCaptcha also has click-a-position and drag questions, which return coordinates instead of tiles; see [hCaptcha image recognition](https://docs.yescaptcha.com/en/tasks/hcaptcha-classification/). Without code, the [browser extension](https://docs.yescaptcha.com/en/extension/) handles all of them. ## Setup ```bash pip install requests selenium export YESCAPTCHA_CLIENT_KEY=your_client_key ``` ## Steps 1. **Click the checkbox.** It is inside the hCaptcha iframe whose URL contains `frame=checkbox`; switch into it and click `#checkbox`. 2. **Switch to the challenge iframe**, whose URL contains `frame=challenge`. 3. **Read the question.** The text in `.prompt-text` is the question; send it as is (switching hCaptcha’s language to English or Simplified Chinese is recommended). If example images appear next to the question, send them in `anchors` too. 4. **Get the images.** Each tile’s `.task-image .image` has the picture as a background image; download them in order, Base64-encode them, and build the `queries` list. 5. **Recognize.** Call `createTask` with type `HCaptchaClassification`. `objects` in the result corresponds to the tiles; `true` means target. 6. **Click and submit.** Click the target tiles and press the submit button. Several rounds may follow; repeat steps 3 to 6. 7. **Done.** After passing, the page’s `h-captcha-response` field holds the token, which is submitted with the form. ## Complete code hcaptcha_click_selenium.py ```python """Click through an hCaptcha 3x3 image challenge with Selenium 4 and HCaptchaClassification. Flow: open the page -> click the checkbox -> read the question and the 9 images -> ask YesCaptcha which images match -> click them -> submit. Repeat while new rounds appear. Run: pip install requests selenium export YESCAPTCHA_CLIENT_KEY=your_client_key python hcaptcha_click_selenium.py Each recognized round is charged (see the price list; rounds with no target found are free). hCaptcha changes its page structure often; adjust the selectors below if a step stops working. Click and drag questions return coordinates instead; see the HCaptchaClassification page. """ import base64 import os import re import time import requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait CLIENT_KEY = os.environ["YESCAPTCHA_CLIENT_KEY"] PAGE_URL = "https://accounts.hcaptcha.com/demo" def classify(question, images_b64): task = {"type": "HCaptchaClassification", "question": question, "queries": images_b64} data = requests.post( "https://api.yescaptcha.com/createTask", json={"clientKey": CLIENT_KEY, "task": task}, timeout=60, ).json() if data.get("errorId"): raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}") return data["solution"] # synchronous def background_image_b64(element): """The tiles are