Skip to content
easycaptcha.to
Documentation

Async hCaptcha tasks with Python and httpx

Use the native async Python client to wait for hCaptcha jobs without blocking an event loop, with explicit polling and client cleanup.

Use a native async transport

A synchronous HTTP call inside an async worker prevents that worker from making progress while the network is busy. The easycaptcha httpx backend provides AsyncHttpxClient, so creation, retrieval, and balance calls can be awaited. Install it with python -m pip install 'easycaptcha-sdk[httpx]'.

The urllib and requests async variants use threads around blocking HTTP. That can be appropriate when those libraries are required, but it is a different execution model. Choose deliberately rather than assuming every class with an async name uses native async networking.

Bound the wait without repeating creation

import asyncio
import os
import time
from easycaptcha.backends.httpx import AsyncHttpxClient

async def solve():
    async with AsyncHttpxClient(os.environ["EASYCAPTCHA_API_KEY"]) as client:
        job = await client.create_job({
            "type": "hcaptcha_token",
            "sitekey": os.environ["HCAPTCHA_SITEKEY"],
            "url": os.environ["HCAPTCHA_PAGE_URL"],
            "hold": 30,
        })
        task_id = job["task_id"]
        deadline = time.monotonic() + 180
        while job["status"] in ("queued", "running"):
            if time.monotonic() >= deadline:
                raise TimeoutError(f"Resume lookup for {task_id}")
            await asyncio.sleep(1)
            job = await client.get_job(task_id)
        if job["status"] == "failed":
            raise RuntimeError(job["error"]["detail"])
        return job["result"]["token"]

# Call await solve() inside your application's event loop.

This function submits exactly once. Its deadline controls local waiting, not server-side cancellation. Persist the task ID outside the function if a background worker must recover after a restart.

Control admission separately from transport

Async networking makes it easy to start many operations; it does not increase your account’s weighted concurrency allowance. Put a queue or semaphore around task creation and release capacity when you observe terminal work. Do not hold a global database lock while waiting for a remote job.

Close the client through its async context manager. When using a supplied httpx session, its lifecycle belongs to your application. Test cancellation, transport failure, and a job that remains queued beyond your local deadline. The API reference supplies the job states; measurement guidance explains why a local timeout should remain an unknown outcome until reconciled.

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.