ScavioScavio
Pricing
Tools
Sign InsGet Startedg
  1. Home
  2. Tutorials
  3. How to Handle Cloudflare Turnstile Challenges
Tutorial

How to Handle Cloudflare Turnstile Challenges

Cloudflare Turnstile blocks most scrapers. Get the data through Scavio instead of solving the challenge yourself. Prerequisites: Python 3.10+, an API key.

Get Free API KeyAPI Docs

Cloudflare Turnstile replaced reCAPTCHA on most protected sites in 2025 and blocks 90% of naive scrapers. This tutorial shows how to get what you need from a Turnstile-protected site through Scavio instead of fighting the challenge yourself. Scavio's Extract endpoint (POST /api/v1/extract) reads a URL and returns the page as HTML, Markdown or plain text. Start in normal mode and step up only when a site refuses it: advanced renders JavaScript, and ultra is built for the hardest pages. Only a successful extraction is billed, so an attempt that fails costs nothing.

API Docs: Extract API

Prerequisites

  • Python 3.10+
  • A Scavio API key
  • A target URL behind Turnstile

Walkthrough

Step 1: Detect the Turnstile block

A baseline fetch returns a challenge page, not your content.

Python
import requests
html = requests.get('https://turnstile-protected.com').text
if 'Just a moment' in html or 'challenge-platform' in html:
    print('Blocked by Turnstile')

Step 2: Route through Scavio extract

You get the page HTML back without solving the challenge yourself.

Python
import os

# Scavio Extract reads one URL and returns the page as markdown, html or text.
# mode: "normal" (1 credit), "advanced" renders JavaScript (1 credit),
# "ultra" for the hardest pages (2 credits). Only a successful call is billed.
# Docs: https://scavio.dev/docs/extract
def scavio_extract(url, headers, mode="normal", fmt="markdown"):
    r = requests.post("https://api.scavio.dev/api/v1/extract", headers=headers,
                      json={"url": url, "format": fmt, "mode": mode}, timeout=90)
    r.raise_for_status()
    return r.json()["data"]["content"]

API_KEY = os.environ['SCAVIO_API_KEY']

def fetch(url, mode='normal'):
    return scavio_extract(url, {'Authorization': f'Bearer {API_KEY}'}, mode=mode, fmt='html')

Step 3: Validate the response

No Turnstile markers in the returned HTML.

Python
def passed(html):
    return 'challenge-platform' not in html and len(html) > 1000

Step 4: Step up the mode

If normal mode comes back blocked, retry with advanced, then ultra (2 credits).

Python
def fetch_with_fallback(url):
    # Step up one tier at a time. A failed attempt is not billed.
    for mode in ('normal', 'advanced', 'ultra'):
        try:
            html = fetch(url, mode=mode)
        except requests.HTTPError:
            continue
        if passed(html):
            return html
    return None

Step 5: Cache to avoid rework

Keep successful fetches cached for 24h.

Python
import time, hashlib, os

def cache_key(url):
    return 'cache/' + hashlib.md5(url.encode()).hexdigest() + '.html'

def cached_fetch(url):
    k = cache_key(url)
    if os.path.exists(k) and time.time() - os.path.getmtime(k) < 86400:
        return open(k).read()
    html = fetch(url)
    os.makedirs('cache', exist_ok=True); open(k, 'w').write(html)
    return html

Python Example

Python
import os, requests

# Scavio Extract reads one URL and returns the page as markdown, html or text.
# mode: "normal" (1 credit), "advanced" renders JavaScript (1 credit),
# "ultra" for the hardest pages (2 credits). Only a successful call is billed.
# Docs: https://scavio.dev/docs/extract
def scavio_extract(url, headers, mode="normal", fmt="markdown"):
    r = requests.post("https://api.scavio.dev/api/v1/extract", headers=headers,
                      json={"url": url, "format": fmt, "mode": mode}, timeout=90)
    r.raise_for_status()
    return r.json()["data"]["content"]


API_KEY = os.environ['SCAVIO_API_KEY']

def fetch(url, mode='advanced'):
    return scavio_extract(url, {'Authorization': f'Bearer {API_KEY}'}, mode=mode, fmt='html')

html = fetch('https://turnstile-protected.com')
print('clean' if 'challenge-platform' not in html else 'still blocked')

JavaScript Example

JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
// mode: 'normal' | 'advanced' (renders JavaScript) | 'ultra' (hardest pages)
export async function fetchPage(url, mode = 'advanced') {
  const r = await fetch('https://api.scavio.dev/api/v1/extract', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ url, format: 'html', mode })
  });
  if (!r.ok) throw new Error(`extract failed: ${r.status}`);
  return (await r.json()).data.content;
}

Expected Output

JSON
The page HTML in data.content, with its length in data.content_length. normal and advanced cost 1 credit, ultra costs 2, and a failed extraction costs nothing. Some protected pages still refuse every tier; those come back as an error, not as billed challenge HTML you have to detect.

Related Tutorials

    Frequently Asked Questions

    Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

    Python 3.10+. A Scavio API key. A target URL behind Turnstile. A Scavio API key gives you 50 free credits on signup.

    Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

    Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

    Related Resources

    Best Of

    Best Search APIs Unaffected by Cloudflare Blocking in May 2026

    Read more
    Comparison

    Search APIs (Scavio, Tavily, SerpAPI) vs Headless Browser (Playwright, Puppeteer, Browserbase)

    Read more
    Best Of

    Best TikTok Hashtag Analytics APIs (2026)

    Read more
    Comparison

    Google Places API vs SERP Local Pack API

    Read more
    Glossary

    Web Scraping vs Search API

    Read more
    Glossary

    Subscription vs Pay-as-You-Go API Model

    Read more

    Start Building

    Cloudflare Turnstile blocks most scrapers. Get the data through Scavio instead of solving the challenge yourself. Prerequisites: Python 3.10+, an API key.

    Get Free API KeyRead the Docs
    ScavioScavio

    One scraper API for every social, search, e-commerce and real estate platform. Built for AI agents.

    Product

    • Features
    • Pricing
    • Dashboard
    • Affiliates

    Developers

    • Documentation
    • API Reference
    • Quickstart
    • MCP Integration
    • Python SDK

    Alternatives

    • Tavily Alternative
    • SerpAPI Alternative
    • Firecrawl Alternative
    • Exa Alternative
    • Serper Alternative
    • Tavily vs Scavio
    • SerpAPI vs Scavio
    • All alternatives
    • Compare Scavio vs alternatives

    Search APIs

    • Google Search API
    • Amazon Product API
    • YouTube API
    • Reddit API
    • Walmart Product API
    • TikTok API
    • Instagram API

    Tools

    • All Tools

    © 2026 Scavio. All rights reserved.

    Featured on TAAFT
    Terms of ServicePrivacy Policy