Skip to content

Task types

Every createTask call carries a task object whose type selects the CAPTCHA you want solved. This page is the payload reference for every supported task.type: the required fields, the useful optional fields, a copy-pasteable request, and the exact solution shape you get back from getTaskResult.

For the request/response envelope and polling rules see createTask and the Quickstart.

Task type reference

task.type is validated on the way in. A value not in this table is rejected with ERROR_TASK_TYPE_UNSUPPORTED (errorId 5); a supported type that is missing a required field is rejected with ERROR_VALIDATION (errorId 8) before a thread is reserved — see How validation works.

Each task.type maps to an internal solve type. Types in the same solve group return the same solution shape.

task.typeSolve groupRequired task.* fieldsOwn proxy
ImageToTextTaskimagebody
GridTaskimagebody
BlsTaskimageat least one image tile (see BLS)
RecaptchaV2TaskProxylessreCAPTCHAwebsiteURL, websiteKey
RecaptchaV2TaskreCAPTCHAwebsiteURL, websiteKeyyes
RecaptchaV2EnterpriseTaskProxylessreCAPTCHAwebsiteURL, websiteKey
RecaptchaV2EnterpriseTaskreCAPTCHAwebsiteURL, websiteKeyyes
RecaptchaV3TaskProxylessreCAPTCHAwebsiteURL, websiteKey
RecaptchaV3EnterpriseTaskProxylessreCAPTCHAwebsiteURL, websiteKey
RecaptchaV3EnterpriseTaskreCAPTCHAwebsiteURL, websiteKeyyes
HCaptchaTaskProxylesshCaptchawebsiteURL, websiteKey
HCaptchaTaskhCaptchawebsiteURL, websiteKeyyes
TurnstileTaskProxylessTurnstilewebsiteURL, websiteKey
TurnstileTaskTurnstilewebsiteURL, websiteKeyyes
AntiCloudflareTaskCloudflare challengewebsiteURLyes
GeeTestTaskProxylessGeeTest v3gt, challenge, websiteURL
GeeTestTaskGeeTest v3gt, challenge, websiteURLyes
GeeTestV4TaskProxylessGeeTest v4captchaId, websiteURL
GeeTestV4TaskGeeTest v4captchaId, websiteURLyes
FunCaptchaTaskProxylessFunCaptchawebsitePublicKey, websiteURL
FunCaptchaTaskFunCaptchawebsitePublicKey, websiteURLyes

*Proxyless variants solve on our infrastructure. The plain (*Task) variants let you supply your own proxy — see Using your own proxy.

Solution shapes at a glance

Solve groupsolution field(s)
image (ImageToTextTask, GridTask, BlsTask)text
reCAPTCHA (v2 / v3, standard / enterprise)gRecaptchaResponse
hCaptchatoken
Turnstiletoken
FunCaptchatoken
GeeTest v3 / v4challenge, validate, seccode
Cloudflare challengecookies, token

How validation works

Required fields are checked before your task is queued, so a bad request fails fast and does not consume a thread. A missing field returns:

json
{
  "errorId": 8,
  "errorCode": "ERROR_VALIDATION",
  "errorDescription": "`websiteURL` is required for TurnstileTaskProxyless."
}

The full list of ERROR_* codes and retry guidance is on the Errors page.

The examples below truncate base64 image data to iVBORw0KGgo...<snip>. Send the full base64 string (no data-URI prefix) in real requests.

Image to text

Classic distorted-text image. Put the raw base64 of the image in body.

Required: body.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "ImageToTextTask",
    "body": "iVBORw0KGgo...<snip>"
  }
}

Result — POST /getTaskResult once status is ready:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "text": "w8kT2"
  },
  "createTime": 1752300000,
  "endTime": 1752300007
}

Grid

A grid image (for example a "select all squares with…" challenge). Send the full challenge image in body, exactly like Image to text. The solver returns the selected tiles as text.

Required: body.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "GridTask",
    "body": "iVBORw0KGgo...<snip>"
  }
}

Result:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "text": "[1, 5, 9]"
  }
}

BLS (numbered image tiles)

BLS challenges present several image tiles and an instruction; you get back the tile numbers that match. This is how real clients send it: one base64 field per tile, named image_base64_1, image_base64_2, … up to image_base64_9, plus the instructions value (the target the tiles are matched against).

Required: at least one image tile. A request is accepted when it contains any of image_base64_1, an images array, or an imagesBase64 array; the numbered image_base64_N form shown here is what the solver consumes. Omitting all of them returns ERROR_VALIDATION`images` is required for BlsTask.

