Skip to main content

nodriver-turnstile

Solve Cloudflare Turnstile inside a nodriver browser. Read the sitekey off the page, get a token, drop it into the widget. Three lines, and it works with the real Chrome nodriver already drives.

Python 3.9+ nodriver MIT License


nodriver gets you past most bot checks on its own. It's a genuine Chrome with no CDP fingerprints. What it can't do is answer a Turnstile challenge, because that's a token the widget mints server-side, not something a browser flag turns off. This library fills that one gap: it hands the (url, sitekey) to a solver and puts the returned token back where the page expects it. Everything else (cookies, TLS, the session) stays in your nodriver browser.

Install

pip install nodriver-turnstile

Use it

import asyncio, os
import nodriver as uc
from nodriver_turnstile import solve_turnstile

async def main():
    browser = await uc.start()
    tab = await browser.get("https://site-with-turnstile.example/login")

    result = await solve_turnstile(tab, os.environ["PEAK_API_KEY"])
    print(result.elapsed, result.cost)   # token is already in the page

    await (await tab.select("button[type=submit]")).click()

asyncio.run(main())

That's the whole thing. solve_turnstile finds the sitekey (explicit-render div, implicit div, or the managed iframe), requests a token, fills every cf-turnstile-response field, and fires the widget's callback if the page registered one.

Matching the exit IP

Turnstile scores the IP that submits the token. If your nodriver browser runs behind a proxy, give the solver the same one so the token and the request line up:

result = await solve_turnstile(tab, api_key, proxy="http://user:pass@host:port")

Leave proxy off and the token is minted from a clean pool instead. That's fine for a lot of sites; test it against yours.

Lower-level pieces

You don't have to hand it the tab. Pull the sitekey and token yourself when you want control over injection:

from nodriver_turnstile import read_sitekey, request_token

sitekey = await read_sitekey(tab)
res = await request_token(api_key, url="https://target.example/", sitekey=sitekey)
await tab.evaluate(f'document.querySelector("[name=cf-turnstile-response]").value = {res.token!r}')

Getting a key

solve_turnstile needs an API key for the solver it calls: Peak. Turnstile solves come back in about a second, you pay only for the ones that land, and the free tier is enough to wire this up and test it end to end. Peak also solves the Cloudflare 5-second challenge (task_type: "cloudflare5stask"); this package focuses on Turnstile.

Peak
$0.90 per 1,000 Turnstile solves, down to $0.35 at volume · pay only on success · 1,000 free solves · peak.fo

Same pattern for other stacks: playwright-turnstile · selenium-turnstile · camoufox-turnstile · scrapling-turnstile · crawlee-turnstile · drissionpage-turnstile · puppeteer-extra-plugin-turnstile · scrapy-turnstile · turnstile-curl · cloudscraper-turnstile · crawl4ai-turnstile. Full list in awesome-turnstile-solvers.

Notes

Use this on sites and accounts you're allowed to automate. Respect each target's Terms of Service and robots.txt. This is tooling for legitimate automation, testing, and public-data scraping; nothing here helps with credential stuffing or abuse. Not affiliated with Cloudflare.

License

MIT

Metadata

Release files for nodriver-turnstile 0.1.0

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

Source distribution (sdist)

Source distribution for nodriver-turnstile 0.1.0
File Size Uploaded
nodriver_turnstile-0.1.0.tar.gz 6.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nodriver-turnstile 0.1.0
File Interpreter ABI Platform
nodriver_turnstile-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 13.5 kB

Release files / nodriver_turnstile-0.1.0.tar.gz

Download URL nodriver_turnstile-0.1.0.tar.gz
Size 6.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9961ced5c67be4fb6bc5206438748b9f5c8ccd5426fbf143d68890bc5577fcf7
BLAKE2b-256 checksum
How to use checksums
6f5fb249cede91dff4ddd1f51c7f2b6b206a5a8cbde2e95a5102de0d8f6d0b3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release files / nodriver_turnstile-0.1.0-py3-none-any.whl

Download URL nodriver_turnstile-0.1.0-py3-none-any.whl
Size 6.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8aacc2b30f609400a96860f5e7683c56958cb30a24037150eba8b58a6b21768b
BLAKE2b-256 checksum
How to use checksums
96cba214fc90d9b0d8472a0a896067076b1cc02b2ba648ac90a3b47be3832dfc
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.1.0 This release

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