By the fastCRW team · Credit costs and capabilities verified 2026-05-18 against the canonical fact sheet · Verify independently before building on them.
Website to JSON extraction, conceptually
Website to JSON extraction means pulling specific, typed fields — a price, a title, a list of specs — out of a page and into a structured record your code can use directly. It sits one level above plain scraping: instead of getting the whole page as Markdown and then writing parsing logic, you declare the shape you want and let the extractor fill it. This guide shows the exact 10-line happy path with fastCRW, what each request costs in credits, which LLM providers run the extraction, and the one limit most "extract anything" pitches gloss over: there is no multi-URL batch endpoint.
Why JSON beats Markdown when you need specific fields
Markdown is the right output when you want the whole page as clean context for a retrieval system or a summarizer. But when you need three fields — say title, price, and inStock — Markdown forces you to re-parse prose every time the page layout shifts. JSON extraction collapses that into one step: you get { "title": "...", "price": 49.0, "inStock": true } back, already typed, ready to validate and store. If your downstream consumer is a database row, an API response, or a typed struct, JSON is the format that survives the trip.
Schema-guided extraction vs brittle CSS selectors
The traditional approach is CSS or XPath selectors: document.querySelector(".price"). Selectors are precise until the site ships a redesign, renames a class, or A/B-tests a layout — then every selector silently returns null and your pipeline fills with empty rows. Schema-guided extraction describes what you want ("the product's sale price as a number") rather than where it lives in the DOM, so it tolerates markup changes a selector cannot. The trade is determinism for resilience: an LLM filling a schema is more robust to layout drift but introduces the usual LLM caveats — occasional misreads on ambiguous pages, which is why validation (covered below) is not optional.
Where the LLM fits: filling a schema from page content
Under the hood, fastCRW first renders and cleans the page to Markdown, then hands that content plus your jsonSchema to an LLM that returns a JSON object conforming to the schema. Extraction quality is therefore downstream of extraction accuracy: if the underlying scrape misses the main content, the schema gets filled from noise. That is why we lead with the measured number — fastCRW posted the highest truth-recall of the three tools tested, 63.74% of 819 labeled URLs (diagnose_3way.py, Firecrawl's public dataset, 2026-05-08), ahead of Crawl4AI (59.95%) and Firecrawl (56.04%). Cleaner input means the schema is filled from the right text.
Website to JSON in 10 lines
The whole job is three moving parts: a schema, a /v1/scrape call with the json output format, and a target URL.
Define a jsonSchema for the fields you want
Describe the record you want as a JSON Schema. Keep it small — fewer, well-named fields extract more reliably than a sprawling schema with vague descriptions:
title— string, the product nameprice— number, the current price in the listed currencyinStock— boolean, whether the item is purchasable now
Call /v1/scrape with the json output format
Send one POST to /v1/scrape with formats: ["json"] and your schema. A curl version of the request:
curl -X POST https://api.fastcrw.com/v1/scrape -H "Authorization: Bearer $CRW_API_KEY" -H "Content-Type: application/json" -d '{"url":"https://example.com/product/42","formats":["json"],"jsonSchema":{"type":"object","properties":{"title":{"type":"string"},"price":{"type":"number"},"inStock":{"type":"boolean"}},"required":["title","price"]}}'
The response carries your typed object under the JSON output field. That is the entire path from URL to structured record — no separate parsing service, no selector maintenance.
The same request via the Firecrawl-compatible SDK (base-URL swap)
fastCRW speaks a Firecrawl-compatible REST API, so existing Firecrawl SDK code works after a base-URL swap — point the client's api_url at your fastCRW endpoint and keep the rest. In Python with the crw SDK, CrwClient() runs a self-contained local engine, so the same jsonSchema you used in curl works from a script without standing up a server. One schema, one call, both languages. For the full schema-design reference, see structured extraction with JSON Schema.
What it costs and which providers run the extraction
What JSON extraction costs per request
Any request that includes formats: ["json"] — equivalently, anything that triggers LLM extraction — costs the 1-credit scrape plus the LLM token cost, billed as usage-metered LLM credits. That is more than a plain scrape (a flat 1 credit on any renderer) because you are paying for an LLM pass on top of the fetch and clean; how much more scales with page size and token usage, not a fixed multiple. Budget accordingly: a thousand product pages extracted to JSON is ~1,000 scrape credits plus the per-page LLM token cost, versus ~1,000 credits flat if you only needed Markdown. Live pricing per plan is on the pricing page rather than hard-coded here.
LLM extraction runs on fastCRW's managed LLM
State this plainly: fastCRW's jsonSchema extraction runs on fastCRW's managed LLM. There is no key, provider, or model to configure and no way to point it at your own model, and the path is available on paid plans only (the Free plan returns HTTP 402). The managed /v1/search answer mode runs on the same managed LLM. Knowing that up front is the kind of honesty the vague "extract anything" marketing skips.
/v1/extract is a managed single-URL convenience wrapper
On the managed cloud you will also see /v1/extract. It is a convenience wrapper over /v1/scrape with formats: ["json"] — same cost (the 1-credit scrape plus the LLM token cost), same engine, slightly different ergonomics — and it is single-URL. Self-hosters skip it entirely and call /v1/scrape + jsonSchema directly. There is no behavioral magic in /v1/extract you cannot reproduce with a scrape call; it exists for parity with the Firecrawl surface. The deep-dive lives at the extract endpoint guide.
Extracting from many URLs
There is no multi-URL batch extract: iterate /v1/scrape concurrently
Here is the limit to plan around: fastCRW has no batched multi-URL extract endpoint. There is no /v1/batch/scrape, and /v1/extract is single-URL. To extract from a list of URLs, you iterate /v1/scrape yourself, ideally with bounded concurrency (a worker pool of, say, 5–10 in-flight requests) so you do not overwhelm the target site or your own rate limits. This is more code than a single batch call, but it is also fully under your control — retries, backoff, and per-URL error handling are yours to tune.
Or crawl first, then extract per page
When the URLs are not known ahead of time — you want "every product page on this store" — start with /v1/crawl (async BFS, returns a job ID, with a maxDepth cap of 10 and maxPages cap of 1000), collect the discovered pages, then run a JSON extraction per page. Crawl is billed 1 credit per page, and each JSON extraction on top is the 1-credit scrape plus the LLM token cost, so price the two stages separately. For the crawl-and-extract pattern end to end, see list crawling for structured data.
Pagination and listing pages
Listing pages (search results, category indexes) often hold many records on one URL. Two strategies: extract an array directly from the listing page with a schema whose top level is an array of objects, or extract the per-item links from the listing and then scrape each detail page individually. The array-on-one-page approach is cheaper (one extraction — a 1-credit scrape plus its LLM token cost — per listing page) but only as complete as what the listing renders; the per-detail-page approach costs more but captures fields that only appear on the item page. Pick based on which fields you actually need.
Validating and storing the JSON
Schema validation and handling missing fields
An LLM filling a schema can still return a field as null, omit an optional property, or coerce a type loosely. Re-validate the response against your jsonSchema in your own code (with Zod, Pydantic, or a JSON Schema validator) before trusting it. Decide explicitly what a missing required field means: drop the record, retry once, or flag it for review. Treat extraction output as untrusted input that happens to be well-shaped, not as guaranteed-correct data.
Deduplication before you persist
When you extract across many URLs — especially after a crawl — you will hit the same logical record via different URLs (canonical vs. tracking-parameter variants, paginated duplicates). Deduplicate on a stable business key (a product SKU, a canonical URL, a content hash) before writing to your store, so a re-run updates rather than duplicates. This matters most for recurring extraction jobs that refresh data on a schedule. For the broader ingestion pattern that combines crawl, scrape, and extract into one pipeline, see converting a website to LLM-ready data.
Self-host the same engine for $0
The extraction engine is the same single AGPL-3.0 Rust binary whether you call the managed cloud or run it yourself. Self-hosting costs nothing in license or credits — you pay only for your own server — and because the API is Firecrawl-compatible, the exact jsonSchema request above works against your local instance after a base-URL swap. If extraction volume is high or the data is sensitive enough that it should never leave your infrastructure, self-host; if you want a hands-off path, use the credits. Either way the schema and the code are identical.
Sources
- fastCRW canonical fact sheet — credit costs, API surface and
formats: ["json"], provider and batch-extract limits. Internal to the fastCRW team. - Scrape benchmark of record:
diagnose_3way.pyon Firecrawl's public labeled dataset, 819 labeled URLs, 2026-05-08 (truth-recall 63.74%). - Open-core endpoint reference: github.com/us/crw · managed cloud: fastcrw.com
Related: Structured extraction with JSON Schema · The /v1/extract endpoint deep dive · List crawling for structured data · Convert a website to LLM-ready data
