Site by site
Kasada liveKasada on Twitch.
The block isn’t on the Twitch website — loading twitch.tv sails straight through. It sits one layer deeper, in front of the data the app actually pulls, and that’s the thing most write-ups about this get wrong. Get past that one wall and everything behind it answers normally.
$ curl -sI -X POST https://gql.twitch.tv/integrity \
-H 'Client-ID: kimne78kx3ncx6brgo4mv6wki5h1ko'
HTTP/2 200
content-type: application/json
x-kpsdk-ct: 0Ml5yFvmvIpok8dV… ← Kasada
x-kpsdk-r: 1-AA ← the grading verdict
# and for contrast, the site itself:
$ curl -sI https://www.twitch.tv/ | grep -ci kpsdk
0
observed 14 Aug 2026 · rerun it before you trust it · token value elided on purpose
The chain
Three links in the chain.
One of them is ours. The other two are yours, and they’re ordinary requests once the first one has been answered. The wall is step one.
-
01 ours
The Kasada challenge
gql.twitch.tv/integrity is fronted by Kasada. A client that cannot run the challenge script and produce a valid x-kpsdk-ct never gets past this, whatever it sends afterwards.
POST /api/tasks
-
02 yours
The integrity token
With the Kasada bundle in hand, the integrity endpoint answers with a token of its own. Publicly documented as a Paseto value, and it is what the GraphQL API is actually asking for.
POST gql.twitch.tv/integrity
-
03 yours
The GraphQL call
Send the integrity token back as Client-Integrity, with the same Client-ID and device id you used to get it, and the API answers normally.
POST gql.twitch.tv/gql
Worth being precise about, because the shorthand is misleading: we do not "solve Twitch". We answer the Kasada challenge standing in front of the token you need, and steps two and three are your own requests, made from your own address, exactly as they always were.
Worked
Start to finish.
One solve, then your own two calls. Same proxy throughout — that’s the part that decides whether this works. For integrators: every field is in the reference.
$ curl -X POST app.getsolvr.io/api/tasks \
-H "X-API-Key: solv_live_…" \
-d '{"target":"https://gql.twitch.tv/integrity",
"proxy":"http://user:pass@host:8000"}'
200 {
"status": "success",
"solution": {
"ct": "…",
"st": 1699999999,
"cd": { … },
"r": "1-B",
"user_agent": "Mozilla/5.0 …"
}
}
# integrity, carrying the bundle
$ curl -X POST https://gql.twitch.tv/integrity \
-H 'Client-ID: kimne78kx3ncx6brgo4mv6wki5h1ko' \
-H 'x-kpsdk-ct: <ct>' \
-H 'x-kpsdk-cd: <fresh proof>' \
-H 'x-device-id: <stable per session>' \
-A '<the user_agent we returned>'
# then graphql, carrying the integrity token
$ curl -X POST https://gql.twitch.tv/gql \
-H 'Client-ID: kimne78kx3ncx6brgo4mv6wki5h1ko' \
-H 'Client-Integrity: <token from step 2>' \
-d '{"query":"…"}'
The per-request proof is free here, so a session making many calls is one solve and as many proofs as it needs. The Kasada page covers that arithmetic.
Consistency
Four ways this goes wrong.
- solve and call on one proxy The address changed
- A token is tied to the address that made it. Solve through one proxy and make your next call from another and you are refused, with everything looking correct. Give us your proxy on the solve and use that same session for the two calls that follow.
- stable for the session The device changed
- Your device has to look like the same one throughout. Settle on one per session and keep it identical across all the calls that follow. Change it mid-session and you look like a brand-new client.
- send the one we return The browser doesn’t match
- The token is made for one specific browser, and we hand that back to you with the solve. Claim to be a different one and it no longer agrees with the token that is meant to vouch for you.
- a fresh proof every time One proof, many requests
- The token is reusable; the proof is not. Every request carrying the token needs its own fresh proof. Reusing one across a run is the single most common reason a working setup appears to stop working.
If we haven’t tuned this host yet, you’ll be told so. We tune per host: one we have not seen comes back marked unsupported_target, free, rather than as a failed solve you paid for. Reporting it is how it gets tuned.
Questions
Twitch, asked and answered.
The first one is checkable in thirty seconds, which is more than most pages on this subject can say.
Does Twitch use Kasada?
On the part that serves its data, yes — and you can prove it in one command (it is in the panel above). Ask that endpoint for its headers and Kasada's own show up: x-kpsdk-ct and x-kpsdk-r. Do the same to twitch.tv and there is nothing — the website itself is not gated this way. The wall is in front of the API, not the site.
What is the Client-Integrity header?
It is the pass the Twitch API wants before it will answer you: a token that proves you cleared the check. You earn it by clearing the check once, then send it back on every call after that. The check itself is the Kasada part, which is why a client that cannot answer Kasada never gets a usable pass — and why we come in at that step.
Why does my GraphQL request fail even with a token?
Three usual reasons, all about staying consistent. The pass is tied to the address that earned it, so solve and call through the same proxy. Your device has to look like the same one throughout. And the browser you claim to be has to match the one we solved as — we hand that back to you for exactly this reason.
How much does this cost?
$0.002 per solve, which is $2.00 per 1,000, and nothing when a solve fails. The per-request proofs are free and unlimited, so a session that makes many calls is one solve and no more.
Is scraping Twitch allowed?
Twitch's terms govern what you may do with their service, and they are the authority on it rather than us. This page documents how a protection mechanism works and how our API answers it. Use it for systems you own or have permission to assess.
How we know this
The Kasada headers on gql.twitch.tv/integrity, and their absence on www.twitch.tv, were observed directly on 14 Aug 2026 with the command in the first panel. The GraphQL endpoint, the web Client-ID and the Client-Integrity header are publicly documented. Token lifetimes and which operations demand integrity are not stated here, because we have not measured them. Prices and behaviour on our side are read out of this application at render time.
Twitch is a trademark of Twitch Interactive, Inc., which is not affiliated with Solvr and has not endorsed this. Kasada is a trademark of Kasada Pty Ltd. Both names are used to identify the systems described. Twitch's own terms govern what you may do with their service. For authorised testing of systems you own or may assess.