Getting the result

After creating a task you poll /getTaskResult with its taskId until the status flips to ready. The response carries the solution you submit to the target site.

The request

POST your clientKey and the taskId you got back from /createTask. The aliases /task/result and /check behave identically.

get-result.sh
curl -s https://api.capzy.ai/getTaskResult \
  -H 'Content-Type: application/json' \
  -d '{ "clientKey": "capzy_YOUR_KEY", "taskId": "df94a1c2-..." }'

Status values

While the solve is in progress you get:

processing.json
{ "errorId": 0, "status": "processing" }

Keep polling until status becomes ready or the response reports a failure. There are three terminal outcomes:

  • processing: not done yet, poll again.
  • ready: solved, solution is present.
  • failed: the solve did not succeed, errorCode explains why.

The ready response

A ready task returns the solution, plus cost (the amount billed for this solve) and ip (the egress IP the solve ran from, useful to confirm an IP-bound token matches your proxy).

ready.json
{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "token": "0.eyJ...",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
    "expireTime": 1735689600
  },
  "cost": 0.002,
  "ip": "203.0.113.7"
}

Solution shapes

What lives inside solution depends on the challenge:

  • Token types (Turnstile, reCAPTCHA, hCaptcha) return solution.token, which you submit where the widget would place its response. Some types also return solution.userAgent and solution.expireTime, a Unix timestamp after which the token is stale.
  • Cookie-clearance types (Cloudflare Challenge, Akamai, F5, Kasada) return solution.cookies and the solution.userAgent they were minted with. Send both from the same proxy IP.
  • Coordinate types return click or drag coordinates you replay on the widget. For these, tell Capzy whether the coordinates worked using reporting.
Poll every 2 seconds
/getTaskResult long-polls: it holds the connection open for up to about 4 seconds waiting on a completion signal before replying. A 2-second interval between calls is the sweet spot. Tighter polling just burns requests against your rate limit.

Handling failure

A failed task returns errorId: 1 with status: "failed" and an errorCode. Outcome errors such as ERROR_CAPTCHA_UNSOLVABLE, ERROR_TIMEOUT, and ERROR_NULL_RESULT are auto-refunded, so a failed solve does not cost you.

failed.json
{
  "errorId": 1,
  "status": "failed",
  "errorCode": "ERROR_CAPTCHA_UNSOLVABLE",
  "errorDescription": "The challenge could not be solved."
}

Poll loop

A complete Python loop with a timeout guard:

poll.py
import time, requests

API = "https://api.capzy.ai"
KEY = "capzy_YOUR_KEY"

def get_result(task_id, timeout=120):
    deadline = time.time() + timeout
    while time.time() < deadline:
        res = requests.post(f"{API}/getTaskResult", json={
            "clientKey": KEY, "taskId": task_id,
        }).json()
        if res["status"] == "ready":
            return res["solution"]
        if res["errorId"]:
            raise RuntimeError(res["errorCode"])
        # still processing; getTaskResult long-polls internally,
        # so a short sleep between calls is enough
        time.sleep(2)
    raise TimeoutError("task did not complete in time")

See Errors for every failure code and Reporting outcomes to feed results back to Capzy.