Optional: instructions (the target, e.g. a number the tiles must contain), expected_image_count.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "BlsTask",
    "instructions": "546",
    "expected_image_count": 9,
    "image_base64_1": "iVBORw0KGgo...<snip>",
    "image_base64_2": "iVBORw0KGgo...<snip>",
    "image_base64_3": "iVBORw0KGgo...<snip>",
    "image_base64_4": "iVBORw0KGgo...<snip>",
    "image_base64_5": "iVBORw0KGgo...<snip>",
    "image_base64_6": "iVBORw0KGgo...<snip>",
    "image_base64_7": "iVBORw0KGgo...<snip>",
    "image_base64_8": "iVBORw0KGgo...<snip>",
    "image_base64_9": "iVBORw0KGgo...<snip>"
  }
}

Result — the matching tile numbers come back as text:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "text": "[2, 3, 8, 9]"
  }
}

reCAPTCHA v2

Google reCAPTCHA v2 ("I'm not a robot" / image challenge). Use RecaptchaV2TaskProxyless to solve on our infrastructure, or RecaptchaV2Task with your own proxy.

Required: websiteURL, websiteKey.

Optional: isInvisible (boolean, for invisible reCAPTCHA), recaptchaDataSValue (the data-s token some deployments require).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "RecaptchaV2TaskProxyless",
    "websiteURL": "https://example.com/login",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
  }
}

Result — the token to submit as g-recaptcha-response:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "gRecaptchaResponse": "03AGdBq26..."
  },
  "createTime": 1752300000,
  "endTime": 1752300019
}

To solve through your own proxy, use RecaptchaV2Task and add the proxy fields:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "RecaptchaV2Task",
    "websiteURL": "https://example.com/login",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
    "isInvisible": true,
    "proxyType": "HTTP",
    "proxyAddress": "203.0.113.10",
    "proxyPort": 8080,
    "proxyLogin": "user",
    "proxyPassword": "pass"
  }
}

reCAPTCHA v2 Enterprise

Same fields and same gRecaptchaResponse solution as reCAPTCHA v2; billed and metered separately. Use RecaptchaV2EnterpriseTaskProxyless, or RecaptchaV2EnterpriseTask with your own proxy.

Required: websiteURL, websiteKey.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "RecaptchaV2EnterpriseTaskProxyless",
    "websiteURL": "https://example.com/checkout",
    "websiteKey": "6Lc_aCMTAAAAABc..."
  }
}

Result:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "gRecaptchaResponse": "03AGdBq26..."
  }
}

reCAPTCHA v3

Score-based reCAPTCHA v3. Only the proxyless variant RecaptchaV3TaskProxyless is available for standard v3; if you need a proxied v3 solve, use reCAPTCHA v3 Enterprise.

Required: websiteURL, websiteKey.

Optional: pageAction (the action name your site sets, e.g. verify), minScore (the minimum score to accept, e.g. 0.3).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "RecaptchaV3TaskProxyless",
    "websiteURL": "https://example.com/",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
    "pageAction": "verify",
    "minScore": 0.3
  }
}

Result:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "gRecaptchaResponse": "03AGdBq26..."
  }
}

reCAPTCHA v3 Enterprise

Enterprise reCAPTCHA v3, metered separately. Use RecaptchaV3EnterpriseTaskProxyless, or RecaptchaV3EnterpriseTask with your own proxy. Same required fields and gRecaptchaResponse solution as reCAPTCHA v3.

Required: websiteURL, websiteKey.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "RecaptchaV3EnterpriseTaskProxyless",
    "websiteURL": "https://example.com/",
    "websiteKey": "6Lc_aCMTAAAAABc...",
    "pageAction": "login",
    "minScore": 0.5
  }
}

hCaptcha

hCaptcha. Use HCaptchaTaskProxyless, or HCaptchaTask with your own proxy.

Required: websiteURL, websiteKey.

Optional: data (the rqdata string some hCaptcha deployments require).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "HCaptchaTaskProxyless",
    "websiteURL": "https://example.com/signup",
    "websiteKey": "10000000-ffff-ffff-ffff-000000000001"
  }
}

Result — the token to submit as h-captcha-response:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "token": "P0_eyJ0eXAiOiJKV1Qi..."
  }
}

Cloudflare Turnstile

Cloudflare Turnstile. Use TurnstileTaskProxyless, or TurnstileTask with your own proxy.

Required: websiteURL, websiteKey.

Optional: action (the action name configured on the widget).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "TurnstileTaskProxyless",
    "websiteURL": "https://example.com/",
    "websiteKey": "0x4AAAAAAABkMYinukE8nzYS",
    "action": "login"
  }
}

Result:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "token": "0.KfM3f..."
  }
}

Cloudflare Challenge

The full Cloudflare "Checking your browser" interstitial (not the Turnstile widget). Use AntiCloudflareTask. Only websiteURL is required, but a proxy is strongly recommended — Cloudflare binds the returned clearance to the solving IP, so pass the same proxy your client will use.

Required: websiteURL.

