Solve a captcha
One authenticated POST returns a token. Authenticate with your API key in the x-api-key header. Only successful solves are billed.
Endpoint
Always send a real desktop userAgent — the token embeds it, so it should match the browser your traffic presents. A mismatched or missing UA lowers the score; when omitted, a default is used.
Async solving (reCAPTCHA only)
/solve holds the connection open for the whole solve, so a busy fleet has to refuse work it would otherwise queue. The async endpoint splits that in two: you submit and get an id back immediately, then poll for the result or let a callback bring it to you. Waiting costs you no socket and costs us no capacity, so a burst queues instead of coming back as concurrency_limit_exceeded.
reCAPTCHA onlyA job carries a single token, which is the whole result for a ReCaptcha* task and not for the others — Kasada returns a header set with no token at all, and Evaluate returns a decision alongside it. Send TicketmasterTmptTask, EvaluateTask, KasadaLogin and KasadaReload to /solve. Our SDKs already do this for you.
The body is the /solve body exactly, plus an optional callback_url. Send an Idempotency-Key header and a resent submit returns the original job instead of buying a second solve — the key is durable and works across shards, so a retry after a network blip is free.
{ "success": true, "id": "8f14e45f-ceea-467a-9e4b-2c1d3a5f7b90", "status": "running" }Poll about every 5 seconds. Read status, never success — success only turns true once status is done, so treating it as the completion test reports a still-running solve as a failure. running means keep going; done and failed are terminal.
{
"success": true,
"id": "8f14e45f-ceea-467a-9e4b-2c1d3a5f7b90",
"status": "done",
"token": "03AFcWeA...",
"solve_ms": 1840,
"elapsed_ms": 2110,
"created_at": "2026-09-10T00:00:00Z",
"completed_at": "2026-09-10T00:00:02Z"
}{ "success": false, "id": "8f14e45f-...", "status": "failed", "error": "solver_unavailable" }Callbacks
Pass callback_url and we POST the finished job to it, so you need not poll at all. It must be a public https URL; private and loopback addresses are rejected up front with callback_url_invalid. Every delivery is signed — verify X-Kagedcap-Signature before trusting the body, and compare it in constant time. Delivery is retried with backoff, and polling always remains authoritative: a callback that never gets through can never cost you the token.
POST https://your-app.example.com/hooks/kagedcap
X-Kagedcap-Signature: sha256=<hmac of the raw body>
X-Kagedcap-Delivery: 1
{ "id": "8f14e45f-...", "status": "done", "token": "03AFcWeA...", "solve_ms": 1840, "elapsed_ms": 2110 }Two things to design around. Results expire: the token is cleared about five minutes after completion — a reCAPTCHA token is dead in roughly two anyway — so a late poll returns done with no token rather than a result you can use. Score is v1 only: a job carries no score or verification block, so if you need those, use /solve.
Direct fleet endpoints (advanced)
You never have to think about this. api.kagedcap.io/solve reads the task and forwards it to the right solver fleet for you. If you're latency-sensitive and already know which fleet a request targets, you can skip that routing hop and POST straight to the fleet subdomain — same path, same body, same x-api-key header, identical response.
Send each task to its own fleet — a task posted to the wrong subdomain is rejected, whereas the default endpoint always routes it correctly. When in doubt, keep using api.kagedcap.io/solve; the routing overhead is a few milliseconds and it never sends a task to the wrong place.
Solve types
The task field selects the type. reCAPTCHA and tmpt return the same envelope — success, token, score, verification — with score populated only for v3. Evaluate adds decision (allow / challenge / block). Kasada returns its own envelope (the x-kpsdk-* headers), shown below.
reCAPTCHA v3
Invisible, score-based. Returns a token and a 0.0–1.0 score. Requires a sitekey and an action.
{
"task": "ReCaptchaV3Task",
"url": "https://example.com/login",
"sitekey": "6Lc…",
"action": "login",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"proxy": "http://user:pass@1.2.3.4:8888"
}{
"success": true,
"task": "ReCaptchaV3Task",
"token": "03AFcWeA…",
"score": 0.9,
"verification": null
}The ProxyLess variant (ReCaptchaV3TaskProxyLess) must omit proxy.
reCAPTCHA v3 Enterprise
Enterprise sitekeys. Same shape as v3 — a sitekey and an action.
{
"task": "ReCaptchaV3EnterpriseTask",
"url": "https://www.example.com",
"sitekey": "6Lc…",
"action": "checkout",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"proxy": "http://user:pass@1.2.3.4:8888"
}{
"success": true,
"task": "ReCaptchaV3EnterpriseTask",
"token": "03AFcWeA…",
"score": 0.9,
"verification": null
}reCAPTCHA v2 · Invisible
Invisible v2. No action and no score — the token is verified pass/fail via Google siteverify, so score is always null.
{
"task": "ReCaptchaV2Task",
"url": "https://example.com/",
"sitekey": "6Lc… (a v2 invisible key)",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"proxy": "http://user:pass@1.2.3.4:8888"
}{
"success": true,
"task": "ReCaptchaV2Task",
"token": "03AGdBq…",
"score": null,
"verification": null
}No action is required. v2 checkbox (which can pop an image challenge) is not supported.
TMPT Solver
Mints a Ticketmaster tmpt cookie. url must be a Ticketmaster host and action must be Event or Login. No sitekey (applied server-side); proxy is optional. Send the userAgent you will replay the cookie with — it is used for the underlying solve, so a mismatch weakens the result. The returned token is the tmpt cookie value.
{
"task": "TicketmasterTmptTask",
"url": "https://www.ticketmaster.com/event/…",
"action": "Event",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"proxy": "http://user:pass@1.2.3.4:8888"
}{
"success": true,
"task": "TicketmasterTmptTask",
"token": "eyJhbGciOi…",
"score": null,
"verification": null
}Score verification does not apply, so score and verification are always null.
Evaluate
Runs Ticketmaster APS protect() — mints the page reCAPTCHA, posts /epsf/v1/evaluate, and returns the APS decision token. url and proxy are required. No sitekey (applied server-side). userAgent is optional but recommended — it picks the device profile the fingerprint is built from, so send the UA you will replay with. auth.* URLs default to verify_phone; any other Ticketmaster host defaults to join_queue. The returned token is the EPSF allow token (replay it on the next APS step).
// verify_phone — the default for auth.* hosts
{
"task": "EvaluateTask",
"url": "https://auth.ticketmaster.com/as/authorization.oauth2?client_id=…&redirect_uri=https://identity.ticketmaster.com/exchange",
"proxy": "http://user:pass@1.2.3.4:8888",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"phone_number": "+12025550123"
}
// join_queue — the default for any other Ticketmaster host
{
"task": "EvaluateTask",
"url": "https://www.ticketmaster.com/event/1A2B3C4D5E6F7A8B",
"proxy": "http://user:pass@1.2.3.4:8888",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36",
"queueId": "examplequeue01",
"eventId": "1A2B3C4D5E6F7A8B"
}{
"success": true,
"task": "EvaluateTask",
"token": "eyJhbGciOi…",
"decision": "allow"
}The action is inferred from the URL host — pass action explicitly only to override it. decision is allow, challenge, or block; challenge means APS wants MFA/PoW/Persona next.
Kasada · Login
Returns the full Kasada header set (x-kpsdk-ct/cd/v/h) plus the identity headers (user-agent + client hints) to replay, and reload — Kasada's trust verdict (true = high-trust token). Requires a proxy — the token is IP-bound. No sitekey; site defaults server-side. Keep kpsdk_st, hash, and the x_kpsdk_* values to drive a later KasadaReload.
{
"task": "KasadaLogin",
"site": "ticketmaster",
"proxy": "http://user:pass@1.2.3.4:8888"
}{
"success": true,
"task": "KasadaLogin",
"site": "ticketmaster",
"headers": {
"user-agent": "Mozilla/5.0 …",
"sec-ch-ua": "\"Chromium\";v=\"131\", …",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\""
},
"x_kpsdk_ct": "…",
"x_kpsdk_cd": "…",
"x_kpsdk_v": "…",
"x_kpsdk_h": "…",
"kpsdk_st": 1712345678901,
"hash": "d49a6b7b…",
"reload": true,
"user_agent": "Mozilla/5.0 …"
}Unlike reCAPTCHA/tmpt there is no token — send the returned headers with your request. Reuse the same proxy for the request the token was minted for. Keep hash + kpsdk_st + x_kpsdk_ct to refresh the cd via KasadaReload.
Kasada · Reload
Refreshes x-kpsdk-cd from a prior KasadaLogin — no proxy, no browser (a few hashes). Send back kpsdk_st, hash, and x_kpsdk_ct (all required) from the login response; the cd is recomputed for that exact token. Use it to keep a session fresh.
{
"task": "KasadaReload",
"kpsdk_st": 1712345678901,
"hash": "d49a6b7b…",
"x_kpsdk_ct": "…",
"x_kpsdk_v": "…",
"x_kpsdk_h": "…"
}{
"success": true,
"task": "KasadaReload",
"x_kpsdk_ct": "…",
"x_kpsdk_cd": "…",
"x_kpsdk_v": "…",
"x_kpsdk_h": "…",
"kpsdk_st": 1712345678901,
"hash": "d49a6b7b…"
}x_kpsdk_ct/v/h and hash are echoed unchanged; only x_kpsdk_cd changes. x_kpsdk_ct must be the token the refreshed cd will ride with — its leading chars are folded into the cd.
Check balance
{ "available_micros": "2998000", "display": "$2.998" }Balance is stored in micros — 1,000,000 micros = $1.00. Only successful solves are billed; a per-solve price is quoted on your dashboard.
Billing & top-ups
Add funds from your dashboard → Top up. Top-ups are a signed-in action, not an API call — there's no endpoint to script with your key.
SDKs
Official clients for five languages — each handles auth, task selection, and errors. Pass version: "v2" for reCAPTCHA v2 invisible; enterprise for the Enterprise family; use kasadaLogin / kasadaReload for Kasada (the login session carries its headers into the reload for you).
All repos on GitHub ↗Every SDK's solve() picks the transport for you: reCAPTCHA goes over the async endpoint and is polled to completion, everything else over /solve. Either way the call blocks and hands you that fleet's full result — you never choose between them.
npm install @kagedcap/sdkimport { KagedCapClient } from '@kagedcap/sdk';
const kc = new KagedCapClient(process.env.KAGEDCAP_API_KEY!);
// v3 (enterprise)
const { token } = await kc.solve({ sitekey, url, action, enterprise: true, proxy });
// v2 invisible — no action
const v2 = await kc.solve({ sitekey, url, version: 'v2', proxy });
// Kasada — the session keeps the headers and resends them on reload
const k = await kc.kasadaLogin({ site: 'ticketmaster', proxy });
const fresh = await kc.kasadaReload(k);npm install kagedcapconst { KagedCapClient } = require('kagedcap');
const kc = new KagedCapClient(process.env.KAGEDCAP_API_KEY);
const { token } = await kc.solve({ sitekey, url, action, enterprise: true, proxy });
const v2 = await kc.solve({ sitekey, url, version: 'v2', proxy });
const k = await kc.kasadaLogin({ site: 'ticketmaster', proxy });
const fresh = await kc.kasadaReload(k); // reuses k's kpsdk_st + x_kpsdk_*pip install kagedcapfrom kagedcap import KagedCapClient kc = KagedCapClient(api_key) res = kc.solve(sitekey=…, url=…, action="login", enterprise=True, proxy=proxy) v2 = kc.solve(sitekey=…, url=…, version="v2", proxy=proxy) k = kc.kasada_login(site="ticketmaster", proxy=proxy) fresh = kc.kasada_reload(k) # resends k's kpsdk_st + x_kpsdk_*
go get github.com/kagedcap/kagedcap-sdk-go/v2kc := kagedcap.New(apiKey)
res, _ := kc.Solve(kagedcap.SolveParams{Sitekey: …, URL: …, Action: "login", Enterprise: true, Proxy: proxy})
v2, _ := kc.Solve(kagedcap.SolveParams{Sitekey: …, URL: …, Version: "v2", Proxy: proxy})
login, _ := kc.KasadaLogin(kagedcap.KasadaParams{Site: "ticketmaster", Proxy: proxy})
fresh, _ := kc.KasadaReload(login) // reuses login's kpsdk_st + x_kpsdk_*cargo add kagedcaplet kc = KagedCapClient::new(api_key);
let res = kc.solve(SolveParams { sitekey, url, action, enterprise: true, proxy, ..Default::default() })?;
let v2 = kc.solve(SolveParams { sitekey, url, version: Some("v2".into()), proxy, ..Default::default() })?;
let login = kc.kasada_login(KasadaParams { site: Some("ticketmaster".into()), proxy, ..Default::default() })?;
let fresh = kc.kasada_reload(&login)?; // reuses login's kpsdk_st + x_kpsdk_*