Date: 2026-05-11
Owner: content/growth
Re-verify within 48h of any page citing this doc.
Sources: docs.firecrawl.dev/sdks/rust and github.com/firecrawl/firecrawl/blob/main/SELF_HOST.md (Firecrawl repo on main as of 2026-05-11 — claims dependent on the exact Firecrawl self-host stack are stated as "as of 2026-05-11" and must be re-verified before any page citing this matrix ships); firecrawl.dev/pricing; fastCRW crates/crw-server/src/routes/, crates/crw-search/src/, Cargo.toml.
This is a capability matrix, not an API-shape compatibility matrix (which the parent plan's COMPATIBILITY.md already provides for Tavily). Capabilities here = what each product can actually do, not just whether endpoint names match.
Honest framing: Firecrawl is a feature-richer cloud-first product with an OSS self-host story that has documented gaps. fastCRW is a single-binary Rust-native alternative with narrower scope but better self-host ergonomics and a Tavily-style search API on top. These products overlap on
/scrape,/crawl,/map,/search; they diverge on LLM extraction, deep research, anti-bot depth, and deployment surface. We do NOT claim drop-in equivalence — claim is "Rust-native alternative for the overlap surface."
Supported compat target — Firecrawl v2 only (as of 2026-07-04): Firecrawl drop-in compatibility is served under the dedicated
/firecrawl/*namespace and targets Firecrawl's v2 API/SDK./firecrawl/v2/*is verified end-to-end forscrape,search,extract,map,crawl, andbatch. How a Firecrawl SDK reaches it depends on the language: the JS/TS SDK (@mendable/firecrawl-js) concatenatesapiUrl+ path, soapiUrl: "…/firecrawl"lands on/firecrawl/v2/*(verified via server access logs); the Python SDK (firecrawl-py) resolves endpoint paths against the host root viaurljoin, dropping a/firecrawlsuffix — so it lands on the equivalent root/v2/*(the same handlers). Point Python clients at the bare host. The legacy v1 Firecrawl SDK is not a supported drop-in: several v1 responses (search,map, crawl-status,extract) use fastCRW's own response shapes and don't deserialize under the strict v1 SDK models —scrapeis the only fully v1-SDK-compatible route. fastCRW's own native API remains/v1/*at the root (what the public docs center on); root/v2/*is a deprecated alias of/firecrawl/v2/*, kept for backward-compat.
| Capability | Firecrawl Cloud | Firecrawl self-host (OSS) | fastCRW |
|---|---|---|---|
/v1/scrape (single URL → markdown/html) |
✅ | ✅ (no Fire-engine) | ✅ |
/v1/crawl (multi-page) |
✅ | ✅ | ✅ |
/v1/map (URL discovery) |
✅ | ✅ | ✅ |
/v1/search (web search → grounded results) |
✅ | ✅ (own search backend) | |
/v1/extract (LLM extraction) |
✅ (standalone route) | .env) |
✅ Standalone POST /v1/extract (async: returns a job id, poll GET /v1/extract/{id}). Accepts urls: [...] (multi-URL, capped by limits.maxExtractUrls). /v1/scrape with formats: ["json"] + jsonSchema also works for a single URL. Needs an LLM key (server-side or per-request). |
/v1/deep-research |
✅ | ❌ (Cloud-only) | ❌ |
/firecrawl/v2/parse (file upload → markdown) |
✅ (PDF/DOCX/XLSX/HTML/…) | ✅ PDF only (multipart file + options; pure-Rust pdf-inspector, no OCR) |
|
/v1/agent (Spark models) |
✅ | ❌ | ❌ |
Source: github.com/firecrawl/firecrawl/blob/main/SELF_HOST.md. Capture commit hash and pin per page citing this row before publish.
parserson/firecrawl/v2/scrape— Firecrawl-compatible. A URL returningapplication/pdfis auto-converted to markdown by default (no field needed, matches Firecrawl). Accepts bothparsers: ["pdf"]andparsers: [{ "type": "pdf", "mode": "auto"|"fast"|"ocr", "maxPages": N }].parsers: []disables conversion (raw bytes).mode— accepted for wire-compatibility. fastCRW has no OCR, somode: "ocr"(and the OCR-fallback half ofauto) degrades to text-layer extraction with apdf_ocr_unsupported/pdf_scannedwarning rather than an error.fast(text-only) is the native behavior.POST /firecrawl/v2/parse— multipartfile+options(JSON string), same response envelope as/firecrawl/v2/scrape. fastCRW supports PDF only (thepdf-inspectorengine); Firecrawl additionally parses DOCX/XLSX/RTF/ODT. Advertised atGET /firecrawl/v2/capabilities→documents.parsers/fileUploadso callers can detect support before sending.
| Firecrawl | fastCRW | |
|---|---|---|
| Header | Authorization: Bearer <key> |
Authorization: Bearer <key> (configurable; default X-API-Key for self-host) |
| Self-host auth bypass | Optional via env var | Optional via [server.auth_required = false] in config.toml |
| Per-key rate limits | Yes (Cloud) | Yes (per-key tier — see crates/crw-server/src/routes/) |
Surface match: Bearer style — yes. Param/header naming — divergent if user customizes.
Reference for full diff: parent plan's
COMPATIBILITY.mdcovers Tavily-shape comparison. For Firecrawl shape comparison: pin in next iteration whencrw-server/tests/has the cross-vendor compat fixtures.
| Field | Firecrawl | fastCRW |
|---|---|---|
Request url |
string | string ✅ |
Request formats |
["markdown", "html", ...] |
["markdown", "html", …] ✅ (extract / llm-extract are accepted aliases for json) |
Request onlyMainContent |
boolean | boolean ✅ |
Request waitFor (ms) |
number | number ✅ |
Response data.markdown |
string | string ✅ |
Response data.metadata |
object (title, description, language, sourceURL...) | object (similar) — field-name divergence on a few keys; needs row-level diff |
Response success |
boolean | boolean ✅ |
Crawl data.completed polling |
required | required ✅ |
| Error envelope | { success: false, error: "..." } |
similar; divergence on error code naming — needs row-level diff |
Action item for next iteration of this doc: add concrete field-by-field diff for metadata and error envelope before any page claims "drop-in" or "API-compatible." Today the page copy says "Rust-native alternative for the overlap surface" — defensible without exhaustive shape match.
| Firecrawl | fastCRW | |
|---|---|---|
| Official Rust SDK | ✅ firecrawl crate on crates.io |
N/A (no SDK; HTTP API only — reqwest example in docs) |
| Self-host constructor | Client::new_selfhosted(api_url, api_key) per docs.firecrawl.dev/sdks/rust (verify in v1 — v2 split documented; constructor naming differs across doc versions) |
N/A |
| Crate version pin (lock before any page cites) | TODO — capture exact crate version + verify constructor in that version + commit a CI demo before T8 spoke ships Path 1 copy. If unverifiable, T8 ships Path-2-only. | N/A |
Plan iter-3 critical: the Client::new_selfhosted signature is documented but the v1/firecrawl/v2 split means the Rust SDK lags v2 features. Before the T8 spoke claims "official Rust SDK works against self-hosted Firecrawl," a CI demo must succeed against the locked crate version. If CI infra isn't stood up (Firecrawl Docker stack: Postgres + Redis + workers), T8 collapses Path 1 to "official Rust SDK exists; CI demo TODO" pointer and ships Path 2 (fastCRW Rust-native alternative) as primary intent.
| Firecrawl Cloud | Firecrawl self-host | fastCRW | |
|---|---|---|---|
| Schema-based extraction (single URL) | ✅ via /v1/extract |
.env) |
✅ via POST /v1/extract, or via /v1/scrape with formats: ["json"] + top-level jsonSchema (Firecrawl-compatible alias: extract.schema; LLM key configured in [extraction.llm] or passed per request) |
Multi-URL /extract (one call → many URLs) |
✅ | ✅ via POST /v1/extract with urls: [...] (capped by limits.maxExtractUrls, default 50) |
|
| Provider support | OpenAI, Anthropic, etc. | Same (manual config) | OpenAI, Anthropic, configurable via [extraction.llm] |
| Pricing | Per call + LLM token cost | Self-paid LLM tokens only | Self-paid LLM tokens only (self-host); cloud per-call pricing on managed plans |
Shape note: fastCRW's /v1/extract is async — it returns a job id you poll on GET /v1/extract/{id}, and it accepts a urls array. The per-request URL cap is advertised as limits.maxExtractUrls on GET /v1/capabilities (default 50). Single-URL extraction also works inline via /v1/scrape formats: ["json"] with a top-level jsonSchema (or the extract.schema alias for closer Firecrawl parity). Per-field basis attribution is supported: pass basis: true to get, for each top-level scalar field, an evidence object with its source URL, a hash of the exact text the model saw, a verbatim excerpt, a confidence, and an honest status (a field that cannot be grounded is marked unverified/unsupported, never fabricated). perFieldAttribution on GET /v1/capabilities reports whether this build ships it.
| Firecrawl Cloud | Firecrawl self-host | fastCRW | |
|---|---|---|---|
| Multi-step web research | ✅ (Spark 1 backend) | ❌ (Cloud-only feature) | ❌ |
Honest divergence: Cloud-only Firecrawl feature. fastCRW does not match.
| Firecrawl | fastCRW | |
|---|---|---|
| MCP server bundled | ✅ (firecrawl-mcp-server) |
✅ (built-in crw-mcp crate; crw_scrape, crw_crawl, crw_check_crawl_status, crw_map, crw_search, crw_parse_file tools) |
Surface match: both products ship MCP. Tool names differ (Firecrawl uses firecrawl_*, fastCRW uses crw_*); semantic mapping is straightforward.
Structured output: crw_search additionally emits MCP-2025-06-18 structuredContent shaped to whichever fastCRW /v1/search body served the call — data.results from a self-hosted engine, results directly in data from the hosted API — and not Firecrawl's data.web shape. It mirrors the body fastCRW clients already consume, so this is not a Firecrawl-shape parity claim. An outputSchema is advertised by the surfaces that produce the body themselves (embedded stdio and the engine's own HTTP /mcp), but not by the stdio proxy, where the body comes from a remote the MCP server does not author. The legacy text content block is retained for lenient clients.
| Firecrawl Cloud | Firecrawl self-host | fastCRW | |
|---|---|---|---|
| Fire-engine (Cloud-only proprietary) | ✅ | ❌ | ❌ |
| Browser fallback | ✅ (Playwright/Puppeteer) | ✅ (manual config) | crates/crw-search/) |
| Rotating IP / proxy | ✅ Cloud | ❌ (BYO proxy) | ❌ (BYO proxy) |
Honest divergence: Firecrawl Cloud has the best anti-bot story; self-host loses this; fastCRW is on par with Firecrawl self-host on this dimension. For high-anti-bot scenarios (cloudflare-protected, JS-heavy SPAs without API), Firecrawl Cloud is still the strongest choice.
| Firecrawl self-host | fastCRW | |
|---|---|---|
| Stack | Docker Compose: API + workers + Postgres + Redis | Single Rust binary (or docker compose up with bundled search backend sidecar) |
| Memory baseline | ~1-2GB (full stack) | ~14 MB idle (binary); +search backend container if used |
| Cold start | ~5-15s (full stack warmup) | ~106ms (process start to first successful /health, binary) |
| Languages | TypeScript (workers), some Rust (/parse Apr 2026) |
Rust |
fastCRW wedge: dramatically simpler deployment surface. Single binary vs multi-service stack. This is the primary "Rust-native, self-host friendly" claim for the T8 spoke.
| Firecrawl | fastCRW | |
|---|---|---|
| License | AGPL-3.0 | AGPL-3.0 |
| Self-host commercial use | Yes, with AGPL §13 obligations | Yes, same |
Same license. Counsel-reviewed §13 explainer is deferred per parent plan; pages cite neutral notice + link to license.
| Plan | Firecrawl Cloud | fastCRW Cloud |
|---|---|---|
| Free | 1k credits/mo | (current pricing — see /pricing) |
| Hobby | $16 / 5k credits | — |
| Standard | $83 / 100k | $69/mo (per src/lib/plans-client.ts:67) |
| Growth | $333 / 500k | — |
| Scale | $599 / 1M | — |
Source: firecrawl.dev/pricing (verify within 48h before any page ships these numbers).
- Firecrawl: Lockdown Mode (Apr 30), Rust-based
/parseengine (Apr 28), Spark 1 models on/agent, multiple status incidents Mar 21/24/31 + Apr 19-30 (status.firecrawl.dev/incidents), Series A $14.5M (Aug 2025). - fastCRW:
/v1/searchon our own search backend (Q2 2026), bundled Docker sidecar, Tavily-cluster pages shipped 2026-05-09.
- T8 spoke and T9 deep refresh may cite this doc by URL.
- Any "compatibility" or "drop-in" copy must reference a specific row that says ✅ in both columns.
- Divergence rows must be acknowledged in page copy with the same word ("not implemented," "not supported," etc.).
- Re-verify-within-48h rule applies to: pricing, recent moves, SDK constructor, SELF_HOST.md commit hash, and Apify announcement (separate doc).
- Latency claims (need own benchmark; cite parent plan Tavily benchmark or wait for Firecrawl-specific benchmark).
- Anti-bot success-rate claims (no benchmark).
- LLM extraction quality claims (the feature ships, but no benchmark backs a quality comparison).
- Drop-in API equivalence claims (request/response shape diff is incomplete in §3).