- Discovers pages via sitemap and recursive link traversal
- Supports path filtering, depth limits, and subdomain/external link control
- Returns results via polling, WebSocket, or webhook
Try it in the Playground
Test crawling in the interactive playground — no code required.
Installation
Basic usage
Submit a crawl job by callingPOST /v2/crawl with a starting URL. The endpoint returns a job ID that you use to poll for results.
Each page crawled consumes 1 credit. The default crawl
limit is 10,000 pages. Before starting, the crawl endpoint checks that your remaining credits can cover the limit — if not, it returns a 402 (Payment Required) error. Set a lower limit to match your intended crawl size (e.g. limit: 100) to avoid this. Additional credits apply for certain options: JSON mode costs 4 additional credits per page, and PDF parsing costs 1 credit per PDF page.Scrape options
All options from the Scrape endpoint are available in crawl viascrapeOptions (JS) / scrape_options (Python). These apply to every page the crawler scrapes, including formats, proxy, caching, actions, location, and tags.
Checking crawl status
Use the job ID to poll for the crawl status and retrieve results.Job results are available via the API for 24 hours after completion. After this period, you can still view your crawl history and results in the activity logs.
Pages in the crawl results
data array are pages that Firecrawl successfully scraped, even if the target site returned an HTTP error like 404. The metadata.statusCode field shows the HTTP status code from the target site. To retrieve pages that Firecrawl itself failed to scrape (e.g. network errors, timeouts, or robots.txt blocks), use the dedicated Get Crawl Errors endpoint (GET /crawl/{id}/errors).Response handling
The response varies based on the crawl’s status. For incomplete or large responses exceeding 10MB, anext URL parameter is provided. You must request this URL to retrieve the next 10MB of data. If the next parameter is absent, it indicates the end of the crawl data.
The
skip and next parameters are only relevant when hitting the API directly.
If you’re using the SDK, pagination is handled automatically and all
results are returned at once.SDK methods
There are two ways to use crawl with the SDK.Crawl and wait
Thecrawl method waits for the crawl to complete and returns the full response. It handles pagination automatically. This is recommended for most use cases.
Start and check later
ThestartCrawl / start_crawl method returns immediately with a crawl ID. You then poll for status manually. This is useful for long-running crawls or custom polling logic.
Real-time results with WebSocket
The watcher method provides real-time updates as pages are crawled. Start a crawl, then subscribe to events for immediate data processing.Webhooks
You can configure webhooks to receive real-time notifications as your crawl progresses. This allows you to process pages as they are scraped instead of waiting for the entire crawl to complete.cURL
Event types
Payload
Verifying webhook signatures
Every webhook request from Firecrawl includes anX-Firecrawl-Signature header containing an HMAC-SHA256 signature. Always verify this signature to ensure the webhook is authentic and has not been tampered with.
- Get your webhook secret from the Advanced tab of your account settings
- Extract the signature from the
X-Firecrawl-Signatureheader - Compute HMAC-SHA256 of the raw request body using your secret
- Compare with the signature header using a timing-safe function
Execution and result accounting
A crawl that finishes is not the same as a crawl that reached every page. This section describes what the crawl endpoints currently report about a run — the counters, the paging contract, the failure records, and the scope limits — so you can judge for yourself whether a run is complete enough to act on. None of these records is a guarantee of completeness.Reading the status counters
Every response from Get Crawl Status (GET /v2/crawl/{id}) carries the counters that describe the run:
The
data array holds only pages Firecrawl successfully scraped. Pages that were attempted but never produced a result are not in data — read them from Get Crawl Errors, below.
Paging through results
Responses are capped at 10MB. When a response is truncated,next carries the URL for the following page of results.
next is not purely a “more data remains” signal: it is also emitted whenever status is not completed, so a terminal failed or cancelled crawl can return a next URL even though no further results exist. Do not use the absence of next as your loop’s exit condition — on a failed or cancelled crawl it never disappears.
The terminal condition is the status field. To read a run to the end:
- Poll
GET /v2/crawl/{id}untilstatusis one ofcompleted,failed, orcancelled. - While
nextis present and the last page returned a non-emptydataarray, follownextto collect the remaining results. - Stop when
nextis absent, or when a page returns no new documents.
Failed and blocked pages
Get Crawl Errors (GET /v2/crawl/{id}/errors) records pages that did not make it into data. It returns two arrays:
errors— errored scrape jobs, each withid,url,error(the error message), and atimestampof the failure. These are pages Firecrawl itself failed to scrape: network errors, timeouts, and similar. Links to an external site’s homepage that were intentionally skipped are reported here with an error code ofEXTERNAL_LINK.robotsBlocked— URLs that were attempted but blocked by the site’s robots.txt.
This list is not guaranteed to be a complete enumeration of every failure: some internal failure classes are currently filtered out of
errors before the response is built. Treat it as the record of failures Firecrawl reports, not as a proof that nothing else went wrong. The error code referenced above (EXTERNAL_LINK) is returned on error objects today but is not yet part of the published GET /crawl/{id}/errors schema; it is pending an API reference update.data with the site’s status code in metadata.statusCode.
What the crawler is scoped to reach
Coverage is bounded by the scope parameters you set, all documented in the configuration reference and the Crawl endpoint reference:- Children only by default. Crawl ignores sublinks that are not children of the URL you provide. Use
crawlEntireDomainfor sibling and parent paths,allowSubdomainsfor subdomains, andallowExternalLinksto follow links off the domain. includePaths/excludePathsmatch the URL pathname, as regex patterns — not the full URL, and not query parameters. SetregexOnFullURL: trueto match against the full URL including query strings instead. The starting URL is also checked againstincludePaths: if it does not match, the crawl may return 0 pages.- Sitemap mode. With the default
sitemap: "include", URLs come from the sitemap plus recursive link discovery."skip"uses HTML links only, so sitemap-only pages such as PDFs or deeply nested pages are missed."only"crawls the sitemap plus the start URL and does not discover links from HTML. maxDiscoveryDepthcaps how many link-discovery hops from the root are followed. Pages at the maximum depth are still scraped, but links found on them are not followed.limitcaps the number of pages, and defaults to10000.ignoreQueryParametersavoids re-scraping the same path with different query parameters.- robots.txt is respected unless
ignoreRobotsTxtis enabled (Enterprise only).
maxConcurrency defaults to your team’s concurrency limit, which is set by your plan — see Rate limits.
When results vary between runs
Crawl results may vary between runs of the same configuration. Pages are scraped concurrently, so the order in which links are discovered depends on network timing and which pages finish loading first. This means different branches of a site may be explored to different extents near the depth boundary, especially at highermaxDiscoveryDepth values.
To make a run more reproducible:
- Set
maxConcurrencyto1. As the configuration reference states,maxConcurrencyis the “maximum concurrent scrapes” — it caps how many requests are in flight at once. That reduces timing-dependent interleaving, but it does not remove run-to-run variation: sitemap discovery is enqueued outside the cap, nested sitemaps are fetched as independent jobs, and the returneddataarray is ordered by finish time rather than discovery order. Settingdelayalso forces concurrency to 1. - Use
sitemap: "only"if the site has a comprehensive sitemap, so the URL set comes from the sitemap rather than from link discovery.
Knowing when a crawl is done
If you are not polling, the webhook events tell you the same thing:crawl.page fires for each page successfully scraped, and crawl.completed (or crawl.failed) fires when the run ends. Job results stay retrievable from the API for 24 hours after completion; after that, view them in the activity logs.
Configuration reference
The full set of parameters available when submitting a crawl job:Important details
- Sitemap discovery: By default, the crawler includes the website’s sitemap to discover URLs (
sitemap: "include"). If you setsitemap: "skip", only pages reachable through HTML links from the root URL are found. Assets like PDFs or deeply nested pages listed in the sitemap but not directly linked from HTML will be missed. For maximum coverage, keep the default setting. - Credit usage: Each page crawled costs 1 credit. JSON mode adds 4 credits per page, and PDF parsing costs 1 credit per PDF page.
- Result expiration: Job results are available via the API for 24 hours after completion. After that, view results in the activity logs.
- Crawl errors: The
dataarray contains pages Firecrawl successfully scraped. Use the Get Crawl Errors endpoint to retrieve pages that failed due to network errors, timeouts, or robots.txt blocks. - External links: With
allowExternalLinks: true, the crawler follows links pointing off your domain and scrapes each linked page once — it does not then crawl the links found on those external pages. Links to an external site’s homepage (a root URL with no path, e.g.https://example.com/) are intentionally skipped to avoid pulling in an entire unrelated site; these appear in Get Crawl Errors with the codeEXTERNAL_LINK. Redirects are followed to their destination — including a link that resolves to its canonical URL (for examplehttp → httpsor thewwwvariant) — so only redirects that land on an external homepage are skipped. - Non-deterministic results: Crawl results may vary between runs of the same configuration, because pages are scraped concurrently and link-discovery order depends on network timing. See Execution and result accounting for what varies and how to make a run more reproducible.
Are you an AI agent that needs a Firecrawl API key? See firecrawl.dev/agent-onboarding/SKILL.md for automated onboarding instructions.

