Skip to main content
Peak — solve Cloudflare Turnstile & the 5s challenge in ~1s

turnstile-curl

turnstile-curl is a curl_cffi companion that solves Cloudflare Turnstile without a browser, so a curl_cffi request that hits a Turnstile wall comes back with a real token instead of a 403.

Why

curl_cffi forges a browser's TLS/JA3 handshake perfectly, which is exactly why people reach for it. But it has no JavaScript engine. Cloudflare Turnstile is a JS widget, so a managed or interactive challenge hands curl_cffi an interstitial HTML page or a 403, and there is nothing in-process that can run the challenge. This is the "curl_cffi cloudflare blocked" wall: the handshake is right, the request still fails.

turnstile-curl reads the Turnstile sitekey straight out of the returned markup, sends it to Peak, and gives you back the cf-turnstile-response token. curl_cffi still does the fetching, so you keep its speed and fingerprint. When your setup gets blocked, drop in a Peak API key and it just works.

Powered by Peak

This package uses Peak to solve Turnstile.

  • Solve Cloudflare Turnstile & the 5s challenge in about a second
  • $0.90 per 1,000 successful Turnstile solves, down to $0.35 at volume
  • 1,000 free solves to start, no card.

→ Get your free API key · Docs · Pricing

Install

pip install turnstile-curl curl_cffi

curl_cffi is the transport you fetch pages with. It is an optional dependency here so the library imports cleanly without it; install it to actually fetch.

Quickstart

import os
from turnstile_curl import solve

# Free key at https://peak.fo.?utm_source=github&utm_medium=readme&utm_campaign=packages&utm_content=turnstile-curl Reads PEAK_API_KEY by default.
os.environ.setdefault("PEAK_API_KEY", "pk_your_api_key")

# Fetch the protected page with curl_cffi, read the sitekey, solve via Peak.
token = solve("https://your-target.example/login")
print(token)  # -> "0.AgAAA..."  (the cf-turnstile-response value)

Send token as the cf-turnstile-response form field (or into the widget callback) on your next request.

Session: solve and resubmit in one shot

TurnstileSession wraps a curl_cffi session and keeps the same browser fingerprint through the whole flow.

from turnstile_curl import TurnstileSession

with TurnstileSession(api_key="pk_your_api_key", impersonate="chrome") as s:
    # Just the token:
    token = s.solve("https://your-target.example/login")

    # Or solve + resubmit the form with the token injected, and keep the
    # authenticated response and cookies on the session:
    resp = s.solve_and_submit(
        "https://your-target.example/login",
        submit_url="https://your-target.example/verify",
        data={"username": "demo", "password": "demo"},
    )
    print(resp.status_code)

Already have the sitekey

Skip the fetch and call Peak directly.

from turnstile_curl import PeakClient

peak = PeakClient(api_key="pk_your_api_key")
token = peak.solve_turnstile(
    sitekey="0x4AAAAAAADnPIDROrmt1Wwj",
    url="https://your-target.example/login",
    # proxy="http://user:pass@ip:port",  # optional
)

Proxies

Pass proxy="http://user:pass@ip:port" to TurnstileSession, solve(), or PeakClient.solve_turnstile(). The same proxy is used for the page fetch and forwarded to Peak so the token is minted from the IP you will use it on.

Earn with your app ID

Pass your Peak app id and you earn 5% of every solve this tool makes, paid as solve credit. It is optional and does not affect solve success or speed; it only tells Peak which app to credit. Create an app id at peak.fo/dashboard/developer, details at peak.fo/earn.

from turnstile_curl import solve

# Pass app_id=, or set the PEAK_APP_ID env var instead.
token = solve("https://your-target.example/login", app_id="app_your_app_id")

app_id works the same on TurnstileSession(...) and PeakClient(...), and falls back to PEAK_APP_ID when omitted.

How it works

  1. curl_cffi fetches the page with a forged browser TLS/JA3 fingerprint.
  2. turnstile-curl parses the sitekey (and cData / action / pagedata when present) from the data-sitekey container or a turnstile.render(...) call.
  3. It calls POST https://api.peak.fo/solve with task_type: "turnstiletask", the sitekey, and the URL.
  4. Peak returns the token; you resubmit the form with it as cf-turnstile-response.

Peak also solves the Cloudflare 5s challenge (task_type: "cloudflare5stask"); this package focuses on Turnstile.

API

  • solve(url, *, api_key=None, impersonate="chrome", proxy=None, app_id=None) -> str — one-shot fetch + solve, returns the token.
  • TurnstileSession(api_key=None, *, impersonate="chrome", proxy=None, app_id=None) — .get(), .solve(url), .detect_challenge(url), .solve_and_submit(url, ...).
  • PeakClient(api_key=None, *, app_id=None) — .solve(challenge), .solve_turnstile(sitekey, url, ...).
  • parse_challenge(html, url) / find_sitekey(html) — the extractor, if you fetch pages yourself.

The API key is read from PEAK_API_KEY unless you pass api_key=. The optional revenue-share app id is read from PEAK_APP_ID unless you pass app_id=.

Legitimate use

For automation, QA, and scraping public data you are allowed to access. Respect each target's Terms of Service and robots.txt, and rate-limit yourself. Do not use this for credential stuffing or to access data you have no right to.

License

MIT — see LICENSE.

Metadata

Release files for turnstile-curl 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for turnstile-curl 0.2.1
File Size Uploaded
turnstile_curl-0.2.1.tar.gz 13.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for turnstile-curl 0.2.1
File Interpreter ABI Platform
turnstile_curl-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 25.4 kB

Release files / turnstile_curl-0.2.1.tar.gz

Download URL turnstile_curl-0.2.1.tar.gz
Size 13.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7123720e602f1ec6396585f424a79e07878d5dbfbc677fa6d1526986ce45cf40
BLAKE2b-256 checksum
How to use checksums
72ef5011b71ac9e8c1becaaf922b7086d47cbdf04ef3103ffa3dcd41527a011f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release files / turnstile_curl-0.2.1-py3-none-any.whl

Download URL turnstile_curl-0.2.1-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
12ea1e7bff5f9daa15ae906dd8258f14316f922eda8643ae435495f4fd262d8b
BLAKE2b-256 checksum
How to use checksums
254a10168f28a8e39bd1da3866b0054df2f5bd8f77d0370ecfdd8a68c08ebf71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page