This article was originally published on the Zenrows blog.
This post compares five web scraping APIs for AI agents using 800 benchmark requests against DataDome, Cloudflare, and Akamai. It then shows you how to connect the strongest performer to Claude Desktop, the OpenAI Agents SDK, and LangChain in a few lines of code.
The APIs are Zenrows, Firecrawl, Jina AI Reader, CrawlForge, and Bright Data. Every number below comes from a public benchmark repository with the raw per-request results, so you can rerun any of it yourself.
The short version
| Provider | Protected-target success rate | Avg. response time |
|---|---|---|
| Zenrows | 100.00% | 5,215 ms |
| Jina | 99.33% | 1,257 ms |
| Firecrawl | 66.67% | 1,497 ms |
| CrawlForge | 0.00% | 867 ms |
All four tested APIs scored 100 percent on an unprotected Wikipedia page. The protected targets are where they separated. Bright Data wasn't part of the test because it requires enterprise KYC.
Why test anti-bot access first
Scraping APIs for agents usually get compared on output format, MCP support, and JavaScript rendering. Those features matter once the agent has the page. The harder question is whether the agent gets the page at all when Cloudflare, DataDome, or Akamai protects the target.
Public docs, company blogs, and news sites rarely cause trouble. E-commerce pricing pages, job boards, and industry directories are different. They return challenge pages, empty responses, or partial content, and the agent has nothing useful to work with. That's why this comparison measures anti-bot success rate before anything else.
How the benchmark worked
- Zenrows, Jina AI Reader, and CrawlForge ran on August 20, 2026, with Zenrows using Fetch in
mode=auto. - Firecrawl ran on August 25, 2026, in
proxy=automode, which starts in standard mode and retries in stealth mode. - Each provider got 50 requests per target at a fixed rate of two requests per second, for 800 requests in total.
- The targets were JobLookup behind DataDome, Chrono24 behind Cloudflare, Reuters behind Akamai, and Wikipedia with no protection as a baseline.
- A request counted as successful only if it returned an HTTP 200 status code and a valid page title or meaningful data.
Every figure was recomputed from the raw dataset on October 1, 2026, so each one traces back to a logged request.
Full results
| Provider | Target | Protection | Success rate | Avg. response time (ms) |
|---|---|---|---|---|
| Zenrows | JobLookup | DataDome | 100% | 10,053 |
| Zenrows | Chrono24 | Cloudflare | 100% | 4,590 |
| Zenrows | Reuters | Akamai | 100% | 4,103 |
| Zenrows | Wikipedia | Unprotected | 100% | 2,115 |
| Jina | JobLookup | DataDome | 98% | 1,029 |
| Jina | Chrono24 | Cloudflare | 100% | 1,417 |
| Jina | Reuters | Akamai | 100% | 1,242 |
| Jina | Wikipedia | Unprotected | 100% | 1,340 |
| Firecrawl | JobLookup | DataDome | 0% | 1,299 |
| Firecrawl | Chrono24 | Cloudflare | 100% | 1,688 |
| Firecrawl | Reuters | Akamai | 100% | 1,488 |
| Firecrawl | Wikipedia | Unprotected | 100% | 1,512 |
| CrawlForge | JobLookup | DataDome | 0% | 781 |
| CrawlForge | Chrono24 | Cloudflare | 0% | 709 |
| CrawlForge | Reuters | Akamai | 0% | 728 |
| CrawlForge | Wikipedia | Unprotected | 100% | 1,251 |
Zenrows returned a usable page on every request across all four targets. Jina came closest and failed once against JobLookup. Firecrawl hit a reCAPTCHA page on all 50 JobLookup requests and scored 100 percent on the other three targets. CrawlForge got 403s on JobLookup and Chrono24 and a 401 on Reuters, so it only succeeded on Wikipedia.
| Provider | Avg. success rate (3 protected targets) | Avg. response time (4 targets) | Observed consumption per request (4 targets) |
|---|---|---|---|
| Zenrows | 100.00% | 5,215 ms | 4.59 credits |
| Jina | 99.33% | 1,257 ms | 24,922.58 tokens |
| Firecrawl | 66.67% | 1,497 ms | 1 credit |
| CrawlForge | 0.00% | 867 ms | 1 credit |
Jina was the fastest API that returned content on the protected targets. CrawlForge's low average reflects how quickly it was turned away. Zenrows was slower on average, especially on the protected targets, where it was the only API to clear every request.
Consumption uses each provider's native unit, so the figures don't compare directly on cost. They're dashboard readings taken before and after the run, divided by the 200 requests each provider served, and the balances are in the repository. A low consumption figure says little about value when the requests behind it fail.
How Zenrows credits scale with protection
The 4.59-credit average for Zenrows blends four very different targets, because mode=auto escalates only as far as each target forces it to.
The unprotected Wikipedia page cost one credit per request. Reuters, behind Akamai, cost ten. Cloudflare-protected Chrono24 averaged 2.36 because not every request needed the full escalation. For an agent whose targets mix easy and hard pages, you pay for the protection each page puts up.
The five APIs
Zenrows
Zenrows fits agents that need protected and dynamic web sources. It scored 100 percent across the protected targets in this benchmark, and Zenrows publishes a 99.93 percent success rate across its wider target set. Zenrows Fetch handles Cloudflare, DataDome, Akamai, and PerimeterX, along with dynamic website support, in one API call.
It returns pages as LLM-ready Markdown, plain text, or PDF, and Zenrows Extract returns structured JSON without pre-written CSS selectors. The Agent Toolkit ships on every plan and includes the following:
- An MCP server exposes
scrape,extract, and more than 30browser_*tools, with first-party setup guides for Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, Zed, JetBrains IDEs, OpenCode, Google Antigravity, the Claude Agent SDK, the OpenAI Agents SDK, Google ADK, and Mastra. You can run it locally overnpxor use the hosted endpoint, and the tool surface is identical either way. - A CLI gives terminal-native agents
zenrows fetchandzenrows extract, andzenrows mcp config --client claude-codewrites the MCP configuration for a client. - Agentic payments let an agent buy its own access. Zenrows publishes a machine-readable API catalogue with prices an agent can read without a login, and it settles through x402, MPP, or a card. An agent that hits a 402 challenge can complete the purchase and carry on.
Zenrows Batch adds async jobs of up to 100,000 URLs with concurrency, retries, and webhook delivery. The free tier gives you 5,000 credits a month with no card. Paid plans run from the Build tier at $16/month for 45,000 credits to the Scale tier at $458/month for five million credits, plus a custom Enterprise tier. Billing is pay per successful request, so blocked requests cost nothing.
Firecrawl
Firecrawl suits agents that access unprotected or lightly protected sources, and it averaged 66.67 percent across the protected targets here. Its output is built for LLMs, with Markdown, JSON Schema generation, and metadata extraction designed for RAG and chunking. It also offers /agent and /interact endpoints for multi-page exploration and stateful browser control.
All 50 of its JobLookup responses came back as a reCAPTCHA page, even with stealth retries. Its AI Extract feature needs a separate subscription on top of the base plan. Firecrawl has a free plan with 1,000 credits a month and paid plans from $19/month.
Jina AI Reader
Jina is a zero-setup gateway that converts URLs into LLM-ready Markdown when you prepend r.jina.ai/ to them. It includes image captioning for multimodal agents. It placed second in this benchmark at 99.33 percent across the protected targets.
Its token consumption varied with the amount of content returned and averaged 24,922.58 tokens per request, which makes billing harder to predict on large crawls. Jina offers 10 million free tokens, and paid usage starts at $50, at $0.050 per million tokens. It's a good match for quick lookups of documentation, news, and public web content.
CrawlForge
CrawlForge is MCP-native and ships 31 specialized tools an agent can discover without wrapper code, including fetch_url, deep_research, map_site, and scrape_template. It produces token-efficient Markdown, can run extraction schemas locally through Ollama at no cost, and charges a predictable one credit for a basic fetch and up to 10 for deep research.
It scored zero percent on all three protected targets and 100 percent on Wikipedia. CrawlForge has a free tier of 1,000 credits and paid plans from $19/month for 5,000 credits. It works best for agents on MCP-native hosts that mostly access unprotected sources.
Bright Data
Bright Data is the enterprise option for protected-site access. It runs a pool of more than 150 million IPs and holds SOC 2 Type II and ISO 27001 certifications. Its Web Unlocker, Browser API, and Residential Proxies products each have $499/month Scale plans, so the full stack costs more than a typical self-service tool. It fits enterprise teams with five-figure monthly data budgets, compliance requirements, and dedicated data engineering staff.
Connecting Zenrows to your agent
You can give an agent access to live web data through the Zenrows MCP server or through a framework integration. Each pattern below needs a Zenrows API key, which you can get from the signup page.
Claude Desktop and other MCP hosts
{
"mcpServers": {
"zenrows": {
"command": "npx",
"args": ["-y", "@zenrows/mcp"],
"env": {
"ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY"
}
}
}
}
Add that block to claude_desktop_config.json and restart Claude Desktop. Claude can then call the scrape and browser_* tools whenever a task needs them. To see how this server compares with the alternatives, read the test of seven MCP servers for web scraping.
OpenAI Agents SDK
import asyncio
import os
from agents import Agent, HostedMCPTool, Runner
ZENROWS_API_KEY = os.environ["ZENROWS_API_KEY"]
agent = Agent(
name="Web Research Assistant",
instructions="Use live web data when you need current information.",
tools=[
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "zenrows",
"server_description": "Web data access through Zenrows.",
"server_url": "https://mcp.zenrows.com/mcp",
"authorization": ZENROWS_API_KEY,
"require_approval": "never",
}
)
],
)
async def main():
result = await Runner.run(
agent,
"Visit https://news.ycombinator.com/ and summarize the three most recent posts.",
)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
The OpenAI Agents SDK supports MCP natively through HostedMCPTool, so this connects the hosted Zenrows MCP server with no custom function-calling logic. If you'd prefer to register Fetch as a plain function tool, this guide to building a web-aware agent with the OpenAI Agents SDK covers it.
LangChain
from langchain_zenrows import ZenRowsUniversalScraper
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(model="gpt-4o-mini")
zenrows_tool = ZenRowsUniversalScraper()
agent = create_react_agent(llm, [zenrows_tool])
result = agent.invoke({
"messages": [
{
"role": "user",
"content": "Scrape https://www.etsy.com/ in Markdown and return the four cheapest products in JSON."
}
]
})
The langchain-zenrows package exposes Zenrows as a LangChain tool, so the agent calls it whenever it needs live web data. Set ZENROWS_API_KEY as an environment variable before you run it.
Everything at a glance
| Criteria | Zenrows | Firecrawl | Jina AI Reader | CrawlForge | Bright Data |
|---|---|---|---|---|---|
| Best for | AI agents accessing protected and dynamic web sources | RAG, LLM data ingestion, and unprotected or lightly protected sources | Quick lookups of documentation, news, and public web content | MCP-native agents accessing primarily unprotected sources | Enterprise teams requiring protected web access |
| Protected-target success rate | 100% | 66.67% | 99.33% | 0% | Not tested (requires enterprise-level KYC) |
| Output formats | Markdown, plaintext, PDF, structured JSON with Extract | Markdown, JSON Schema, metadata | LLM-ready Markdown, visual descriptions | Markdown, extraction schemas | HTML, Markdown, structured data and other formats depending on product |
| MCP server | Yes | Yes | Yes, official and community | Yes | Yes |
| SDK support | Python, Node.js, Go | Python, Node.js, and others | HTTP API | No dedicated SDK | Multiple SDK and API integrations |
| Free tier | 5,000 credits/month, no card | 1,000 credits/month | 10 million tokens | 1,000 credits | 5,000 credits/month |
| Entry price | $16/month | $19/month | $50 | $19/month | Product-dependent, with Scale plans from $499/month |
| Success-billed only | Yes | Partial (only API-level failures are free) | No | No | Partial (Web Unlocker, SERP API, and Web Scraper API products only) |
| KYC required | No | No | No | No | Yes for Residential and Mobile IP networks |
| Benchmark source | Our benchmark | Our benchmark | Our benchmark | Our benchmark | Not tested |
What the benchmark settles
Every API here handles output format and tool coverage well. Protected access decides whether an agent returns an answer or a challenge page, and that's where the five tools differ most.
Across 800 requests, Zenrows was the only API to return a usable page every time on DataDome, Cloudflare, Akamai, and the unprotected baseline. It charged one credit for the page that needed no escalation. Jina came closest and runs faster on open targets. Firecrawl and CrawlForge are reasonable choices for agents whose targets stay public.
Choose based on the targets your agent will hit. If any of them sit behind an anti-bot system, start with 5,000 free credits and run your own list through Fetch before you commit.
What's next
- Clone the benchmark repository and swap in your own targets to see how each API handles them.
- Build a full agent on top of Fetch with this guide to an AI lead generation agent with the OpenAI Agents SDK.
- Compare a wider set of options in the roundup of AI web scraping tools.
FAQ
Can AI agents scrape websites protected by Cloudflare or DataDome?
They can when the API they call handles the protection for them. In this benchmark, two of the four tested APIs returned nothing usable from the DataDome target across 50 requests each. Zenrows returned a valid page on every request to the Cloudflare, DataDome, and Akamai targets.
What's the difference between a web scraping API and a scraping MCP server?
A web scraping API is the service that fetches the page. An MCP server hands that service to an agent as a callable tool. Zenrows offers both, so the same Fetch capability works over REST, through the CLI, or as an MCP tool your agent discovers automatically.
Does an AI agent need JavaScript rendering to scrape a page?
It depends on the target. Pages that build their content in the browser return little usable text without rendering, which is why a plain HTTP fetch often comes back empty. Zenrows' mode=auto decides per request, so the agent doesn't have to.
Can I use Zenrows with CrewAI?
You can. CrewAI and other agent frameworks connect to Zenrows through its MCP server, and LangChain agents can use the langchain-zenrows package.







Top comments (1)
Nice benchmark. One cheap step that pairs well with this: after any plain fetch, check how much text actually came back, because a 200 OK with almost no text usually means the page needs JavaScript. Only fall back to a headless browser in that case, and you keep cost and latency down for the majority of pages that render fine without it.