Optional: proxy fields.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "AntiCloudflareTask",
    "websiteURL": "https://example.com/",
    "proxyType": "HTTP",
    "proxyAddress": "203.0.113.10",
    "proxyPort": 8080,
    "proxyLogin": "user",
    "proxyPassword": "pass"
  }
}

Result — the clearance cookie plus token:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "cookies": {
      "cf_clearance": "hR2s...<snip>"
    },
    "token": "hR2s...<snip>"
  }
}

GeeTest v3

GeeTest v3 slider/click. Use GeeTestTaskProxyless, or GeeTestTask with your own proxy. gt and challenge come from the target site's GeeTest init call.

Required: gt, challenge, websiteURL.

Optional: geetestApiServerSubdomain (the GeeTest API subdomain some sites use).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "GeeTestTaskProxyless",
    "websiteURL": "https://example.com/",
    "gt": "f1ab2cdefa3456789012345678901234",
    "challenge": "12345678abc90123456ab789012345ab"
  }
}

Result — the three GeeTest validation fields:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "challenge": "12345678abc90123456ab789012345ab",
    "validate": "cbe98a7d6f5e4c3b2a1908f7e6d5c4b3",
    "seccode": "cbe98a7d6f5e4c3b2a1908f7e6d5c4b3|jordan"
  }
}

GeeTest v4

GeeTest v4. Use GeeTestV4TaskProxyless, or GeeTestV4Task with your own proxy. v4 identifies the widget by captchaId (no gt/challenge).

Required: captchaId, websiteURL.

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "GeeTestV4TaskProxyless",
    "websiteURL": "https://example.com/",
    "captchaId": "e392e1d7fd421dc63325744d5a2b9c73"
  }
}

Result — same three-field shape as GeeTest v3:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "challenge": "e392e1d7fd421dc63325744d5a2b9c73",
    "validate": "cbe98a7d6f5e4c3b2a1908f7e6d5c4b3",
    "seccode": "cbe98a7d6f5e4c3b2a1908f7e6d5c4b3|jordan"
  }
}

FunCaptcha

Arkose Labs FunCaptcha. Use FunCaptchaTaskProxyless, or FunCaptchaTask with your own proxy. The site key is passed as websitePublicKey.

Required: websitePublicKey, websiteURL.

Optional: funcaptchaApiJSSubdomain (the FunCaptcha service subdomain some deployments use).

Request — POST /createTask:

json
{
  "clientKey": "cai_YOUR_KEY",
  "task": {
    "type": "FunCaptchaTaskProxyless",
    "websiteURL": "https://example.com/",
    "websitePublicKey": "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC"
  }
}

Result — the token to submit as fc-token / arkoselabs response:

json
{
  "errorId": 0,
  "status": "ready",
  "taskId": "tsk_0190a1b2-c3d4-7abc",
  "solution": {
    "token": "3126f0b4c4e3a...|r=us-east-1|..."
  }
}

Using your own proxy

The plain (*Task) variants — and AntiCloudflareTask — accept your own proxy so the CAPTCHA is solved from your IP. Add these fields to the task object:

FieldRequiredNotes
proxyTypeyesHTTP, HTTPS, SOCKS4, or SOCKS5
proxyAddressyesProxy host or IP
proxyPortyesProxy port
proxyLoginnoUsername, if the proxy needs auth
proxyPasswordnoPassword, if the proxy needs auth
json
{
  "proxyType": "HTTP",
  "proxyAddress": "203.0.113.10",
  "proxyPort": 8080,
  "proxyLogin": "user",
  "proxyPassword": "pass"
}

The *Proxyless variants ignore proxy fields — the solve runs on our infrastructure.

Migrating from CaptchaAI v1

If you already send tasks to CaptchaAI v1 (the 2captcha-style in.php/res.php flow), the field names change in the v2 native task object. The mapping:

v1 (2captcha) paramv2 native task.* field
method=userrecaptcha + googlekeytype + websiteKey
sitekey (hCaptcha / Turnstile)websiteKey
publickey (FunCaptcha)websitePublicKey
pageurlwebsiteURL
captcha_id (GeeTest v4)captchaId
gt, challenge (GeeTest v3)gt, challenge (unchanged)
min_scoreminScore
action (reCAPTCHA v3)pageAction
action (Turnstile)action (unchanged)
data-srecaptchaDataSValue
invisible=1isInvisible: true
api_server (GeeTest)geetestApiServerSubdomain
surl (FunCaptcha)funcaptchaApiJSSubdomain
image_base64_1..9 (BLS)image_base64_1..9 (unchanged)
proxy / proxyaddress + proxyportproxyAddress + proxyPort + proxyType

v1 returns a single flat string; v2 returns a structured solution object — use the field named in Solution shapes at a glance for each type.

CaptchaAI · phase 1 docs