Quick start
- 1Open the console and create an account number. Every account comes with an API key.
- 2Top up your balance.
- 3Send the request below with your key; the token comes back in the response.
curl -G "https://resolver.guru/v1/api" \
--data-urlencode "key=xxxxxxxxxxxx" \
--data-urlencode "sitekey=0x4AAAAAAA..." \
--data-urlencode "url=https://example.com/login"Authentication
Send your API key as the key parameter on every request, in the query string with the other parameters. Create and revoke keys under API keys in the console.
Because the key is part of the URL, it can show up in tools that record request URLs (logs, error tracking). Do not share those records; if you think a key has leaked, revoke it in the console and create a new one.
https://resolver.guru/v1/api?key=xxxxxxxxxxxx&sitekey=…&url=…Never put your key in code that runs in the browser (frontend). Always send requests from your own server.
Token request
Requests are sent with GET; parameters go in the query string. Remember to URL-encode the values (the libraries in the examples do this for you).
| Parameter | Type | Required | Description |
|---|---|---|---|
sitekey | string | Yes | The data-sitekey of the Turnstile widget on the target page. Usually starts with 0x4AAAA…. |
url | string | Yes | Full URL of the page the widget is on (https://…). |
action | string | No | Same value as the widget’s data-action, if it has one. Otherwise omit. |
cdata | string | No | Same value as the widget’s data-cdata, if it has one. Otherwise omit. |
curl -G "https://resolver.guru/v1/api" \
--data-urlencode "key=xxxxxxxxxxxx" \
--data-urlencode "sitekey=0x4AAAAAAA..." \
--data-urlencode "url=https://example.com/login" \
--data-urlencode "action=login" \
--data-urlencode "cdata=abc123"Where do I find the sitekey?
Look at the target page’s HTML for an element with the cf-turnstile class or a turnstile.render(…) call:
<div class="cf-turnstile"
data-sitekey="0x4AAAAAAA..." // → sitekey
data-action="login" // → action
data-cdata="abc123"></div> // → cdataResponse
A successful response returns 200:
{
"status": "success",
"token": "0.Rk9aXw3QpL7mT2vB8nYc...",
"solve_time": 1.21
}status | success or error |
token | The Turnstile token to add to your form or request. |
solve_time | Solve time in seconds. |
Every response includes your remaining balance (USD) in the X-Balance header.
On failure you get status: "error", a machine-readable error code and a message:
{
"status": "error",
"error": "insufficient_balance",
"message": "Your balance is too low. Top up in the console."
}Error codes
| Code | HTTP | Meaning | Charge |
|---|---|---|---|
missing_api_key | 401 | No key parameter. | None |
invalid_api_key | 401 | The key is invalid or was revoked. | None |
sitekey_required | 400 | sitekey was not sent. | None |
invalid_url | 400 | url is not a full http(s) URL. | None |
insufficient_balance | 402 | Balance too low. Top up in the console. | None |
too_many_concurrent | 429 | Too many requests in progress for your account. Retry shortly. | None |
solve_failed | 422 | This attempt could not be solved. Safe to retry. | None |
timeout | 504 | Solving took too long. Safe to retry. | None |
solver_unavailable | 504 | The service is temporarily unreachable. | None |
solver_not_configured | 503 | The service is temporarily unavailable. | None |
Examples
Copy your real key from the console and replace xxxxxxxxxxxx.
import requests
def solve(sitekey, url, action=None, cdata=None):
params = {"key": "xxxxxxxxxxxx", "sitekey": sitekey, "url": url}
if action: params["action"] = action
if cdata: params["cdata"] = cdata
res = requests.get(
"https://resolver.guru/v1/api",
params=params,
timeout=100,
)
data = res.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
return data["token"]
token = solve("0x4AAAAAAA...", "https://example.com/login")Using the token
Put the token in the field the target site’s form uses for Turnstile. The default field name is cf-turnstile-response.
Turnstile tokens are valid for about 300 seconds and can be used only once. Use the token right after you get it, and request a new one for every submission.
Pricing and limits
- Price: $0.30 per 1,000 tokens ($0.00030 per token). No subscription.
- Only successful solves are billed. Requests that return an error never touch your balance.
- Up to 20 requests per account are processed at the same time; more return
429. - A solve can take up to 90 seconds. Set your client timeout to at least 100 seconds.
- For
solve_failed,timeoutand429, wait a few seconds and retry 2–3 times.