Choose Your Endpoint
CRW has a native /v1 API for new integrations and a /firecrawl/v2 compatibility layer for Firecrawl migrations. Pick the capability that matches your input and output.
/v1/v1/extractComparison table
New to CRW? Use /v1. Use /firecrawl/v2 when migrating Firecrawl v2 SDK code or when the feature only exists on the compatibility surface, such as POST /firecrawl/v2/batch/scrape or POST /firecrawl/v2/parse.
| Verb | Route | Input | Output | Use when | LLM required? |
|---|---|---|---|---|---|
| scrape | POST /v1/scrape |
A single URL | Markdown, HTML, plain text, links, or raw HTML | You know the exact page URL and want its content | No (yes for summary format) |
| map | POST /v1/map |
A domain or start URL | List of URLs discovered under that origin | You need to enumerate pages before scraping or crawling | No |
| crawl | POST /v1/crawl |
A start URL | Async job — poll GET /v1/crawl/{id} for all pages |
You want every page under a URL scraped in one background job | No (yes if you add summary to scrapeOptions) |
| search | POST /v1/search |
A query string | Ranked web search results, optionally with scraped content | You do not have a URL — you want the web to find relevant pages | No (yes for answer/summarize_results options) |
| extract (single URL) | POST /v1/scrape |
A URL + prompt/schema | data.json — a filled-in object |
You have one page and want structured fields (price, title, date…) | Yes |
| extract (multi-URL) | POST /v1/extract |
URLs + prompt/schema | Async job — poll GET /v1/extract/{id} for a per-URL results array |
You want the same structure extracted across several pages in one job | Yes |
| parse | POST /firecrawl/v2/parse |
A PDF file upload | Markdown (or JSON/summary with schema) from the document | You have a local file, not a URL | No (yes for summary/json formats) |
Two ways to extract. For a single page, extraction is just
POST /v1/scrapewithformats: ["json"]+ apromptand/orjsonSchema. For multiple URLs, the nativePOST /v1/extractruns them as one async job and returns a per-URLresultsarray (each URL keeps its own object; no last-write-wins merge). Both call an LLM.
Decision tree
Do you have a file (PDF) to parse?
└─ Yes ──► Parse POST /firecrawl/v2/parse
Do you know the exact URL(s) of the page(s) you want?
├─ Yes ──► Do you need structured fields (price, date, …)?
│ ├─ Yes ──► One URL? ──► Extract POST /v1/scrape (formats:["json"] + prompt/jsonSchema)
│ │ Many URLs? ──► Extract POST /v1/extract (async, per-URL results)
│ └─ No ──► Scrape POST /v1/scrape
└─ No ──► Are you looking across an entire site?
├─ Yes ──► Do you want every page's content in one job?
│ ├─ Yes ──► Crawl POST /v1/crawl
│ └─ No ──► Map POST /v1/map
└─ No ──► Search POST /v1/search
About extract
Extract reuses the scrape route. The only difference from a plain scrape is that you add two fields to the request body:
{
"url": "https://example.com/product/42",
"formats": ["json"],
"jsonSchema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"price": { "type": "string" }
},
"required": ["title"]
}
}
CRW scrapes the page and then calls an LLM with your schema to produce the data.json
field in the response. Because an LLM call is involved, extraction requires either a
server-side [extraction.llm] configuration (self-hosted) or a per-request llmApiKey.
Multiple URLs: POST /v1/extract
When you want the same structure from several pages, use the native async route instead of calling scrape N times:
{
"urls": ["https://example.com/a", "https://example.com/b"],
"prompt": "extract the product title and price",
"schema": { "type": "object", "properties": { "title": {"type":"string"}, "price": {"type":"string"} } }
}
It returns { "success": true, "id", "status": "processing", "urls": 2 }; poll GET /v1/extract/{id} for
a results array (one { url, status, data, error } per URL, in request order). Capped
by crawler.max_extract_urls (default 50) since each URL triggers an LLM call.
On the hosted service at api.fastcrw.com this is handled automatically.
See Extract for the full parameter reference and provider options.
Quick examples
Scrape one page as markdown:
curl -X POST https://api.fastcrw.com/v1/scrape \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","formats":["markdown"]}'
Discover all URLs on a site:
curl -X POST https://api.fastcrw.com/v1/map \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
Crawl an entire site (start + poll):
# Start
curl -X POST https://api.fastcrw.com/v1/crawl \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
# Poll with the returned job ID
curl https://api.fastcrw.com/v1/crawl/{id} \
-H "Authorization: Bearer YOUR_API_KEY"
Search the web:
curl -X POST https://api.fastcrw.com/v1/search \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"open source web scraping 2025","limit":5}'
Extract structured data:
curl -X POST https://api.fastcrw.com/v1/scrape \
-H "Authorization: Bearer YOUR_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": "string"}
},
"required": ["title"]
}
}'
Parse a PDF:
curl -X POST https://api.fastcrw.com/firecrawl/v2/parse \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@/path/to/document.pdf"