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

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

  1. process_response inspects every response for Turnstile markers (cf-turnstile, the challenges.cloudflare.com/turnstile script, the "Just a moment" interstitial).
  2. On a match it extracts the data-sitekey and the request URL.
  3. It calls Peak: POST https://api.peak.fo/solve with {"task_type": "turnstiletask", "sitekey": ..., "url": ...} and header X-API-Key.
  4. It re-issues the original request with the returned token injected as the cf-turnstile-response form field, and also on request.meta["cf_turnstile_response"] for custom submits.
  5. A meta flag 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

scrapy_turnstile-0.1.0.tar.gz (448.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scrapy_turnstile-0.1.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

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

Hashes for scrapy_turnstile-0.1.0.tar.gz
Algorithm Hash digest
SHA256 618dd36c6b2f0ba523c419274fd4684bcf0e2ffc1756146363dd7aebdd1358b4
MD5 254d70ca17c45ea28f0b4b6b66900793
BLAKE2b-256 b82cead89ca44a41c9e8e033030dca23ad37e31776d0822f1fca79a6a1f20de8

See more details on using hashes here.

File details

Details for the file scrapy_turnstile-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for scrapy_turnstile-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5f2a87930a3ecb0966cc5eb2ea9e75b6216f9d65ba60c73bebeb05e6c86e6e1d
MD5 7525329452655c2f3c2b8efd1390159a
BLAKE2b-256 101c12b6d505a260444f82a104d2944e5287d1e67256d47b20098e9a698929d7

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 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