Limits and Queueing

How long a result lives, how to poll, and what a refusal means

Nothing here is a per-key quota: a key is not rate limited, and a burst is not rejected for being a burst. The API is bounded by how many solves the platform runs at once, and everything above that waits in a queue. This page describes what that means in practice.

Results and Polling

  • A finished result is kept for a short window (minutes), then it expires: a late /getTaskResult answers ERROR_TASK_NOT_FOUND. Read the result when it is ready; do not archive the taskId and expect to come back to it later.
  • Poll /getTaskResult every few seconds, not in a tight loop. A solve takes from a couple of seconds to a minute depending on the product and on whether the site is busy.
  • Every call answers with HTTP 200, success or failure: read errorId (and errorCode) rather than the HTTP status. A client library that only checks response.ok will treat every error as a success.

The Queue

Tasks are solved as slots free up. A task you just created is behind everything that arrived before it, so a slow answer usually means a busy platform, not a stuck task.

When the queue is long enough that a new task would wait far longer than the solve itself, /createTask refuses it immediately with ERROR_TASK_QUEUE_FULL and refunds the reservation. The task never reaches a worker. That is deliberate: a task that waits longer than a result lives could never be delivered.

In that situation, back off and come back: retrying in a loop only lengthens the queue. Errors and Retries has the per-code rules.

Concurrency

There is no per-key limit on concurrent tasks today. Many customers run large batches through a single key, and the queue absorbs them.

Two things bound a batch in practice:

  • The platform's slots. Everything past the running solves waits.
  • The private-beta products. The payload API caps concurrent sessions per key and answers concurrency_limit with a retryAfterMs; its own page documents it.

Requests

  • proxy is required for every non-ProxyLess task type and ignored on a ProxyLess one. One clean token, no whitespace: see Proxy Format.
  • websiteURL must be the page that renders the challenge, without credentials, on a public host. A private or reserved address in the URL or in the proxy host is refused with ERROR_BLOCKED_TARGET.
  • Fields are validated before anything is reserved: a malformed request is answered at once and never charged.

Per Product

ProductWhat is specific to it
reCAPTCHA v3 / EnterpriseA standard sitekey sent to an Enterprise type (or the reverse) is refused with ERROR_WRONG_TASK_TYPE. See reCAPTCHA v3
AWS WAF CaptchaThe ProxyLess variant uses our pool; AntiAwsWafTask needs your proxy. See AWS WAF
GeeTest v3 + v4v3 and v4 are the same task type, selected by the fields you send. See GeeTest
CaptchaFoxThe token format depends on the site. See CaptchaFox
Cloudflare TurnstileEnabled per API key, and a managed widget can ask for a click. See Cloudflare Turnstile

On this page