Firecrawl on n8n: picking the right operation, and what async does to your workflow
n8n-nodes-firecrawl-v2 exposes ten operations. Six of them return web content, and from the parameter list they look interchangeable. They are not: picking the wrong one costs an order of magnitude in either time or credits, and two of them change the shape of your workflow because they run asynchronously.
The README documents every parameter. This is the part that comes before that: which one you want, and what to expect once it runs.
The decision in one table
| You know | You want | Operation |
|---|---|---|
| One exact URL | Its content | Scrape |
| A list of exact URLs | All their content | Batch Scrape |
| A site, not which pages | The URL list, cheaply | Map |
| A site, and you want everything | Content of every page under it | Crawl |
| Neither the site nor the URL | Pages matching a query | Search |
| A page and a schema | Structured fields, not prose | Extract |
The two that get misused are Crawl and Extract.
Crawl is for when you genuinely want a whole site section. It follows links, respects includePaths and excludePaths, and it is the expensive one. If you already know which pages you want, Batch Scrape does the same work without the discovery cost.
Extract is not a scrape with extra steps. It runs an AI pass over the fetched content against a prompt and a schema, and returns fields rather than markdown. When you want "the price, the SKU and the stock status from each of these product pages", Extract is the operation. When you want the page text and you will parse it yourself, Scrape is cheaper and deterministic.
Map first is almost always right
The instinct with a site you do not know is to Crawl it and see what comes back. That is the expensive way to find out you only needed nine pages.
Map returns the URL list without fetching content. It is fast and cheap, and it turns an unbounded job into a bounded one:
Firecrawl: Map (https://example.com/docs)
-> Code: filter the URLs you actually want
-> Firecrawl: Batch Scrape (the filtered list)Three benefits over Crawl. You see the size before you commit. You filter with real code rather than path-pattern guessing. And the result is reproducible: the same URL list yields the same batch, which matters when you diff this week against last week.
Use Crawl when the site is small enough that enumeration is pointless, or when you genuinely want everything under a path and do not care about the count.
Async operations change the workflow shape
Crawl, Extract and Batch Scrape are asynchronous. By default they return a job ID, not results. Your next node receives an ID and nothing else, which looks like the node failed.
Two ways to handle it, and they suit different jobs:
Inline. Set waitForCompletion and the node polls every 2 seconds and returns results directly. Simple, and the workflow reads top to bottom. The cost is that the execution occupies a worker slot for the entire duration, which for a large crawl can be minutes.
Deferred. Take the job ID, and use Get Crawl Status, Get Extract Status or Get Batch Scrape Status later, either on a schedule or after a Wait node. More nodes, but a long job stops holding a worker hostage.
For anything short and interactive, take the inline path. For a nightly crawl of a large site, take the deferred path so a slow job cannot stall the rest of your queue.
Three defaults that surprise people
waitForCompletion is not consistent across operations. Extract defaults to true; Crawl and Batch Scrape default to false. So the same setting produces inline results in one node and a bare job ID in the next. Set it explicitly on every async operation rather than relying on the default, if only so the workflow reads unambiguously six months later.
Format support differs by operation. Scrape supports ten formats, including json, summary, audio and changeTracking. Crawl, Search and Batch Scrape support five basic ones. If your workflow depends on changeTracking for content monitoring, that constrains you to Scrape, and that is worth knowing before you design around Crawl.
onlyMainContent defaults to true. It strips headers, navigation and footers, which is what you want for an article and wrong for a page whose value is in the nav. Turn it off deliberately rather than wondering where half the page went.
One more that is not a default but bites the same way: waitFor is 0 by default. For a server-rendered page that is correct. For a single-page app, the fetch completes before the content exists and you get an empty shell. Raise it and the page appears; the number is per site and you find it by trying.
Self-hosted versus cloud
The node works against both. The credential difference is one field:
| Base URL | |
|---|---|
| Cloud | https://api.firecrawl.dev/v2 |
| Self-hosted | http://your-host:3002/v2 |
The /v2 suffix is required in both cases. Leaving it off is the single most common credential failure, and the error it produces points at authentication rather than at the path, which sends people looking in the wrong place.
Self-hosting is worth it when volume is steady enough that per-request pricing stops making sense, when the pages you fetch must not leave your own infrastructure, or when you want latency measured in your own network rather than across the internet. It costs you an instance to run and patch. Cloud is worth it when volume is bursty or when nobody on the team wants to own another service.
The node does not care which you pick, and switching later is a credential change rather than a workflow change.
Error handling
The node supports n8n's continueOnFail. On failure the item becomes { "error": "message" } and the workflow keeps going.
That is the right default for batch work, where one dead URL out of forty should not kill the run. It is also a trap: an item with an error key still flows downstream and still looks like an item. Filter for it explicitly before anything writes to a database, or you will store rows whose content field contains an error string.
Tối Ưu Hóa Quy Trình Thu Thập Dữ Liệu Web cho Doanh Nghiệp Việt với n8n và Firecrawl
Trong bối cảnh kinh tế số ngày càng phát triển, việc thu thập và phân tích dữ liệu web trở nên vô cùng quan trọng đối với các doanh nghiệp Việt...
The part after the fetch
Getting the content is the first half. The second half is putting it somewhere useful without duplicating it, losing it, or failing silently when a fetch returns nothing.
That second half is what we build and run.
Found this useful? Follow hecigo on Zalo OA for new technical writing, or get in touch if two of your systems need to talk to each other and something is going wrong in between.
Read next: Running a Zalo bot on n8n: what breaks between test mode and production
The node works on the first try in test mode. Then you activate the workflow and nothing arrives. Five failure modes we hit running Zalo Bot...
References
- n8n-nodes-firecrawl-v2 - hecigo
- Firecrawl - Firecrawl
- Error handling | n8n Docs - n8n