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
- Pay only for successful solves — from $1 / 1,000
- 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_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. |
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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scrapy_turnstile-0.1.0.tar.gz.
File metadata
- Download URL: scrapy_turnstile-0.1.0.tar.gz
- Upload date:
- Size: 448.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
618dd36c6b2f0ba523c419274fd4684bcf0e2ffc1756146363dd7aebdd1358b4
|
|
| MD5 |
254d70ca17c45ea28f0b4b6b66900793
|
|
| BLAKE2b-256 |
b82cead89ca44a41c9e8e033030dca23ad37e31776d0822f1fca79a6a1f20de8
|
File details
Details for the file scrapy_turnstile-0.1.0-py3-none-any.whl.
File metadata
- Download URL: scrapy_turnstile-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f2a87930a3ecb0966cc5eb2ea9e75b6216f9d65ba60c73bebeb05e6c86e6e1d
|
|
| MD5 |
7525329452655c2f3c2b8efd1390159a
|
|
| BLAKE2b-256 |
101c12b6d505a260444f82a104d2944e5287d1e67256d47b20098e9a698929d7
|