By the fastCRW team · Benchmark figures verified 2026-05-18 against the 2026-05-08 run of record · Cite raw numbers, not multiples · Verify independently before quoting internally.
Disclosure: We build fastCRW. This is a vendor-authored benchmark write-up, so weight it accordingly — we publish the full percentile split, not a single flattering average, because a latency post that hides its own distribution is useless to anyone building a real system.
What latency-sensitive web scraping actually means
"Latency-sensitive web scraping" is not a single number you can shop for. It is a constraint: somewhere in your system, a human or an agent is waiting on the scrape to finish before anything else can happen. A live UI that fetches a page on click, a synchronous agent tool call inside a reasoning loop, a monitoring probe that has to alert within seconds — these share a property that bulk overnight jobs do not. The clock is running while the request is in flight, and a slow request is a visible failure, not just a slower batch.
That changes which metric matters. For an offline pipeline you care about throughput and the median. For a latency-sensitive path you care about the tail — the requests in the slow 10% or 1% — because those are the ones that blow your deadline and strand the caller. The honest design question is therefore never "which scraper has the lowest average?" It is "how do I fit this scraper's distribution inside my latency budget, and what do I do when a request lands in the tail?"
Synchronous agent calls and live UIs
A synchronous scrape inside an agent loop blocks the entire reasoning step. The model cannot plan its next action until the page comes back, so a slow scrape is dead time the user feels directly. Live UIs are the same shape: a spinner that runs past a couple of seconds reads as broken, regardless of what the median was. Both cases are dominated by the worst case they regularly hit, not the typical case.
Latency budgets and timeouts
A latency budget is the total wall-clock time you can spend before the caller gives up — say 8 seconds for an agent step, or 3 seconds for a UI fetch. Inside that budget you have to fit DNS, connection, the actual fetch and render, and your own post-processing. The scraper's contribution is the part you can measure and design around, which is exactly why you want its full distribution, not a marketing average.
Median vs tail for your budget
If your budget comfortably exceeds the median but not the tail, you are not safe — you are gambling that requests stay typical. One request in ten landing at the p90 will blow a budget sized for the p50. The rest of this post is about reading that gap honestly and engineering around it.
Design patterns for tight latency budgets
Before any benchmark numbers, the patterns matter more than the tool, because they apply to every scraper including ours. A latency-sensitive system that ignores these will struggle on any backend.
Deadlines and per-call timeouts
Set an explicit per-call deadline below your budget and treat a breach as a normal, expected outcome rather than an error. If your agent step has 8 seconds, give the scrape 6 and reserve 2 for everything else. When the deadline trips, fall back — return partial context, a cached version, or a "couldn't fetch in time" signal the agent can reason about — instead of letting the loop hang. A deadline you act on is the single highest-leverage defense against a slow tail.
Async crawl jobs over synchronous scrape
If you need many pages and can tolerate getting them slightly later, do not loop synchronous scrapes on the hot path. fastCRW's /v1/crawl is asynchronous: you POST a job, get an ID back immediately, and poll /v1/crawl/:id for results. The caller is never blocked on the slowest page. Reserve synchronous /v1/scrape for the one page a user or agent is actually waiting on, and push everything else off the critical path.
Concurrency to mask the tail
Because fastCRW is stateless per request — there is no session to warm or reuse — you can fan out independent scrapes concurrently and let the median absorb the occasional slow one. If you need five pages and issue them in parallel, your wall-clock cost trends toward the slowest of five rather than the sum of five. That is the cheapest way to keep a tail-heavy distribution inside a budget, and it works precisely because the engine carries no per-request state that would serialize the calls.
How fastCRW's latency profile fits a budget
Here are the numbers, from the run of record. The scrape benchmark used Firecrawl's own public scrape-content-dataset-v1 (1,000 URLs, 819 of them carrying labeled ground truth), measured with the diagnose_3way.py harness across 3,000 requests in a single run on 2026-05-08. Same dataset, same harness, three tools, identical inputs.
| Latency percentile | fastCRW | Crawl4AI | Firecrawl |
|---|---|---|---|
| p50 (median) | 1914 ms | 1916 ms | 2305 ms |
| p90 (fast mode) | 4348 ms | 4754 ms | 6937 ms |
| p99 | — | 13749 ms | 21107 ms |
p50 1914 ms is the lowest of the three
On the typical request, fastCRW has the lowest p50 of the three: a p50 of 1914 ms versus Firecrawl's 2305 ms, and effectively tied with Crawl4AI's 1916 ms (two milliseconds apart — call it a draw). For a budget sized around the median, fastCRW gives you the most headroom of the three. This is the honest headline, and it is scoped to the median on purpose — we do not claim a speed multiple, because the distribution does not support one.
p90 in fast mode: 4348 ms — the lowest of the three
In fast mode, fastCRW's p90 is 4348 ms — the lowest of the three tools (Crawl4AI 4754 ms, Firecrawl 6937 ms). If your latency budget is tight, fast mode gives you the most p90 headroom of any tool in this benchmark.
Why the mode choice matters
fastCRW's highest truth-recall — 63.74% of the 819 labeled URLs, versus Crawl4AI's 59.95% and Firecrawl's 56.04% (diagnose_3way.py, 2026-05-08) — comes from a chrome-stealth path that recovers pages the others miss. In fast mode that same path delivers the lowest p90. In recall mode, additional recovery work on the hardest pages extends the tail. fastCRW also scored ~92% scrape-success of reachable URLs with 0 thrown errors across the 3,000 requests. Choose the mode that matches whether your binding constraint is coverage or worst-case latency.
Live retrieval: the search path has lower latency
If your latency-sensitive workload is search rather than full-page scrape — the common case for grounding an agent's answer — the relevant numbers come from a different, self-consistent benchmark. The search benchmark (triple-bench.ts, 100 queries across 10 categories, run concurrently against all three providers, single point-in-time) measures /v1/search, not /v1/scrape.
| Search metric | fastCRW | Firecrawl | Tavily |
|---|---|---|---|
| Average latency | 880 ms | 954 ms | 2,000 ms |
| Median latency | 785 ms | 932 ms | 1,724 ms |
| Latency wins | 73/100 | 25/100 | 2/100 |
880 ms average, 785 ms median over 100 queries
fastCRW search averaged 880 ms over the 100-query benchmark with a 785 ms median, and won 73 of 100 latency races against Firecrawl and Tavily; all three providers hit 100% success. Search retrieval is a much tighter distribution than full scrape because there is no per-page chrome fallback in the hot path — which is exactly why a sub-second median search is a better fit inside a reasoning loop than a synchronous full scrape, with lower latency than a synchronous full scrape.
When to reach for search instead of scrape
If your agent needs to ground an answer and does not strictly need the full rendered page, the search path keeps you in sub-second median territory and sidesteps the scrape tail entirely. Use full /v1/scrape when you genuinely need the page's content; use /v1/search when a ranked set of results plus snippets is enough. On managed cloud, search answer mode runs a managed LLM, which is part of why the search path stays fast and cheap.
Choosing a tool by latency profile
The decision is not "which has the lowest latency" but "which percentile governs my budget."
Median-first vs tail-first decisions
| Your workload | Governing percentile | What to pick |
|---|---|---|
| Bulk batch, overnight, offline | p50 / throughput | fastCRW (best median, highest recall) |
| Concurrent fan-out with deadlines | p50, tail masked by concurrency | fastCRW (stateless, parallelizes well) |
| Live agent search / grounding | search p50/p95 | fastCRW search (785 ms median) |
| Hard synchronous deadline, no fallback | scrape p90 | fastCRW fast mode (4348 ms p90) — the lowest of the three |
Where fastCRW fits, and where it does not
fastCRW fits latency-sensitive work when you can (a) use fast mode to get the lowest p90 of the three, (b) mask any tail with concurrency and deadlines, or (c) use the search path instead of full scrape. In recall mode, the hardest pages take longer to recover; if maximum recall matters more than tail latency, that is the right trade — if not, fast mode is designed for you. The full distribution, dataset, and harness are public on the benchmarks page so you can verify all of this before committing.
Sources
- Scrape benchmark of record:
diagnose_3way.pyover Firecrawl's publicscrape-content-dataset-v1(1,000 URLs / 819 labeled), 3,000 requests, single run 2026-05-08 — see /benchmarks. - Search benchmark:
triple-bench.ts, 100 queries across 10 categories, single point-in-time run, all three providers concurrent. - fastCRW repo and pricing: github.com/us/crw · /pricing.
Related: Scraping latency explained · Honest tail latency for agents · Web search API latency benchmark · The fastCRW benchmark in full
