By the fastCRW team · Benchmarks and footprint verified 2026-05-18 · fastCRW launch pricing expires 2026-06-01 · Verify independently before relying on any figure.
Disclosure: we build fastCRW. This is a vendor-authored tutorial, so weight it accordingly — but the latency tail and the missing endpoints below are stated plainly because a setup guide that hides them wastes your afternoon, not ours.
Mastra TypeScript agents and the web-data gap
Mastra is a TypeScript-native agent framework, and the mastra typescript fastcrw integration pattern exists because Mastra gives you the orchestration — agents, tools, workflows, memory — but no opinion on how to fetch the live web. The moment one of your agents needs the current state of a page rather than the model's training data, you need a tool that turns a URL into clean, LLM-ready markdown. This guide wires fastCRW in as that tool: a typed Zod tool over a Firecrawl-compatible REST API, backed by an engine that is a single ~8 MB binary you can self-host.
Where Mastra tools fit in the agent loop
A Mastra agent reasons, decides it needs information, calls a tool, and folds the result back into the next reasoning step. A web-fetch tool sits squarely on that path: the agent passes a URL (or a query), the tool returns markdown, and the agent reads it. The quality of that markdown is the ceiling on the agent's answer — garbage in, confidently-wrong out. So the two things that matter for a Mastra web tool are the cleanliness of the extracted content and the predictability of the call's latency and cost.
Why TypeScript teams want typed tool I/O
Mastra leans on Zod for tool input and output schemas, which means the agent runtime validates arguments before your tool runs and validates the shape your tool returns. That discipline is the whole reason teams pick a typed framework. A web tool should honor it: declare exactly what it accepts (a URL, an optional renderer) and exactly what it returns (markdown plus metadata), so a malformed tool call fails at the boundary instead of three steps downstream.
Define a fastCRW tool with a Zod schema
fastCRW exposes a Firecrawl-compatible REST surface — /v1/scrape, /v1/crawl, /v1/map, /v1/search — so from Node you are just making typed fetch calls and wrapping them in createTool.
createTool with Zod input/output
Define the tool once, with explicit schemas on both sides:
- Input schema:
{ url: z.string().url(), renderer: z.enum(["auto","http","lightpanda","chrome"]).default("auto") }. - Output schema:
{ markdown: z.string(), title: z.string().optional(), sourceUrl: z.string() }. - execute: calls fastCRW and maps the response onto the output schema. Because Mastra validates the return against the schema, a partial or error response surfaces as a typed failure your agent can branch on.
Calling the Firecrawl-compatible REST from Node
Inside execute, POST to /v1/scrape with { url, formats: ["markdown"] } and an Authorization: Bearer header. Pull data.markdown off the response and return it. Keep the call abortable with an AbortController timeout — you will want that when we discuss the latency tail below.
Base-URL swap from Firecrawl to fastcrw.com
If you already have a Mastra tool built against Firecrawl's SDK, the migration is a base-URL change, not a rewrite. Point the client's API URL at https://fastcrw.com (or your self-hosted host) and keep everything else. The honest caveat from our own compatibility notes: a few response field names and the error-envelope shape diverge slightly, and cloud-only Firecrawl specialties have no fastCRW equivalent — validate that short list once before cutover. See the base-URL swap walkthrough for the exact diff.
A worked example: a research workflow
The canonical Mastra use case is a research agent: find sources, read them, synthesize. fastCRW covers both halves of that.
Search then scrape to markdown
Add a second tool over /v1/search so the agent can discover URLs before it reads them. The flow is: the agent calls the search tool with a query, gets back a ranked list of results, picks the ones worth reading, and calls the scrape tool on each. Search bills 1 credit per query and a scrape bills 1 credit per page on the http or lightpanda renderer.
Wiring the tool into a Mastra agent
Register both tools on the agent's tools map and write an instruction that tells the model when to reach for them: search when it lacks sources, scrape when it has a specific URL. Mastra handles the tool-call loop; your tools just return clean markdown, and the typed output schema keeps each result well-formed on the way back into the model context.
Structured JSON output for downstream steps
When a downstream workflow step needs fields rather than prose, switch the scrape call to formats: ["json"] with a jsonSchema. fastCRW runs an LLM extraction pass and returns structured data that maps onto a Mastra/Zod output schema. Note the cost: any request with formats: ["json"] bills 5 credits, and LLM extraction supports OpenAI and Anthropic providers only — plan for that if you standardize on another model.
One binary behind the whole stack
Mastra is deliberately infra-light, so the worst thing you can bolt onto it is a heavy cloud dependency you cannot run yourself. fastCRW's engine is the opposite of heavy.
Single ~8 MB AGPL-3.0 binary, 1 container
fastCRW is a single statically-linked Rust binary distributed as a roughly 8 MB Docker image running in 1 container (plus an optional sidecar). These are structural facts from the repo README, not benchmark claims. The default Docker Compose ships the lightweight lightpanda renderer; chrome is opt-in.
Self-host for $0 vs managed cloud
The engine is AGPL-3.0, so self-hosting it costs nothing beyond your own server — you can run the same engine your managed calls would hit, on a small VPS, and pay zero per-credit cost. For teams that would rather not run anything, the managed cloud at fastcrw.com meters the same operations at the credit costs above. The point for a Mastra app is that the choice is reversible: a config value, not a fork.
Footprint vs a multi-container cloud stack
For comparison, Firecrawl's self-host path is a multi-service stack reported in its own materials at roughly 2–3 GB across about 5 containers. That is the difference between "self-host is one docker run next to your Mastra service" and "self-host is a platform-team project." More on the single-binary tradeoff in our single-binary infrastructure write-up.
Performance honesty
The reason to put a number on this at all is that a web tool sits inline in the agent loop, so its latency is the user's latency.
Median latency beats Firecrawl
On the canonical three-way scrape benchmark — Firecrawl's own public 1,000-URL dataset, run via diagnose_3way.py on 2026-05-08 — fastCRW's p50 scrape latency was 1914 ms, which beats Firecrawl's 2305 ms and is effectively tied with Crawl4AI (1916 ms, two milliseconds apart). On accuracy, fastCRW posted the highest truth-recall of the three tools tested: 63.74% of 819 labeled URLs, versus Crawl4AI 59.95% and Firecrawl 56.04%, with 91.8% scrape-success of reachable URLs and 0 thrown errors across 3,000 requests. Higher recall on the first fetch is what keeps a Mastra agent from looping back to re-fetch.
The p90 in fast mode and timeout strategy
In fast mode, fastCRW's p90 is 4348 ms — the lowest of the three (Crawl4AI 4754 ms, Firecrawl 6937 ms). For a Mastra tool, that means you can set the AbortController timeout confidently from the fast-mode p90: let the agent fall back to a cached result or a re-plan on a timed-out edge instead of blocking, and reserve the chrome renderer for pages that actually need it. Verify the full split yourself at /benchmarks before quoting any figure internally.
Limitations to plan for
Two gaps will shape how you architect the Mastra side.
Stateless requests
fastCRW is stateless per request — there is no server-side session or cookie jar carried between calls. That is fine for Mastra, which already owns conversation state and memory: keep any cross-call context in the agent's state, not in the scraper. Just do not expect a login established in one scrape to persist into the next.
No /v1/agent autonomous endpoint
fastCRW has no /v1/agent (Spark-style) autonomous endpoint, no managed /v1/deep-research, and no multi-URL batch /v1/extract. The agentic loop lives in Mastra, which is exactly where a TypeScript team wants it. For many pages, iterate /v1/scrape concurrently or kick off a /v1/crawl job rather than reaching for a batch endpoint that does not exist. And there is no screenshot format — a request for formats: ["screenshot"] returns HTTP 422.
Where Firecrawl genuinely wins
An honest tutorial names the cases where you should not switch:
- Cloud-only specialties. Firecrawl's heavy anti-bot fire-engine paths and its agentic/research endpoints are real strengths with no fastCRW equivalent. If your Mastra agent depends on those, use Firecrawl.
- Ecosystem gravity. Firecrawl is the default name with more tutorials and examples. fastCRW wins on substitution, footprint, and the self-host floor — not on mindshare.
- Non-fast-mode rendering. If you need to force the chrome renderer on every page rather than use fast-mode auto-selection, plan around the higher tail latency that produces.
Sources
- fastCRW fact sheet and benchmark of record: github.com/us/crw (
crw-opencore/README.md) ·bench/server-runs/RESULT_3WAY_1000_FULL.md(diagnose_3way.py, 2026-05-08) - Pricing and credits: fastcrw.com/pricing (launch pricing verified 2026-05-18)
- Mastra docs: mastra.ai/docs
Related: Node.js web scraping quickstart · Firecrawl SDK base-URL swap · Single-binary infrastructure
