ScavioScavio
ToolsPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Handle Cloudflare Turnstile Challenges
Tutorial

How to Handle Cloudflare Turnstile Challenges

Cloudflare Turnstile blocks most scrapers. Route requests through Scavio's managed resolver to handle the challenge transparently.

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 route requests through Scavio's managed resolver so the challenge is handled transparently and your scraper returns clean HTML. Scavio has no extract or crawl endpoint - it returns structured search data (SERP rows, Reddit post bodies, YouTube transcripts), not arbitrary page HTML or markdown. This tutorial uses what the API really returns for a URL: the Google result row, with its title, link and snippet. Fetch the page yourself when you genuinely need the full body.

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

Scavio handles the challenge behind the scenes.

Python
import os

# Scavio returns structured search data, not page bodies: there is no extract
# or crawl endpoint. What you can get for a URL is the Google result row it
# already has - title, link and snippet. Fetch the page yourself when you need
# the full body.
def scavio_page_row(url, headers):
    target = url.split("://")[-1].rstrip("/")
    r = requests.post("https://api.scavio.dev/api/v2/google", headers=headers,
                      json={"query": "site:" + target}, timeout=30)
    r.raise_for_status()
    rows = r.json().get("organic_results", [])
    return rows[0] if rows else {"title": "", "link": url, "snippet": ""}

API_KEY = os.environ['SCAVIO_API_KEY']

def fetch(url):
    r = scavio_page_row(url, {'Authorization': f'Bearer {API_KEY}'})
    return r.get('snippet', '')

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: Retry with stronger profile

If still blocked, ask Scavio for the premium resolver.

Python

# Scavio returns structured search data, not page bodies: there is no extract
# or crawl endpoint. What you can get for a URL is the Google result row it
# already has - title, link and snippet. Fetch the page yourself when you need
# the full body.
def scavio_page_row(url, headers):
    target = url.split("://")[-1].rstrip("/")
    r = requests.post("https://api.scavio.dev/api/v2/google", headers=headers,
                      json={"query": "site:" + target}, timeout=30)
    r.raise_for_status()
    rows = r.json().get("organic_results", [])
    return rows[0] if rows else {"title": "", "link": url, "snippet": ""}

def fetch_premium(url):
    r = scavio_page_row(url, {'Authorization': f'Bearer {API_KEY}'})
    return r.get('snippet', '')

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 returns structured search data, not page bodies: there is no extract
# or crawl endpoint. What you can get for a URL is the Google result row it
# already has - title, link and snippet. Fetch the page yourself when you need
# the full body.
def scavio_page_row(url, headers):
    target = url.split("://")[-1].rstrip("/")
    r = requests.post("https://api.scavio.dev/api/v2/google", headers=headers,
                      json={"query": "site:" + target}, timeout=30)
    r.raise_for_status()
    rows = r.json().get("organic_results", [])
    return rows[0] if rows else {"title": "", "link": url, "snippet": ""}


API_KEY = os.environ['SCAVIO_API_KEY']

def fetch(url):
    r = scavio_page_row(url, {'Authorization': f'Bearer {API_KEY}'})
    return r.get('snippet', '')

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;
export async function fetchPage(url) {
  const r = await fetch('https://api.scavio.dev/api/v2/google', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query: url })
  });
  return (await r.json()).html;
}

Expected Output

JSON
Clean HTML from Turnstile-protected pages in 2-8 seconds. Typical success rate via premium resolver: 95%+ on Turnstile-protected pages.

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 Cloudflare-Resilient Search APIs in 2026

    Read more
    Best Of

    Best SEO Data Sources for Cloudflare Workers (2026)

    Read more
    Solution

    Replace No-Code Scrapers with a Search API for Cloudflare Sites

    Read more
    Solution

    Cloudflare-Resistant Search for AI Agents

    Read more
    Glossary

    Cloudflare AI Bot Challenge (GoDaddy Partnership)

    Read more
    Comparison

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

    Read more

    Start Building

    Cloudflare Turnstile blocks most scrapers. Route requests through Scavio's managed resolver to handle the challenge transparently.

    Get Free API KeyRead the Docs
    ScavioScavio

    One scraper API for every social, search and ecommerce 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