scrapy-turnstile
scrapy-turnstile is a Scrapy downloader middleware that solves Cloudflare Turnstile automatically. When a request hits a Turnstile-protected page, it detects the challenge, solves it through Peak, and re-issues the request with the token so your spider gets the real page.
Why
Scrapy makes plain HTTP requests. It has no JS engine, so a Turnstile-protected site returns a 403 or the "Just a moment..." interstitial instead of the content you asked for. The old scrapy-cloudflare-middleware only handled the legacy IUAM (I'm Under Attack Mode) JS challenge and is unmaintained; it does nothing for Turnstile, which is what Cloudflare now serves. cloudscraper has the same limitation: it can't solve Turnstile.
This middleware routes the Turnstile challenge to Peak, which returns a valid token. 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 scrapy-turnstile
Quickstart
Add the middleware to your project's settings.py and set your Peak key:
# settings.py
DOWNLOADER_MIDDLEWARES = {
"scrapy_turnstile.TurnstileMiddleware": 585,
}
PEAK_API_KEY = "pk_your_api_key" # better: read from an env var
# PEAK_PROXY = "http://user:pass@ip:port" # optional, routed to Peak
Or per-spider:
import os
import scrapy
class ProtectedSpider(scrapy.Spider):
name = "protected"
start_urls = ["https://protected.example.com/"]
custom_settings = {
"DOWNLOADER_MIDDLEWARES": {
"scrapy_turnstile.TurnstileMiddleware": 585,
},
"PEAK_API_KEY": os.environ["PEAK_API_KEY"],
}
def parse(self, response):
# The challenge, if any, was already solved upstream.
yield {"title": response.css("title::text").get()}
export PEAK_API_KEY=pk_your_api_key
scrapy runspider examples/quotes_spider.py
A runnable spider is in examples/quotes_spider.py.
How it works
process_responseinspects every response for Turnstile markers (cf-turnstile, thechallenges.cloudflare.com/turnstilescript, the "Just a moment" interstitial).- On a match it extracts the
data-sitekeyand the request URL. - It calls Peak:
POST https://api.peak.fo/solvewith{"task_type": "turnstiletask", "sitekey": ..., "url": ...}and headerX-API-Key. - It re-issues the original request with the returned token injected as the
cf-turnstile-responseform field, and also onrequest.meta["cf_turnstile_response"]for custom submits. - A
metaflag stops the retried request from being re-processed, so there are no loops.
Peak also supports the Cloudflare 5s interstitial via task_type: "cloudflare5stask".
Settings
| Setting | Default | Purpose |
|---|---|---|
PEAK_API_KEY |
(required) | Your Peak key, format pk_.... |
PEAK_PROXY |
None |
Proxy string forwarded to Peak so the solve matches your crawl IP. |
PEAK_API_URL |
https://api.peak.fo/solve |
Override the solve endpoint. |
PEAK_APP_ID |
None |
Optional app id sent as appId to earn revenue share on each solve. |
PEAK_TURNSTILE_FIELD |
cf-turnstile-response |
Form field the token is injected into. |
PEAK_TURNSTILE_MAX_RETRIES |
2 |
Max solve attempts per request before giving up. |
Earn with your app ID
Set PEAK_APP_ID in your Scrapy settings to earn 5% of every solve your spider makes, paid as Peak solve credit. It is optional and does not change whether a solve succeeds or how fast it returns.
# settings.py
PEAK_APP_ID = "app_your_id" # optional; earns solve credit on each solve
Create an app id at peak.fo/dashboard/developer; details at peak.fo/earn.
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 scrapy-turnstile 0.2.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 | Provenance | |
|---|---|---|---|---|
| scrapy_turnstile-0.2.1.tar.gz | 449.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scrapy_turnstile-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 459.0 kB
Release files / scrapy_turnstile-0.2.1.tar.gz
| Download URL | scrapy_turnstile-0.2.1.tar.gz |
|---|---|
| Size | 449.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3995597f3077c69ee248fda93007caf371e23fe2aa19acb0d78c53db1a8c05d2
|
|
BLAKE2b-256 checksum How to use checksums |
9b30b526133c00ea67ac4133fe30b150100e46f9aecc797239f77f6dc42d58d0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Release files / scrapy_turnstile-0.2.1-py3-none-any.whl
| Download URL | scrapy_turnstile-0.2.1-py3-none-any.whl |
|---|---|
| Size | 9.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
336fc50dff84e971728eced82d8842ad089644b6977d772747a8d8eec0239db5
|
|
BLAKE2b-256 checksum How to use checksums |
4a27addee0591d5f77b49243f36a47db119016f7a00baacec487d799ac33d5b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Security for scrapy-turnstile 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.