Tiger CaptchaTiger Captcha API

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.

Base URLhttps://api.tigercaptcha.com
  • Content type: application/json on 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.

json
{ "clientKey": "tc_live_your_api_key", "task": { } }
Keep your key secret — it authorizes billable solves. You can rotate it any time from API Keys in the dashboard.

The solve flow

  • 1. CreatePOST /createTask with the image → get a taskId.
  • 2. Wait — poll POST /getTaskResult every ~1s or receive a webhook.
  • 3. Read — when status is ready, take the answer from solution.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

POSThttps://api.tigercaptcha.com/createTask

Submit a Facebook captcha. Returns a taskId instantly. The task.type selects how you supply the image.

task.typeSupply the image via
FacebookCaptchaImagebase64 in task.body (or a multipart image file)
FacebookCaptchaUrla public image URL in task.url — the worker fetches it

Body parameters

FieldTypeDescription
clientKeystringrequiredYour account API key.
task.typestringrequiredFacebookCaptchaImage or FacebookCaptchaUrl.
task.bodystringimageBase64-encoded image bytes.
task.urlstringurlPublic URL of the captcha image.
callbackUrlstringoptionalWe POST the result here on completion. See Webhooks.

Response 200 OK

json
{ "errorId": 0, "taskId": "a1b2c3d4e5f6…" }
The only rejections here are a bad 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:

Facebook captcha sample
A real Facebook challenge (280×70)
apgXfK

Request

json
{
  "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:

captcha url
https://www.facebook.com/captcha/tfbimage/?bd=EiIGSNX…&db=2&tk=AYjq9Rf…

Request

json
{
  "clientKey": "tc_live_your_api_key",
  "task": {
    "type": "FacebookCaptchaUrl",
    "url": "https://www.facebook.com/captcha/tfbimage/?bd=EiIGSNX…"
  }
}
The URL must be a public 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.

POST your callbackUrl
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-Signature is sha256= + HMAC-SHA256 of the raw body, keyed by your API key.
  • callbackUrl must be a public http(s) URL. We retry with backoff, then give up — the result stays fetchable by taskId.
python — verify
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

POSThttps://api.tigercaptcha.com/getTaskResult

Fetch a task's state by taskId. Poll until the status is no longer processing.

FieldTypeDescription
clientKeystringrequiredYour account API key.
taskIdstringrequiredThe id returned by createTask.

Still working

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

Solved

json
{ "errorId": 0, "status": "ready", "solution": { "text": "AB12CD" } }

Failed

json
{ "errorId": 1, "status": "error",
  "errorCode": "ERROR_SOLVE_FAILED", "errorDescription": "Internal solver error" }
An unknown or expired taskId returns errorId 16 · ERROR_NO_SUCH_CAPCHA_ID. Results are retained for a few minutes after solving — fetch promptly.

Get balance

POSThttps://api.tigercaptcha.com/getBalance

Read your account balance and plan details. Works even for a zero-balance or unverified account — only an unknown key is rejected.

request
{ "clientKey": "tc_live_your_api_key" }
response
{
  "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 many createTask calls per second. Honour Retry-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 errorId0 means success. Failures also include a machine-readable errorCode and a human errorDescription.

errorIderrorCodeHTTPMeaning
0200Success.
1ERROR_KEY_DOES_NOT_EXIST401Missing or wrong clientKey.
1ERROR_TASK_TYPE_INVALID400Unsupported task.type.
1ERROR_IMAGE_INVALID400No image, or it couldn't be decoded.
1ERROR_URL_INVALID400Missing or non-public task.url.
1ERROR_CALLBACK_INVALID400callbackUrl is not a public http(s) URL.
1ERROR_TASKID_MISSING400getTaskResult without a taskId.
16ERROR_NO_SUCH_CAPCHA_ID200Unknown or expired taskId.
1ERROR_SOLVE_FAILEDThe workers repeatedly failed to solve it.
1ERROR_RATE_LIMIT429Exceeded your plan's requests/second.
1ERROR_CONCURRENCY_LIMIT429Too many tasks in flight for your plan.
1ERROR_ZERO_BALANCE402Insufficient balance — add funds.
1ERROR_EMAIL_UNVERIFIED403Verify your email to use the API.
1ERROR_ACCOUNT_SUSPENDED403Account suspended — contact support.
1ERROR_NO_SLOT_AVAILABLE503Gateway paused, or the task waited too long.

Need help? Create an account to get your API key and start solving.