API reference
HTTP methods, paths, authentication, request bodies and response bodies for the customer API.
Base URL and formats
See the Python and JavaScript token examplesfor a complete task flow, or download the OpenAPI specificationto generate a client. Read burst and fastfor concurrency, priority and pricing details.
The API base URL is https://api.easycaptcha.to. JSON requests use Content-Type: application/json. Successful response bodies use application/json, unless the endpoint returns 204 with no body.
Task identifiers use the full task_ TypeID prefix. Timestamps use UTC RFC 3339. USD balances use integer strings in microcents, with 100,000,000 microcents per dollar.
Using a NopeCHA, 2Captcha, or CapSolver client? See the vendor compatibility APIs for dedicated hostnames and request formats.
Authentication
Task integrations send Authorization: Bearer YOUR_API_KEY. API keys cannot manage accounts or create other API keys.
Endpoint index
POST /v1/taskGET /v1/task/{task_id}POST /v1/task/{task_id}/feedbackGET /v1/task-historyGET /v1/ratesGET /v1/balanceGET /v1/extensionsGET /v1/extensions/{extension_id}/version/@latestGET /v1/extensions/{extension_id}/releasesGET /v1/extensions/{extension_id}/version/{version_id}
hCaptcha recognition payload schema
Shared response object schemas
Errors
HTTP errors return an application/problem+json body. See all problem types and the error schema. Private resources owned by another account return the same 404 as unknown resources. All endpoints can also return method_not_allowed, unsupported_media_type where applicable, or service errors.
A transport failure without a response has no error body. Do not automatically repeat a write after an ambiguous timeout. Check the resource state first when an identifier is available.
Submit a task
POST /v1/taskCreate one paid task. The response can wait for completion using hold.
Authentication
API key. Enterprise token tasks require explicit account whitelisting.
Request body
| Field | Type | Presence | Description |
|---|---|---|---|
type | string | Required | hcaptcha_recognition, hcaptcha_token or hcaptcha_enterprise_token. |
task | provider object | Recognition only | The hCaptcha challenge object; see the recognition payload schema below. |
sitekey | string | Token types | Site key for the target hCaptcha integration. |
url | string, URL | Token types | URL of the page with the hCaptcha integration. |
rqdata | string | Enterprise only | Enterprise request data. Only explicitly whitelisted accounts can submit this task type. |
hold | number | Optional | Wait in seconds. Default 0, maximum 30. This does not set the task's lifetime. |
{
"type": "hcaptcha_token",
"sitekey": "YOUR_SITEKEY",
"url": "https://example.com",
"hold": 30
}Response
202 application/json when queued or running after hold. 200 application/json when completed or failed during hold. Both return the Task body below.
| Field | Type | Presence | Description |
|---|---|---|---|
task_id | task TypeID | Always | Use this identifier to retrieve the task and submit feedback. |
type | string | Always | hcaptcha_recognition, hcaptcha_token or hcaptcha_enterprise_token. |
status | string | Always | queued, running, completed or failed. |
created_at | RFC 3339 timestamp | Always | UTC creation time. |
completed_at | timestamp or null | Always | Completion time when available. |
expires_at | timestamp or null | Always | Result expiry time when available. |
result | object or null | Always | Completed token tasks contain token, a string. Recognition results are keyed by the original task_key: booleans for binary tasks, selection arrays for area tasks, and placement arrays for drag/drop tasks. |
error | problem object or null | Always | Failed task's stored Problem Details, without numeric status. See the problems reference. |
{
"task_id": "task_01m40t5ag0e008000000000001",
"type": "hcaptcha_token",
"status": "queued",
"created_at": "2026-10-03T12:00:00Z",
"completed_at": null,
"expires_at": null,
"result": null,
"error": null
}A task continues when hold ends or the client disconnects. Do not automatically repeat this POST after an ambiguous timeout.
The default JSON body limit is 4 MiB. Unknown types and invalid values are rejected before admission.
Recognition task fields, image inputs, task counts, and drag entities are validated before the task is charged or queued.
Errors
invalid_request, invalid_credentials, insufficient_balance, forbidden, account_suspended, payload_too_large, rate_limited.
Get a task
GET /v1/task/{task_id}Read an immediate task snapshot. This endpoint does not wait for completion.
Authentication
API key belonging to the task's account.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
task_id | task TypeID | Path, required | Identifier returned by task submission. |
Request body
No request body.
Response
200 application/json. A failed task is also returned with HTTP 200 and an embedded problem in error.
| Field | Type | Presence | Description |
|---|---|---|---|
task_id | task TypeID | Always | Use this identifier to retrieve the task and submit feedback. |
type | string | Always | hcaptcha_recognition, hcaptcha_token or hcaptcha_enterprise_token. |
status | string | Always | queued, running, completed or failed. |
created_at | RFC 3339 timestamp | Always | UTC creation time. |
completed_at | timestamp or null | Always | Completion time when available. |
expires_at | timestamp or null | Always | Result expiry time when available. |
result | object or null | Always | Completed token tasks contain token, a string. Recognition results are keyed by the original task_key: booleans for binary tasks, selection arrays for area tasks, and placement arrays for drag/drop tasks. |
error | problem object or null | Always | Failed task's stored Problem Details, without numeric status. See the problems reference. |
{
"task_id": "task_01m40t5ag0e008000000000001",
"type": "hcaptcha_token",
"status": "completed",
"created_at": "2026-10-03T12:00:00Z",
"completed_at": "2026-10-03T12:00:10Z",
"expires_at": "2026-10-03T12:05:10Z",
"result": {
"token": "HCAPTCHA_TOKEN"
},
"error": null
}The default result retention window is five minutes after completion. Save the result promptly. An expired, unknown or non-owned task returns task_not_found.
Errors
invalid_request, invalid_credentials, task_not_found, account_suspended, rate_limited.
Report a task outcome
POST /v1/task/{task_id}/feedbackReport whether an owned, completed and still-retained task succeeded in use. Feedback is used to improve AI performance.
Authentication
API key belonging to the task's account.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
task_id | task TypeID | Path, required | The completed task's identifier. |
Request body
| Field | Type | Presence | Description |
|---|---|---|---|
success | boolean | Required | true for a successful observed outcome, false otherwise. |
{
"success": true
}Response
204 No Content. No response body.
Repeating identical feedback is a no-op. Conflicting feedback returns 409.
Errors
invalid_request, invalid_credentials, task_not_found, conflict, rate_limited.
Get recent task history
GET /v1/task-historyGet your latest 50 admitted tasks from the past seven days, newest first. No request body or query parameters. History contains summaries only, with no payloads, solutions or tokens.
Authentication
API key.
Request body
No request body.
Response
200 application/json.
| Field | Type | Presence | Description |
|---|---|---|---|
currency | string, "USD" | Always | Cost currency. |
items | array, at most 50 | Always | Recent task summaries, newest first. |
items[].task_id | task TypeID | Always | Original task identifier. |
items[].type | string | Always | Recognition, token or enterprise token capability. |
items[].status | pending | completed | failed | Always | Pending covers queued/running work; completed means a valid solution was accepted. |
items[].cost_microcents | decimal integer string | Always | Original charge including group and mode pricing, before any charge reversal. |
items[].created_at | RFC 3339 timestamp | Always | Admission time. |
items[].completed_at | timestamp or null | Always | Terminal outcome time; null while pending. |
{
"currency": "USD",
"items": [
{
"task_id": "task_01m40t5ag0e008000000000001",
"type": "hcaptcha_recognition",
"status": "completed",
"cost_microcents": "20000",
"created_at": "2026-10-04T12:00:00Z",
"completed_at": "2026-10-04T12:00:02Z"
}
]
}Entries are retained for at most seven days and may disappear sooner when newer tasks exceed the 50-entry limit. Financial records and aggregate usage have separate retention.
Errors
invalid_credentials, account_suspended, rate_limited, service_unavailable.
Get your task rates
GET /v1/ratesRead your current effective prices, including custom pricing and mode multipliers. No request body or query parameters.
Authentication
API key.
Request body
No request body.
Response
200 application/json.
| Field | Type | Presence | Description |
|---|---|---|---|
currency | string, "USD" | Always | Pricing currency. |
burst_multiplier | number | Always | Burst price multiplier; standard rate 1.5×. |
fast_multiplier | number | Always | Fast price multiplier; standard rate 1.2×. |
rates | object | Always | Contains hcaptcha_recognition, hcaptcha_token and hcaptcha_enterprise_token rates. |
rates.<type>.standard_microcents | decimal integer string | Always | Base price per recognition group or token task. |
{
"currency": "USD",
"rates": {
"hcaptcha_recognition": {
"standard_microcents": "10000"
},
"hcaptcha_token": {
"standard_microcents": "200000"
},
"hcaptcha_enterprise_token": {
"standard_microcents": "500000"
}
},
"burst_multiplier": 1.5,
"fast_multiplier": 1.2
}1 USD = 100,000,000 microcents. Recognition groups contain nine binary tiles or one area/drag image.
For multiple groups, multiply the standard price by the group count and selected mode multiplier, then round upward once.
Rates apply to new requests. Existing charges retain their original prices.
Errors
invalid_credentials, account_suspended, rate_limited, service_unavailable.
Get available balance
GET /v1/balanceRead the account's available USD credit.
Authentication
API key.
Request body
No request body.
Response
200 application/json.
| Field | Type | Presence | Description |
|---|---|---|---|
currency | string, "USD" | Always | Balance currency. |
balance_microcents | decimal integer string | Always | Signed USD microcents. 1 USD = 100,000,000 microcents. Use integer or decimal arithmetic. |
{
"currency": "USD",
"balance_microcents": "100000000"
}Errors
List public extensions
GET /v1/extensionsList extensions available to the caller. Anonymous callers see only public extensions; a valid session applies account visibility and permission rules.
Authentication
Optional session. Anonymous callers see only public extensions; a valid session applies account visibility and permission rules.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
cursor | string | Query, optional | Pagination cursor from next_cursor. |
limit | integer | Query, optional | Page size, default 50 and maximum 100. |
Request body
No request body.
Response
200 application/json. A page containing items and next_cursor (null when there are no more results).
| Field | Type | Presence | Description |
|---|---|---|---|
items | Extension[] | Always | Public extensions visible without an account. |
next_cursor | string or null | Always | Cursor for the next page. |
Errors
Get the latest extension version
GET /v1/extensions/{extension_id}/version/@latestGet metadata and a temporary download link for the latest stable release.
Authentication
None.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
extension_id | extension TypeID | Path, required | Owning package identifier. |
Request body
No request body.
Response
200 application/json. The response describes the selected version and its download link.
| Field | Type | Presence | Description |
|---|---|---|---|
extension_version_id | extension_version TypeID | Always | Release identifier. |
extension_id | extension TypeID | Always | Owning package. |
version | SemVer string | Always | Release version, including any prerelease suffix. |
prerelease | boolean | Always | Whether this is a prerelease. |
browser | string, "chromium" | Always | Target browser family. |
filename | string | Always | Download filename. |
size | integer | Always | Package size in bytes. |
sha256 | 64-character hex string | Always | Package checksum. |
release_notes | string | Always | Notes for this release. |
download_url | string, URL | Always | Temporary signed package download link. |
expires_at | RFC 3339 timestamp | Always | Download link expiry. |
Errors
Get available extension releases
GET /v1/extensions/{extension_id}/releasesGet the latest stable release and the newest prerelease only when it is newer than stable. Each includes a temporary download link.
Authentication
None.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
extension_id | extension TypeID | Path, required | Owning package identifier. |
Request body
No request body.
Response
200 application/json. Either release can be null. An extension with no available releases returns both as null.
| Field | Type | Presence | Description |
|---|---|---|---|
stable | Version | null | Always | Latest stable release. |
prerelease | Version | null | Always | Newest prerelease newer than stable; also available when no stable exists. |
Errors
Get an extension release
GET /v1/extensions/{extension_id}/version/{version_id}Get a specific release and a fresh signed download link. Unavailable releases return 404.
Authentication
None.
Path and query parameters
| Field | Type | Presence | Description |
|---|---|---|---|
extension_id | extension TypeID | Path, required | Owning package identifier. |
version_id | extension_version TypeID | Path, required | Release identifier. |
Request body
No request body.
Response
200 application/json. A Version object with a temporary signed download link.
Errors
hCaptcha recognition payload
Send {"type":"hcaptcha_recognition","task":{…}} toPOST /v1/task. The task field is the challenge object itself. You may also include an optional top-level sitekeystring for site-specific challenge and outcome attribution. Include these challenge fields:
| Field | Type | Presence | Description |
|---|---|---|---|
request_type | string | Required | image_label_binary, image_label_area_select, or image_drag_drop. |
requester_question | string or localized object | Required | Nonblank text, or string values by locale with a nonblank en entry. |
requester_question_example | image input or image input array | Optional | One example image or an image array. May be omitted, null, an empty string, or an empty array. |
tasklist | image task array | Required | Binary: exactly 9, 18, or 27 tiles. Area selection and drag/drop: exactly 1, 2, or 3 tasks. |
tasklist[].task_key | string | Required | Original hCaptcha task identifier, unique within the task list. |
tasklist[].datapoint_uri | image input | Required | Base64 image/video data URI for this tile or full challenge background. Remote URLs are rejected. |
tasklist[].entities | entity array | Drag/drop only | Between 1 and 5 entities for each drag/drop task. |
tasklist[].entities[].entity_id | string | Drag/drop only | Required draggable entity identifier, unique within this task image. |
tasklist[].entities[].coords | [number, number] | Drag/drop only | Original x and y coordinates; retained for entities that are not moved. |
tasklist[].entities[].entity_uri | image input | Drag/drop only | Image content for the draggable entity. |
tasklist[].entities[].size | [number, number] | Drag/drop only | Positive finite width and height in pixels in the original challenge. |
A media input is a nonempty data:image/png;base64,… ordata:video/webm;base64,… URI containing valid base64 data. HTTP(S) and other remote media URLs are rejected. This applies to task images, videos, drag entities, and question examples.
Additional fields inside the challenge are preserved. Image arrays in place of the challenge object and text_free_entry are rejected. Validation runs before charging or queue admission.
Recognition is billed per challenge group: nine binary tiles, one area-selection image, or one drag/drop image. Requests with two or three groups cost twice or three times the base price. Burst and fast multipliers apply to the total, with fractional microcents rounded upward once.
Recognition results are objects keyed by the original task_key. Binary images are processed in consecutive groups of nine, then each tile maps to a boolean: true selects that tile.
Area selection maps each task key to an array of{entity_coords, entity_name} objects. Points use[x, y]; rectangles use [x, y, x+w, y+h]. The name is a zero-based number in click order, starting again for each image.
Drag/drop maps each task key to one placement per entity, in task entity order. Each placement has entity_coords: [x, y] andentity_name equal to the original entity_id. Entities the worker did not move retain their original coords.
Worker coordinates and dimensions use absolute pixels inside the image, video, or canvas. Empty area selections return []. A failed worker group returnsnull under each affected task key.
Response models
Extension version responses use the definition below.
Version
| Field | Type | Presence | Description |
|---|---|---|---|
extension_version_id | extension_version TypeID | Always | Release identifier. |
extension_id | extension TypeID | Always | Owning package. |
version | SemVer string | Always | Release version, including any prerelease suffix. |
prerelease | boolean | Always | Whether this is a prerelease. |
browser | string, "chromium" | Always | Target browser family. |
filename | string | Always | Download filename. |
size | integer | Always | Package size in bytes. |
sha256 | 64-character hex string | Always | Package checksum. |
release_notes | string | Always | Notes for this release. |
download_url | string, URL | Always | Temporary signed package download link. |
expires_at | RFC 3339 timestamp | Always | Download link expiry. |