Skip to content

Solving captchas

POST /captchas/resolve takes a captcha description and keeps the request open until it is solved, then answers with the solution. The response has the same shape for a given type, however it was solved.

You send the type and that type’s fields. This solves a Turnstile widget:

curl -X POST https://api.clearance.rest/captchas/resolve \
-H "X-API-Key: $CLEARANCE_REST_API_KEY" \
-H "X-Service-Timeout: 120000" \
-H "content-type: application/json" \
-d '{ "type": "turnstile", "website_url": "https://example.com", "website_key": "0x4AAA..." }'
{
"success": true,
"job_id": "0190...",
"type": "turnstile",
"mode": null,
"status": "solved",
"solution": { "token": "0.abc...", "user_agent": "Mozilla/5.0 ..." },
"waited_ms": 1234,
"price": 0.003,
"balance": 9.997
}

X-Service-Timeout (milliseconds) bounds the wait. Without it the request waits up to 10 minutes.

The HTTP status is 200 for all three outcomes. Read status:

status Meaning Charged
solved solution is filled. Yes, the price of the type.
failed It could not be solved. error has a code and a message. No
timeout No solution arrived within the wait time. No

balance is your available balance after the request. Only solved costs money; see Billing.

If the answer a solver produced does not have the shape the type requires, the request ends as failed with error.code: "invalid_solution". It is not charged and you can send it again.

The request is strict: an unknown field, an unknown type, a missing required field or a field of the wrong type is rejected with 400 validation_error (error.details.issues lists the problems). Fields not listed for a type are rejected as well.

type Required fields Solution
recaptcha_v2 website_url, website_key token
recaptcha_v3 website_url, website_key token
turnstile website_url, website_key token
hcaptcha website_url, website_key token, resp_key
geetest_v3 website_url, gt, challenge challenge, validate, seccode
geetest_v4 website_url, captcha_id captcha_id, lot_number, pass_token, gen_time, captcha_output
aws_waf website_url cookies
mtcaptcha website_url, website_key token
funcaptcha website_url, website_key token
datadome website_url, captcha_url, user_agent, proxy cookies
cloudflare_challenge website_url, proxy token, cookies, user_agent
image_to_text image text
coordinates image coordinates: a list of { x, y }

Most types also take optional fields such as proxy, user_agent, enterprise or action. Every field of every type, with its description, is returned by GET /captchas/types and is documented in the API reference. That endpoint also returns each type’s price_per_1000, the price of 1,000 solutions in USD, and its supported modes.

Shared formats:

  • proxy is scheme://[user:pass@]host:port with http, https, socks4 or socks5. The port is required.
  • image and instructions_image are base64 without a data: prefix.
  • Types that produce cookies return cookies as an object of name to value.

Some fields are hints: a field marked as a hint is used when it can be, and dropped otherwise, instead of failing the request. GET /captchas/types marks each field as required, optional or hint.

If no solver can handle a combination of type, fields and mode, the request fails with 400 unsupported_request before anything is held.

For hcaptcha you can add "mode": "browser" to have the captcha solved in a real browser.

{ "type": "hcaptcha", "website_url": "https://example.com", "website_key": "10000000-ffff-ffff-ffff-000000000001", "mode": "browser" }
  • Only hcaptcha accepts mode, and "browser" is its only value.
  • Without mode, the request is served by whichever solver is available.
  • With mode: "browser", only browser solvers are used. If none is connected, the request fails with 503 provider_unavailable. This is retryable: try again shortly.
  • A browser solver that disconnects mid-job also ends the request with 503 provider_unavailable.

provider_unavailable is also what you get when no solver of any kind can take the request right now. Nothing was charged.

Status error.code
400 validation_error The body does not match the type’s fields.
400 unsupported_request No solver supports this combination.
400 invalid_service_timeout Bad X-Service-Timeout.
402 insufficient_balance, spend_limit_exceeded Rejected before the request started.
503 provider_unavailable See above. Retry shortly.

The SDKs return the response with its status for the three outcomes above, and throw only for HTTP errors: ValidationError, InsufficientBalanceError, ProviderUnavailableError.