SDKs
More
Our clients for JavaScript and TypeScript, Python and Go do the same things: create a Cloudflare Turnstile task or a Cloudflare challenge page’s task, wait for its result, read your balance, and check a callback’s signature. None has dependencies beyond its language’s standard library, and each is MIT-licensed.
| Language | Package | Needs | Page |
|---|---|---|---|
| JavaScript, TypeScript | @zerocaptcha/sdk on npm (coming) |
Node.js 20+, Deno, Bun or a browser | Node.js |
| Python | zerocaptcha on PyPI (coming) |
Python 3.9+ | Python |
| Go | github.com/zerocaptcha/zerocaptcha-go (coming) |
Go 1.22+ | Go |
Each one sends an Idempotency-Key with every task it creates, so when it retries a request we
asked it to slow down on (429), could not serve for a moment (502, 503, 504), or whose answer never
arrived whole, it never creates a second task. A wait for a result never runs past the time you
give it. A task that fails or expires is an error with its code, such as
ERROR_CAPTCHA_UNSOLVABLE, and nothing is charged for it.
Give each client your API key and the API’s address, from your environment, and each task the widget’s site key, and its action and cData when it sets them (see action and cData):
import { ZeroCaptcha } from "@zerocaptcha/sdk";
const client = new ZeroCaptcha({ apiKey: process.env.ZEROCAPTCHA_KEY!, baseUrl: process.env.ZEROCAPTCHA_API!,});
const token = await client.solve({ websiteURL: "https://shop.example.com/login", // the page with the widget websiteKey: "0x4AAAAAAAB1cD2eF3gH4iJ5", // its data-sitekey // The widget's data-action and data-cdata, or the action and cData options of // turnstile.render(). Leave out any the widget does not set. action: "login", cdata: "session-7f3a9c2e", // proxy: "http://user:pass@proxy.example.net:8080", // to solve through your own proxy // callbackUrl: "https://hooks.example.com/zerocaptcha", // to be called when it ends});const { available } = await client.getBalance();import os
from zerocaptcha import ZeroCaptcha
client = ZeroCaptcha(api_key=os.environ["ZEROCAPTCHA_KEY"], base_url=os.environ["ZEROCAPTCHA_API"])
token = client.solve( website_url="https://shop.example.com/login", # the page with the widget website_key="0x4AAAAAAAB1cD2eF3gH4iJ5", # its data-sitekey # The widget's data-action and data-cdata, or the action and cData options of # turnstile.render(). Leave out any the widget does not set. action="login", cdata="session-7f3a9c2e", # proxy="http://user:pass@proxy.example.net:8080", # to solve through your own proxy # callback_url="https://hooks.example.com/zerocaptcha", # to be called when it ends)available = client.get_balance()["available"]client, err := zerocaptcha.NewClient(os.Getenv("ZEROCAPTCHA_KEY"), os.Getenv("ZEROCAPTCHA_API"))if err != nil { log.Fatal(err)}token, err := client.Solve(ctx, zerocaptcha.NewTask{ WebsiteURL: "https://shop.example.com/login", // the page with the widget WebsiteKey: "0x4AAAAAAAB1cD2eF3gH4iJ5", // its data-sitekey // The widget's data-action and data-cdata, or the action and cData options of // turnstile.render(). Leave out any the widget does not set. Action: "login", CData: "session-7f3a9c2e", // Proxy: "http://user:pass@proxy.example.net:8080", // to solve through your own proxy // CallbackURL: "https://hooks.example.com/zerocaptcha", // to be called when it ends})For a challenge page, solveChallenge (solve_challenge in Python, SolveChallenge in Go) takes
the page and your proxy, and returns the cf_clearance cookie with the user agent to send it with.
Each language’s page shows it.
The clients are not in those registries yet. Until they are, call the API over plain HTTP, as the quickstart does in Python, Node, Go and curl.