langchain-turnstile
Give a LangChain agent the ability to solve Cloudflare Turnstile. A BaseTool that takes a page URL and a sitekey, calls Peak, and hands back a token. A browsing agent that hits a Turnstile challenge gets a move to make instead of getting stuck.
An agent that browses the web eventually runs into Cloudflare Turnstile. The widget needs a token minted server-side. No fingerprint, proxy, or retry loop gets around that; it's a missing capability, not a detection problem. This package is that capability, packaged as a LangChain Tool: give it a URL and a sitekey, it returns a token.
The tool itself never touches a browser. It is pure request/response to the Peak API, which keeps it usable from any agent regardless of whether it's driving Playwright, Selenium, a raw HTTP client, or nothing at all. Pair it with whatever tool your agent already uses to read the DOM (to get the sitekey) and to run JS (to put the token back); see Closing the loop below.
Install
pip install langchain-turnstile
Use it
from langchain_turnstile import PeakTurnstileTool
tool = PeakTurnstileTool(api_key="pk_...") # or set PEAK_API_KEY
token = tool.run({"url": "https://example.com/login", "sitekey": "0x4AAAAAAA..."})
Hand it to an agent like any other tool:
from langchain.agents import create_agent
from langchain_turnstile import PeakTurnstileTool
agent = create_agent(llm, tools=[*your_browser_tools, PeakTurnstileTool(api_key=api_key)])
The agent decides when to call it, typically after a browsing tool reports it's stuck on a Cloudflare challenge. The tool's description is written for that: an LLM reading the tool list will reach for solve_cloudflare_turnstile when it sees a Turnstile widget blocking a page.
Closing the loop
Reading the sitekey and injecting the token both happen on a live page, which is specific to whatever browser your agent drives, so this package deliberately doesn't pick one for you. inject.py ships the JS every other Peak wrapper package uses, so you can call it from whichever execute_script / page.evaluate your stack exposes:
from langchain_turnstile import build_injection_script
page.evaluate(build_injection_script(token)) # Playwright
driver.execute_script(build_injection_script(token)) # Selenium
It fills every cf-turnstile-response field and fires the widget's data-callback if the page registered one, the same two places a real form submit reads from.
Matching the exit IP
Turnstile scores the IP that submits the token. If your agent's browser runs behind a proxy, pass the same one so the token and the request line up:
tool.run({"url": url, "sitekey": sitekey, "proxy": "http://user:pass@host:port"})
Leave proxy out and the tool solves through Peak's own IP pool instead. Fine for most sites, wrong for the ones that bind the token to the requesting IP.
Errors come back as text, not exceptions
A tool-calling agent works better when a failure is something it can read and react to, rather than a crash that kills the run. PeakTurnstileTool returns "ERROR: <reason>" (bad sitekey, no balance, no key configured) instead of raising, so the agent's next step can be "try a different sitekey" rather than "the whole chain died." Call PeakClient.solve() directly from langchain_turnstile.peak if you want exceptions instead.
Getting a key
The tool 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.
For Cloudflare Turnstile, Cloudflare 5s challenge, AWS WAF, and DataDome:
API-first · $0.35 – $1.00 / 1K · volume tiers · pay only on success · peak.fo
Related
Same pattern for driving a browser directly instead of through an agent: playwright-turnstile · selenium-turnstile · puppeteer-extra-plugin-turnstile · nodriver-turnstile · camoufox-turnstile.
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 agents, testing, and public-data access. Nothing here helps with credential stuffing or abuse. Not affiliated with Cloudflare or LangChain.
License
MIT
Metadata
Release files for langchain-turnstile 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langchain_turnstile-0.1.1.tar.gz | 9.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langchain_turnstile-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 19.7 kB
Release files / langchain_turnstile-0.1.1.tar.gz
| Download URL | langchain_turnstile-0.1.1.tar.gz |
|---|---|
| Size | 9.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8b50efa5a28a00da135661416d29bf4e601fb22dded969083cc15b2be167c279
|
|
BLAKE2b-256 checksum How to use checksums |
5a5f29af5cfb6b1745b41f9045fd57a6ebc648aa9f1f78f4b5caef4b5481073e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Release files / langchain_turnstile-0.1.1-py3-none-any.whl
| Download URL | langchain_turnstile-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e64c8fb250d3b0666ca002a6e035cf6db2ac4581451858fb324dc719e449aca4
|
|
BLAKE2b-256 checksum How to use checksums |
7f301b00d9c28c70828fde779a591d36054f63f0d574de5553ff6dc8a3a7d5d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|