API Reference
Tiger Captcha solves Facebook captchas through a simple, asynchronous JSON API. Submit a task, get a taskId instantly, then poll for the result or receive it by webhook.
- Content type:
application/jsonon every request.
Authentication
Every request is authenticated with your account API key, sent as clientKey in the JSON body. Create and manage keys from your dashboard.
{ "clientKey": "tc_live_your_api_key", "task": { } }The solve flow
- 1. Create —
POST /createTaskwith the image → get ataskId. - 2. Wait — poll
POST /getTaskResultevery ~1s or receive a webhook. - 3. Read — when
statusisready, take the answer fromsolution.text.
Quick start
A full create-and-poll loop in your language of choice:
import base64, time, requests GATEWAY = "https://api.tigercaptcha.com" API_KEY = "tc_live_your_api_key" def solve(path): b64 = base64.b64encode(open(path, "rb").read()).decode() task = requests.post(f"{GATEWAY}/createTask", json={ "clientKey": API_KEY, "task": {"type": "FacebookCaptchaImage", "body": b64}, }).json() task_id = task["taskId"] while True: r = requests.post(f"{GATEWAY}/getTaskResult", json={ "clientKey": API_KEY, "taskId": task_id}).json() if r.get("status") == "ready": return r["solution"]["text"] if r.get("status") == "error": raise RuntimeError(r.get("errorDescription")) time.sleep(1) print(solve("captcha.png"))
import { readFileSync } from "fs"; const GATEWAY = "https://api.tigercaptcha.com", API_KEY = "tc_live_your_api_key"; async function solve(path) { const body = readFileSync(path).toString("base64"); const { taskId } = await (await fetch(`${GATEWAY}/createTask`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, task: { type: "FacebookCaptchaImage", body } }), })).json(); for (;;) { const r = await (await fetch(`${GATEWAY}/getTaskResult`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientKey: API_KEY, taskId }), })).json(); if (r.status === "ready") return r.solution.text; if (r.status === "error") throw new Error(r.errorDescription); await new Promise(s => setTimeout(s, 1000)); } } console.log(await solve("captcha.png"));
# 1) create curl -s -X POST https://api.tigercaptcha.com/createTask \ -H 'Content-Type: application/json' \ -d "{\"clientKey\":\"tc_live_...\",\"task\":{\"type\":\"FacebookCaptchaImage\",\"body\":\"$(base64 -w0 captcha.png)\"}}" # -> {"errorId":0,"taskId":"a1b2c3..."} # 2) poll curl -s -X POST https://api.tigercaptcha.com/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey":"tc_live_...","taskId":"a1b2c3..."}' # -> {"errorId":0,"status":"ready","solution":{"text":"AB12CD"}}
Create task
Submit a Facebook captcha. Returns a taskId instantly. The task.type selects how you supply the image.
| task.type | Supply the image via |
|---|---|
FacebookCaptchaImage | base64 in task.body (or a multipart image file) |
FacebookCaptchaUrl | a public image URL in task.url — the worker fetches it |
Body parameters
| Field | Type | Description | |
|---|---|---|---|
clientKey | string | required | Your account API key. |
task.type | string | required | FacebookCaptchaImage or FacebookCaptchaUrl. |
task.body | string | image | Base64-encoded image bytes. |
task.url | string | url | Public URL of the captcha image. |
callbackUrl | string | optional | We POST the result here on completion. See Webhooks. |
Response 200 OK
{ "errorId": 0, "taskId": "a1b2c3d4e5f6…" }task.type, an unreadable image/URL, a wrong key, your plan limits (429), or an admin pause. Capacity pressure never produces an error.Solve by image
Send the captcha itself as base64 in task.body with type FacebookCaptchaImage. This is what a Facebook captcha looks like — and what you get back:
Request
{
"clientKey": "tc_live_your_api_key",
"task": {
"type": "FacebookCaptchaImage",
"body": "/9j/4AAQSkZJRgABAQEAYABgAAD…" // base64 of the image above
}
}Then poll getTaskResult — or add a callbackUrl — and read solution.text ("apgXfK").
Solve by URL
Give us a public image URL with type FacebookCaptchaUrl and our worker fetches it. The image bytes never touch your side — handy when you already have the captcha's URL, and lighter on bandwidth.
A Facebook captcha URL typically looks like this:
https://www.facebook.com/captcha/tfbimage/?bd=EiIGSNX…&db=2&tk=AYjq9Rf…
Request
{
"clientKey": "tc_live_your_api_key",
"task": {
"type": "FacebookCaptchaUrl",
"url": "https://www.facebook.com/captcha/tfbimage/?bd=EiIGSNX…"
}
}http(s) address we can reach — internal/loopback URLs are rejected with 400 ERROR_URL_INVALID. The response and polling are identical to the image flow.Webhooks
Add a callbackUrl to createTask and we'll POST the result to it the moment the task finishes — no polling needed. getTaskResult still works, so you can use either or both.
Content-Type: application/json
X-Tiger-Task-Id: a1b2c3…
X-Tiger-Signature: sha256=<hmac>
{ "taskId": "a1b2c3…", "status": "ready", "solution": { "text": "AB12CD" } }- On failure the body is
{ "status": "error", "errorCode": …, "errorDescription": … }. - Verify it's from us:
X-Tiger-Signatureissha256=+ HMAC-SHA256 of the raw body, keyed by your API key. callbackUrlmust be a public http(s) URL. We retry with backoff, then give up — the result stays fetchable bytaskId.
import hmac, hashlib expected = "sha256=" + hmac.new(API_KEY.encode(), request.body, hashlib.sha256).hexdigest() # constant-time compare vs the X-Tiger-Signature header
Get task result
Fetch a task's state by taskId. Poll until the status is no longer processing.
| Field | Type | Description | |
|---|---|---|---|
clientKey | string | required | Your account API key. |
taskId | string | required | The id returned by createTask. |
Still working
{ "errorId": 0, "status": "processing" }Solved
{ "errorId": 0, "status": "ready", "solution": { "text": "AB12CD" } }Failed
{ "errorId": 1, "status": "error",
"errorCode": "ERROR_SOLVE_FAILED", "errorDescription": "Internal solver error" }taskId returns errorId 16 · ERROR_NO_SUCH_CAPCHA_ID. Results are retained for a few minutes after solving — fetch promptly.Get balance
Read your account balance and plan details. Works even for a zero-balance or unverified account — only an unknown key is rejected.
{ "clientKey": "tc_live_your_api_key" }{
"errorId": 0,
"balance": 12.35,
"currency": "USD",
"plan": "Pay-As-You-Go",
"status": "active",
"emailVerified": true,
"subscription": null,
"pricePer1000": 1.0,
"concurrency": 10,
"rps": 15
}Plan limits
Each key has a concurrency (max tasks in flight at once) and a requests-per-second cap set by your plan — call getBalance to read them. Exceeding either returns 429:
ERROR_RATE_LIMIT— too manycreateTaskcalls per second. HonourRetry-After.ERROR_CONCURRENCY_LIMIT— too many tasks still unfinished. Retrieve results (that frees a slot) before submitting more, or upgrade for more threads.
A concurrency slot frees the instant a task reaches ready or error.
Error codes
Every response carries an errorId — 0 means success. Failures also include a machine-readable errorCode and a human errorDescription.
| errorId | errorCode | HTTP | Meaning |
|---|---|---|---|
| 0 | — | 200 | Success. |
| 1 | ERROR_KEY_DOES_NOT_EXIST | 401 | Missing or wrong clientKey. |
| 1 | ERROR_TASK_TYPE_INVALID | 400 | Unsupported task.type. |
| 1 | ERROR_IMAGE_INVALID | 400 | No image, or it couldn't be decoded. |
| 1 | ERROR_URL_INVALID | 400 | Missing or non-public task.url. |
| 1 | ERROR_CALLBACK_INVALID | 400 | callbackUrl is not a public http(s) URL. |
| 1 | ERROR_TASKID_MISSING | 400 | getTaskResult without a taskId. |
| 16 | ERROR_NO_SUCH_CAPCHA_ID | 200 | Unknown or expired taskId. |
| 1 | ERROR_SOLVE_FAILED | — | The workers repeatedly failed to solve it. |
| 1 | ERROR_RATE_LIMIT | 429 | Exceeded your plan's requests/second. |
| 1 | ERROR_CONCURRENCY_LIMIT | 429 | Too many tasks in flight for your plan. |
| 1 | ERROR_ZERO_BALANCE | 402 | Insufficient balance — add funds. |
| 1 | ERROR_EMAIL_UNVERIFIED | 403 | Verify your email to use the API. |
| 1 | ERROR_ACCOUNT_SUSPENDED | 403 | Account suspended — contact support. |
| 1 | ERROR_NO_SLOT_AVAILABLE | 503 | Gateway paused, or the task waited too long. |
Need help? Create an account to get your API key and start solving.
Tiger Captcha API