The project's README from github.com/biusberline/cloudflare-turnstile-solver. As one markdown file: README.md.
The Cloudflare Turnstile Solver package makes it easy to work with
Cloudflare Turnstile from Python: it finds the Turnstile sitekey on any page,
creates a valid Turnstile token via the Peak API, and hands you a
cf-turnstile-response token you can inject into a form or request. It is a
small, dependency-free library plus a CLI — designed for CI pipelines, QA
automation, and integration engineering.
Table of Contents:
Cloudflare Turnstile protects pages with a widget that issues a token. Two things are always needed: find the sitekey the page is using, and create a token for that sitekey. This package provides both:
find_sitekey() — scan a page for its data-sitekey.create_token() — submit a solve task to the Peak API and get a valid token.token_for_page() — do both in one call.It has no browser dependency. A single Python file, standard library only, works on headless servers and CI runners.
$ export PEAK_API_KEY=pk_your_api_key
$ python -m cloudflare_turnstile_solver --url https://example.com/
0.AgAAABBqzz...
Or find the sitekey first, then create the token:
from cloudflare_turnstile_solver import find_sitekey, create_token
sitekey = find_sitekey("https://example.com/")
token = create_token("pk_...", sitekey, "https://example.com/")
print(token) # -> "0.AgAAABBqzz..."
Turnstile widgets expose the sitekey in the markup:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAAxxxx"></div>
find_sitekey() reads it for you:
from cloudflare_turnstile_solver import find_sitekey
sitekey = find_sitekey("https://example.com/")
print(sitekey) # -> "0x4AAAAAAAxxxx"
It also finds data-action when present, so tokens are scoped correctly.
A token is tied to the sitekey, the page URL, and optionally the action. To create one with the Peak API:
from cloudflare_turnstile_solver import create_token
result = create_token("pk_...", "0x4AAAAAAAxxxx", "https://example.com/",
proxy="http://u:[email protected]:8080")
print(result.token)
Submit the returned token as cf-turnstile-response:
cf-turnstile-response: 0.AgAAABBqzz...
⚠️ If the token is rejected, check the basics. The token is bound to the page URL and environment that created it. Use the same proxy and a matching user agent for the request.
| Function | Description |
|---|---|
find_sitekey(url, html=None) |
Scan a page for its Turnstile sitekey. |
find_action(html) |
Find an optional data-action value. |
create_token(api_key, sitekey, url, proxy=None, action=None, cdata=None, ...) |
Create a valid token via the Peak API. |
token_for_page(api_key, url, proxy=None, html=None) |
Find the sitekey and create a token in one call. |
All functions raise TurnstileTokenError on failure. create_token retries
transient failures automatically.
$ python -m cloudflare_turnstile_solver --url https://example.com/ --output json
{
"sitekey": "0x4AAAAAAAxxxx",
"token": "0.AgAAABBqzz...",
"success": true
}
Flags: --url (required), --sitekey, --proxy, --api-key, --output {text,json}, --retries.
import requests
from cloudflare_turnstile_solver import token_for_page
result = token_for_page("pk_...", "https://example.com/")
resp = requests.post("https://example.com/submit",
data={"cf-turnstile-response": result.token})
print(resp.status_code)
TOKEN=$(python -m cloudflare_turnstile_solver --url https://example.com/)
curl -X POST https://example.com/submit \
-H "cf-turnstile-response: $TOKEN" \
-d "payload=..."
This package uses Peak to solve Turnstile.
Get your free API key • Docs • Pricing
Does it run headless / without a browser?
Yes. The whole package is a single Python file on the standard library - no browser, no webdriver, no Node. It runs the same on a headless CI runner as it does locally.
How do I use a proxy?
Pass it to create_token / token_for_page with the proxy argument, or use
--proxy on the CLI:
$ python -m cloudflare_turnstile_solver --url https://example.com/ --proxy http://u:[email protected]:8080
Can I use it for multiple pages on the same site?
Yes - call token_for_page per page URL. Each token is bound to the page URL
it was created for, so don't reuse one token across different pages.
MIT