Migrate with your coding agent
Copy this prompt into Claude Code, Cursor, or Codex, run from your project’s root:Prompt
Migrate this codebase from the Firecrawl v1 API to v2. v1 stops working on December 10, 2026.
1. Find every Firecrawl v1 call: raw HTTP to https://api.firecrawl.dev/v1/..., old SDK versions (Node @mendable/firecrawl-js or firecrawl 1.x, Python firecrawl-py or firecrawl 1.x and 2.x, Go github.com/mendableai/firecrawl-go, Rust firecrawl crate 1.x, firecrawl-mcp 1.x), and explicit v1 clients on any version (firecrawl.v1, FirecrawlAppV1, V1FirecrawlApp, AsyncV1FirecrawlApp).
2. Upgrade the Firecrawl SDK to the latest version: npm install @mendable/firecrawl-js@latest, pip install -U firecrawl-py, go get github.com/firecrawl/firecrawl/apps/go-sdk@latest (new import path), or firecrawl = "2" in Cargo.toml.
3. Rewrite each call to its v2 equivalent with the mapping below. Keep behavior the same.
4. Run the project's tests and fix what breaks.
5. Calls to /v1/extract, /v1/deep-research, or /v1/llmstxt are not part of this migration. List them and leave them unchanged.
REST mapping:
- Base URL https://api.firecrawl.dev/v1 -> https://api.firecrawl.dev/v2. Every path stays the same except GET /v1/crawl/ongoing -> GET /v2/crawl/active.
- formats "extract" with extract: { prompt, schema }, or "json" with jsonOptions: { prompt, schema } -> { "type": "json", "prompt": ..., "schema": ... } in formats. Read results from data.json, not data.extract. systemPrompt is not accepted: merge it into prompt.
- "screenshot@fullPage" -> { "type": "screenshot", "fullPage": true }.
- "changeTracking" with changeTrackingOptions: { modes, schema, prompt, tag } -> { "type": "changeTracking", "modes": ..., "schema": ..., "prompt": ..., "tag": ... } in formats. Keep "markdown" in formats.
- parsePDF: false -> parsers: []. parsePDF: true is the default: drop it.
- geolocation -> location. __experimental_cache is removed: use maxAge.
- Crawl allowBackwardLinks -> crawlEntireDomain. Crawl and map ignoreSitemap: true -> sitemap: "skip". Map sitemapOnly: true -> sitemap: "only". Map no longer accepts maxDepth or allowBackwardLinks: remove them.
- Crawl maxDepth N has no v2 option. Keep regexOnFullURL false and add includePaths ["^(/+[^/]+){0,N}/*$", "^(/+[^/]+){0,N}/+index\\.(html|php)/*$"] with N written as a number. If the crawl already has includePaths, add excludePaths ["^(/+[^/]+){N+1}"] instead. maxDiscoveryDepth is not a substitute: it counts link hops, not path segments.
- Map links are objects: read link.url instead of a string.
- Search results move from data to data.web (data.news and data.images when requested with sources). The default limit is now 10, was 5: pass limit: 5 where the code relied on the default.
- Batch scrape ignoreInvalidURLs now defaults to true: pass false where the code relied on the request failing.
- With location.country set, proxy now defaults to "auto", was "basic": pass proxy: "basic" to keep it.
- /team/credit-usage and /team/token-usage return camelCase: remaining_credits -> remainingCredits, plan_credits -> planCredits, remaining_tokens -> remainingTokens, plan_tokens -> planTokens, billing_period_start -> billingPeriodStart, billing_period_end -> billingPeriodEnd.
Node SDK: import Firecrawl from "@mendable/firecrawl-js"; const firecrawl = new Firecrawl({ apiKey }). scrapeUrl -> scrape, mapUrl -> map, crawlUrl(url, params, pollInterval) -> crawl(url, { ...options, pollInterval }), asyncCrawlUrl -> startCrawl, checkCrawlStatus -> getCrawlStatus, checkCrawlErrors -> getCrawlErrors, batchScrapeUrls(urls, params) -> batchScrape(urls, { options: params }), asyncBatchScrapeUrls(urls, params) -> startBatchScrape(urls, { options: params }), checkBatchScrapeStatus -> getBatchScrapeStatus, checkBatchScrapeErrors -> getBatchScrapeErrors, crawlUrlAndWatch and batchScrapeUrlsAndWatch -> startCrawl or startBatchScrape, then watcher(id). Search results are under .web. v2 methods return the data directly, with no success field, and throw on failure.
Python SDK: from firecrawl import Firecrawl; firecrawl = Firecrawl(api_key=...), and AsyncFirecrawl for async code. scrape_url -> scrape, map_url -> map, crawl_url -> crawl, async_crawl_url -> start_crawl, check_crawl_status -> get_crawl_status, check_crawl_errors -> get_crawl_errors, batch_scrape_urls -> batch_scrape, async_batch_scrape_urls -> start_batch_scrape, check_batch_scrape_status -> get_batch_scrape_status, check_batch_scrape_errors -> get_batch_scrape_errors, crawl_url_and_watch and batch_scrape_urls_and_watch -> start_crawl or start_batch_scrape, then watcher(id). Pass options as snake_case keyword arguments, not a params dict (crawl_entire_domain=True, sitemap="skip"). Search results are under .web.
Go SDK: import github.com/firecrawl/firecrawl/apps/go-sdk and its option package. NewFirecrawlApp(key, url) -> NewClient(option.WithAPIKey(key)). ScrapeURL -> Scrape(ctx, url, *ScrapeOptions), CrawlURL -> Crawl(ctx, url, *CrawlOptions). Every method takes a context.Context first. CrawlParams.AllowBackwardLinks -> CrawlOptions.CrawlEntireDomain, IgnoreSitemap -> Sitemap.
Rust SDK: FirecrawlApp::new(key) -> Client::new(key). scrape_url -> scrape, with formats as the Format enum. crawl_url -> crawl.
MCP server: run npx -y firecrawl-mcp@latest in the MCP client config.
Latest version of this prompt: https://docs.firecrawl.dev/migrate-to-v2.md
Migrate by hand
Changehttps://api.firecrawl.dev/v1 to https://api.firecrawl.dev/v2, upgrade your SDK to the latest version, then apply these changes:
| v1 | v2 |
|---|---|
GET /v1/crawl/ongoing | GET /v2/crawl/active |
"extract" or "json" format with extract or jsonOptions | { "type": "json", "prompt": "...", "schema": {...} } in formats, read from data.json |
"screenshot@fullPage" | { "type": "screenshot", "fullPage": true } |
"changeTracking" with changeTrackingOptions | { "type": "changeTracking", ... } in formats |
parsePDF: false | parsers: [] |
geolocation | location |
Crawl allowBackwardLinks | crawlEntireDomain |
Crawl and map ignoreSitemap: true | sitemap: "skip" |
Map sitemapOnly: true | sitemap: "only" |
Crawl maxDepth | No v2 option. Use the includePaths patterns in the prompt above. |
Map links as strings | Objects with url, title, and description |
Search results in data | data.web. The default limit is now 10, was 5. |
Batch scrape ignoreInvalidURLs default false | Default true |
remaining_credits, plan_credits, billing_period_start | remainingCredits, planCredits, billingPeriodStart. Token fields change the same way. |
Node FirecrawlApp, scrapeUrl, crawlUrl, mapUrl | Firecrawl, scrape, crawl, map |
Python FirecrawlApp, scrape_url, crawl_url, map_url | Firecrawl, scrape, crawl, map |
Go github.com/mendableai/firecrawl-go | github.com/firecrawl/firecrawl/apps/go-sdk |
Rust firecrawl 1.x | firecrawl 2.x |
firecrawl-mcp 1.x | firecrawl-mcp@latest |
https://api.firecrawl.dev/v2, change any /v1/ URL in an HTTP Request node to /v2/, and replace the community node n8n-nodes-firecrawl with the official @mendable/n8n-nodes-firecrawl.
Questions? Email help@firecrawl.com.
