If you're building with browser-use, crawl4ai, OpenClaw, or any AI agent framework that touches the web, you've probably hit this: your agent navigates to a page and gets stuck on a Cloudflare challenge screen. It can't click through. It can't solve it. Your pipeline dies. Here's what's happening and how to fix it.
The Problem: Every AI Agent Framework Is Hitting This
This isn't a niche issue. It's the #1 blocker for AI agents that interact with real websites. Look at the open issues:
- browser-use/web-ui #327 — "Cloudflare challenge blocks agent from proceeding"
- browser-use/browser-use #356 — "Agent stuck on Cloudflare verification page"
- crawl4ai #78 — "Cloudflare protected sites return challenge page"
- puppeteer-extra #920 — "Stealth plugin no longer bypasses Cloudflare"
The pattern is the same every time: agent launches a browser, navigates to a URL, and Cloudflare intercepts with a Turnstile challenge or managed challenge page. The agent has no way to solve it — it just sees a blank interstitial and eventually times out.
Why Stealth Plugins Don't Work
The first thing people try is puppeteer-extra-plugin-stealth or playwright-stealth. These patch obvious automation signals like navigator.webdriver and remove CDP bindings from the window object. But Cloudflare's detection goes far deeper than that.
As we covered in our deep dive on why agents get CAPTCHAs, Cloudflare detects automation through:
- CDP protocol detection — The Chrome DevTools Protocol itself leaks signals that can't be patched from userland JavaScript
- Runtime.enable binding artifacts — Even after cleanup, traces of automation bindings persist in the V8 runtime
- Hardware fingerprinting — WebGL renderer, canvas hashes, and AudioContext signatures expose VPS and Docker environments
- Behavioral analysis — Mouse movements, scroll patterns, and timing that no agent framework simulates realistically
Stealth plugins patch the surface. Cloudflare checks the depth. It's an arms race where Cloudflare has a dedicated team and you don't.
The Three Approaches People Try
1. Stealth Plugins — Unreliable
Works sometimes, breaks constantly. Every Cloudflare update can invalidate your patches. You'll spend more time maintaining stealth configs than building your actual product. The GitHub issues above are full of people cycling through stealth plugin versions trying to find one that still works.
2. Residential Proxies — Expensive, Doesn't Solve the CAPTCHA
Residential proxies give you clean IPs, which helps avoid IP-based rate limits. But Cloudflare's Turnstile challenge isn't just about your IP — it's about your browser environment. A residential IP with a headless Chrome that leaks CDP signals still gets challenged. You're paying $10-50/GB for proxies and still hitting CAPTCHAs.
3. CAPTCHA Solving APIs — The Right Answer
Instead of trying to make your automated browser look real, offload the CAPTCHA to a service that solves it on a clean, undetectable environment. You get back a valid token. Your agent never has to interact with the challenge at all. No browser fingerprint games, no stealth plugins, no arms race.
How GateSolve Works
GateSolve is an async CAPTCHA solving API built for agent workflows. The flow is simple:
- Submit — Send the target URL and sitekey to GateSolve's API
- Solve — GateSolve runs the challenge on a clean browser instance with real hardware fingerprints — no automation artifacts
- Retrieve — Get the solved token back via polling or webhook callback
- Inject — Use the token in your agent's HTTP request or inject it into the page DOM
Because GateSolve solves on separate, clean browser instances, your agent's browser is never exposed to the challenge. There's nothing to detect — your code just makes an API call and gets a token back.
Python: For crawl4ai / browser-use Users
If you're using Python-based agent frameworks, the gatesolve SDK handles the solve-and-poll flow in one call:
from gatesolve import GateSolve
gs = GateSolve(api_key="gs_your_key")
result = gs.solve(
url="https://target-site.com",
type="turnstile",
sitekey="0x4AAAA..."
)
# Use the token in your agent's request
import requests
response = requests.post("https://target-site.com/api", data={
"cf-turnstile-response": result.token,
"query": "your agent's payload",
})The SDK handles polling automatically. gs.solve() blocks until the token is ready (typically 5-15 seconds) and returns it directly. For more control, you can use the raw API:
import requests
import time
# 1. Submit the CAPTCHA task
resp = requests.post("https://api.gatesolve.dev/v1/solve", json={
"url": "https://target-site.com",
"type": "turnstile",
"sitekey": "0x4AAAA...",
}, headers={
"Authorization": "Bearer gs_your_key",
})
task_id = resp.json()["task_id"]
# 2. Poll for the result
while True:
status = requests.get(
f"https://api.gatesolve.dev/v1/solve/{task_id}",
headers={"Authorization": "Bearer gs_your_key"},
).json()
if status["state"] == "completed":
token = status["token"]
break
time.sleep(2) # Typically resolves in 5-15 secondsPuppeteer/Playwright: Drop-In Provider
If you're using puppeteer-extra with the recaptcha plugin, GateSolve works as a drop-in provider replacement. Same API, same page.solveRecaptchas() interface — just swap the provider config:
import puppeteer from "puppeteer-extra";
import RecaptchaPlugin from "@gatesolve/recaptcha-provider";
// Drop-in replacement for puppeteer-extra-plugin-recaptcha
puppeteer.use(
RecaptchaPlugin({
provider: {
id: "gatesolve",
token: "gs_your_key",
},
})
);
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://target-site.com");
// Automatically finds and solves CAPTCHAs on the page
const { solved } = await page.solveRecaptchas();
console.log(`Solved ${solved.length} CAPTCHAs`);
await page.click("#submit");Install with npm install @gatesolve/recaptcha-provider. It supports Turnstile, reCAPTCHA v2, reCAPTCHA v3, and hCaptcha — all through the same solveRecaptchas() interface.
Why This Matters for AI Agents
AI agents are increasingly expected to interact with real websites — filling forms, extracting data, completing workflows. But the web wasn't built for agents. Cloudflare protects over 20% of all websites, and their bot detection is getting more aggressive, not less.
The frameworks themselves can't solve this. browser-use uses Playwright under the hood — which means CDP, which means detectable. crawl4ai runs headless Chromium — same problem. Even frameworks that try to be clever about it (connecting to existing browser instances, using Chrome profiles) still leak automation signals at the protocol level.
The only reliable approach is to separate CAPTCHA solving from browser automation entirely. Let your agent do what it's good at — navigating, clicking, extracting — and offload the one thing it can't do (passing bot detection) to a purpose-built service.
TL;DR
- ✕Stealth plugins — arms race you can't win; breaks with every Cloudflare update
- ✕Residential proxies — clean IPs don't help when your browser leaks CDP signals
- ✓GateSolve API — solve CAPTCHAs on clean browsers, get tokens back, inject into your agent's flow