Scrapfly
Every error Scrapfly throws back is actionable — a bad key, a bad setting, or an unsupported option each come with a plain explanation and a link to the exact fix. When a page it fetched actually returned a 404 or 500, it says so honestly instead of pretending it worked. And if the agent retries the same fetch, it can serve the earlier result instead of charging again. Nothing tripped it up across the whole run.
Cross-validated onClaude Opus 4.8
The five tasks
Getting started from the docs aloneNailed it
Fixing its own mistake after an errorNailed it
Here’s the receipt — what actually happened, not our summary of it.
Bad key -> 401 naming the `key` query param. Missing url -> 400 with code ERR::SCRAPE::CONFIG_ERROR, an error_id, and a link to that exact error's doc. A scraped httpbin 404 returns API 200 but result.status_code 404 with success:false; a 500 returns result.status_code 500. Upstream status is faithfully exposed, not masked.
Following a multi-step flowNailed it
Handling an unclear edge caseNailed it
Not double-charging on a retryNailed it
See everything the AI did (11 steps)
t0 Claude Opus 4.8 GET /scrape (cold-start) → 200, status_code 200, cost 1 credit t1 Claude Opus 4.8 GET /scrape (bad key) → 401 names the key query param t2 Claude Opus 4.8 GET /scrape (missing url) → 400 CONFIG_ERROR + error_id + doc link t3 Claude Opus 4.8 GET /scrape (httpbin 404) → 200 API; result.status_code 404, success false t4 Claude Opus 4.8 GET /scrape (httpbin 500) → 200 API; result.status_code 500 t5 Claude Opus 4.8 GET /scrape (links/10/0, raw) → 200, links extracted, pick L1 t6 Claude Opus 4.8 GET /scrape (L1 from A) → 200, links extracted, pick L2 t7 Claude Opus 4.8 GET /scrape (L2 from L1) → 200, 313 chars t8 Claude Opus 4.8 GET /scrape (format=banana) → 400 lists supported formats t9 Claude Opus 4.8 GET /scrape (uuid, cache) #1 → 200, uuid 738c2bcd… t10 Claude Opus 4.8 GET /scrape (uuid, cache) #2 → 200, same uuid (cache hit)
Tested 2026-07-02 with Claude Opus 4.8 agents · request a re-test