Skip to content
easycaptcha.to
Documentation

Token API examples

Submit an hCaptcha token task and retrieve its result in Python or JavaScript.

Before you start

Create a paid API key in the dashboard and set the EASYCAPTCHA_API_KEY environment variable. Set HCAPTCHA_SITEKEY and HCAPTCHA_PAGE_URL to the site key and page URL for your integration. Keep your API key on the server; do not put it in browser JavaScript.

Submit POST https://api.easycaptcha.to/v1/task with type: "hcaptcha_token", sitekey, and url. The examples use hold: 30 to wait up to 30 seconds for completion. If the task is still queued or running, they poll GET /v1/task/{task_id}?hold=30 using the same API key.

A completed task has status: "completed" and its token in result.token. A failed task has status: "failed" and an embedded error, even when the lookup itself returns HTTP 200. HTTP errors use Problem Details.

Python

Install the HTTP client with python -m pip install requests. Save the following as token.py and run python token.py.

import os
import time
import requests

BASE_URL = "https://api.easycaptcha.to"

def read_response(response):
    body = response.json()
    if not response.ok:
        raise RuntimeError(
            f"HTTP {response.status_code}: {body.get('detail', body)} "
            f"(request_id={body.get('request_id', 'unknown')})"
        )
    return body

with requests.Session() as client:
    client.headers["Authorization"] = f"Bearer {os.environ['EASYCAPTCHA_API_KEY']}"
    # Submit once. Do not retry this POST after a timeout or connection failure.
    task = read_response(client.post(
        f"{BASE_URL}/v1/task",
        json={
            "type": "hcaptcha_token",
            "sitekey": os.environ["HCAPTCHA_SITEKEY"],
            "url": os.environ["HCAPTCHA_PAGE_URL"],
            "hold": 30,
        },
        timeout=45,
    ))
    task_id = task["task_id"]
    print(f"Task ID: {task_id}")
    deadline = time.monotonic() + 300
    while task["status"] in ("queued", "running"):
        if time.monotonic() >= deadline:
            raise TimeoutError(f"Still waiting for {task_id}; retrieve this task again")
        time.sleep(1)
        task = read_response(client.get(
            f"{BASE_URL}/v1/task/{task_id}",
            params={"hold": 30},
            timeout=45,
        ))
    if task["status"] == "failed":
        problem = task["error"]
        raise RuntimeError(
            f"Task {task_id} failed: {problem['detail']} "
            f"(request_id={problem['request_id']})"
        )
    token = task["result"]["token"]
    # Pass token to your integration immediately.
    print(token)

JavaScript

This example uses Node.js 22 or newer and its built-in fetch. Save it as token.mjs and run node token.mjs.

import { setTimeout as sleep } from "node:timers/promises";

const baseUrl = "https://api.easycaptcha.to";
const authorization = `Bearer ${process.env.EASYCAPTCHA_API_KEY}`;

async function api(path, options = {}) {
  const response = await fetch(`${baseUrl}${path}`, {
    ...options,
    headers: {
      Authorization: authorization,
      ...(options.body ? { "Content-Type": "application/json" } : {}),
    },
    signal: AbortSignal.timeout(45_000),
  });
  const body = await response.json();
  if (!response.ok) {
    throw new Error(
      `HTTP ${response.status}: ${body.detail ?? body.title} ` +
        `(request_id=${body.request_id ?? "unknown"})`,
    );
  }
  return body;
}

// Submit once. Do not retry this POST after a timeout or connection failure.
let task = await api("/v1/task", {
  method: "POST",
  body: JSON.stringify({
    type: "hcaptcha_token",
    sitekey: process.env.HCAPTCHA_SITEKEY,
    url: process.env.HCAPTCHA_PAGE_URL,
    hold: 30,
  }),
});
const taskId = task.task_id;
console.log(`Task ID: ${taskId}`);
const deadline = performance.now() + 300_000;
while (task.status === "queued" || task.status === "running") {
  if (performance.now() >= deadline) {
    throw new Error(`Still waiting for ${taskId}; retrieve this task again`);
  }
  await sleep(1000);
  task = await api(`/v1/task/${encodeURIComponent(taskId)}?hold=30`);
}
if (task.status === "failed") {
  throw new Error(
    `Task ${taskId} failed: ${task.error.detail} ` +
      `(request_id=${task.error.request_id})`,
  );
}
const token = task.result.token;
// Pass token to your integration immediately.
console.log(token);

Enterprise tokens

Enterprise token tasks require account whitelisting. Use the sales contact form to request access. Once enabled, use type: "hcaptcha_enterprise_token" and add the integration’s rqdata string to the request. The polling flow and result.token field are the same.

{
  "type": "hcaptcha_enterprise_token",
  "sitekey": "YOUR_SITEKEY",
  "url": "https://your-site.test/login",
  "rqdata": "YOUR_RQDATA",
  "hold": 30
}

Timeouts and modes

A local timeout does not cancel the task. Save the returned task_id so you can retrieve that task again. If the initial POST times out before returning an ID, its outcome is unknown; automatically resubmitting may create another charged task.

Both examples submit standard tasks. Add the optional burst and fast booleans if you want extra concurrency or higher queue priority. See the API reference for the complete request and response schemas.

Optional worker proxy

You can include a proxy object in a token task request. It contains scheme (http, https, or socks5), host, port (1–65535), and optional username and password. The proxy is passed to the token worker for challenge traffic.

"proxy": {
  "scheme": "http",
  "host": "proxy.example",
  "port": 8080,
  "username": "proxy-user",
  "password": "proxy-password"
}

Developer revenue sharing

Activate the developer program in the dashboard to get your tag. Your software can send X-Developer-Tag: dev_... or add "developer_tag": "dev_..." to the JSON task request. Tags apply only to that request and cannot be set on API keys. Header and body tags must match if both are supplied.

The developer earns 5% of credit spent on attributed paid requests, credited to service balance daily. Refunded requests, free-plan tasks, and the developer’s own requests do not generate revenue. Developer tags provide attribution; requests still require a valid customer API key.

Read the affiliate and developer program guide for activation, daily credits, eligibility, and payout approval.

Get started with easycaptcha

Build your next integration with easycaptcha.

Create an account, get your API key, and start submitting hCaptcha jobs. Use typed Python and JavaScript SDKs or integrate directly over HTTP.

Create an accountExplore the API

Prepaid credit. Check pricing before submitting paid tasks.