Appearance
Node.js Source of Truth
Canonical Firecrawl Node.js source of truth for agents using key endpoints like search, scrape, and interact.
Canonical Firecrawl Node.js source of truth for agents. Aligned with @mendable/firecrawl-js v4.18.2 (firecrawl/apps/js-sdk/firecrawl) and the v2 OpenAPI spec. Method names, parameters, and types match the SDK public API.
Install
bash
npm install @mendable/firecrawl-jsAuthenticate
ts
import Firecrawl from "@mendable/firecrawl-js";
const client = new Firecrawl({
apiKey: process.env.FIRECRAWL_API_KEY,
// apiUrl: "https://api.firecrawl.dev" // optional; falls back to FIRECRAWL_API_URL or cloud default
});When To Use What
search: use when you start with a query and need discovery.scrape: use when you already have a URL and want page content.interact: use when the page needs clicks, forms, or other browser actions after a scrape has created a session. For multi-step interactive flows, preferinteractover scrape-timeactions.support/ask: use when a Firecrawl API call fails or returns unexpected results and you need a diagnosis.support/docs-search: use when you need to look up Firecrawl documentation.
Search
Why use it
Use search to discover relevant pages from a query, then pick URLs to scrape or interact with. You can constrain results to a site with site:, for example site:docs.firecrawl.dev crawl webhooks.
Preferred SDK method
client.search(query, options?) → Promise<SearchData>
Simple Example
ts
const results = await client.search("site:docs.firecrawl.dev webhook retries");Complex Example
ts
const results = await client.search("site:docs.firecrawl.dev crawl webhooks", {
sources: ["web", "news"],
categories: ["research"],
limit: 10,
tbs: "qdr:m",
location: "San Francisco,California,United States",
ignoreInvalidURLs: true,
timeout: 60000,
scrapeOptions: {
formats: [
"markdown",
"links",
{ type: "json", prompt: "Extract title and key endpoints." }
],
onlyMainContent: true,
includeTags: ["main", "article"],
excludeTags: ["nav", "footer"],
waitFor: 1000
}
});Return value
SearchData is an object with optional arrays (each entry is either a lightweight result object or a full Document when scrapeOptions hydrated the hit):
web: web index hitsnews: news hitsimages: image hits
Parameters
query- Type: string
- Use when: you need a search query.
- Notes: use
site:example.comto limit results to a domain.
options(optional; second argument defaults to{})- Type:
Omit<SearchRequest, "query">
- Type:
options.sources- Type: array of source names or typed source objects
- Use when: you want to control which sources are searched.
- Confirmed values:
"web": web index results"news": news results"images": image results{ type: "web" | "news" | "images" }: typed source object form
options.categories- Type: array of category names or typed category objects
- Use when: you want to filter results by category.
- Confirmed values:
"github": GitHub-focused results"research": research and academic results"pdf": PDF-focused results{ type: "github" | "research" | "pdf" }: typed category object form
options.limit- Type: number
- Use when: you want to cap results.
options.tbs- Type: string
- Use when: you need a time-based filter (for example
qdr:d,qdr:w,sbd:1,qdr:m).
options.location- Type: string
- Use when: you want localized results.
options.ignoreInvalidURLs- Type: boolean
- Use when: you want to drop URLs that cannot be scraped by other endpoints.
options.timeout- Type: number
- Use when: you need a request timeout in milliseconds.
options.scrapeOptions- Type:
ScrapeOptions - Use when: you want to scrape each search result (see Scrape parameters for fields). The SDK runs the same validation as for
scrape(for example plain string"json"informatsis rejected).
- Type:
Scrape
Why use it
Use scrape when you already have a URL and want structured content in one or more formats.
Preferred SDK method
client.scrape(url, options?) → Promise<Document>
Simple Example
ts
const doc = await client.scrape("https://docs.firecrawl.dev", {
formats: ["markdown"]
});Complex Example
ts
const doc = await client.scrape("https://example.com/pricing", {
formats: [
"markdown",
"links",
{ type: "json", prompt: "Extract plan names and prices." },
{ type: "screenshot", fullPage: true, quality: 80, viewport: { width: 1280, height: 720 } },
{ type: "changeTracking", modes: ["git-diff"], tag: "pricing" },
{ type: "attributes", selectors: [{ selector: "a", attribute: "href" }] }
],
headers: {
"User-Agent": "FirecrawlDocsBot/1.0"
},
onlyMainContent: true,
waitFor: 1000,
parsers: [{ type: "pdf", mode: "auto", maxPages: 5 }],
actions: [
{ type: "click", selector: "#accept" },
{ type: "wait", milliseconds: 750 },
{ type: "scrape" }
],
location: { country: "US", languages: ["en-US"] },
removeBase64Images: true,
fastMode: true,
blockAds: true,
proxy: "auto",
maxAge: 86400000,
minAge: 1,
storeInCache: true,
profile: { name: "docs-session", saveChanges: true }
});Parameters
url- Type: string
- Use when: you want to scrape a specific page.
options.formats- Type: array of format strings or format objects
- Use when: you want multiple output formats.
- Plain string formats (the
FormatStringunion also includes"json", but the SDK rejects"json"as a plain string, use ajsonobject below):"markdown": markdown content"html": cleaned HTML"rawHtml": raw HTML"links": page links"images": image URLs"screenshot": screenshot output"summary": summary output"changeTracking": change tracking output (for options likemodes, use{ type: "changeTracking", modes: [...] },modesis required on that object in typings)"attributes": attribute extraction (use{ type: "attributes", selectors: [...] }when passing selectors)"branding": branding profile output"audio": audio extraction"video": video extraction
- Object-only format types (at minimum
typeas shown):{ type: "json", prompt?: string, schema?: JSON schema or Zod schema }: at least one ofpromptorschemais required (SDK validation).{ type: "question", question: string }: question-answer style extraction.{ type: "highlights", query: string }: relevant source-text extraction.{ type: "screenshot", fullPage?, quality?, viewport? }: same options as the string form but as an object.{ type: "changeTracking", modes: ("git-diff" | "json")[], schema?, prompt?, tag? }:modesis required.{ type: "attributes", selectors: Array<{ selector, attribute }> }
- Shared object fields where applicable:
schema: JSON schema or Zod schema forjson, or forchangeTrackinginjsonmode (Zod is converted to JSON Schema by the SDK).modes: forchangeTrackingonly:"git-diff"and/or"json".tag: optional change-tracking branch tag.fullPage,quality,viewport: screenshot options.
options.headers- Type: record of string to string
- Use when: you need custom request headers.
options.includeTags- Type: array of strings
- Use when: you want to include only specific HTML tags.
options.excludeTags- Type: array of strings
- Use when: you want to exclude specific HTML tags.
options.onlyMainContent- Type: boolean
- Use when: you want to strip nav, footer, and other boilerplate.
options.timeout- Type: number
- Use when: you need a timeout in milliseconds.
options.waitFor- Type: number
- Use when: you need to wait for the page to render (milliseconds).
options.mobile- Type: boolean
- Use when: you want a mobile viewport.
options.parsers- Type: array of parser names or parser objects
- Use when: you need file parsing controls (for example PDF parsing).
- Confirmed values:
"pdf": enable PDF parsing{ type: "pdf", mode?: "fast" | "auto" | "ocr", maxPages?: number }: PDF parser options
options.actions- Type: array of action objects
- Use when: you need lightweight pre-scrape actions.
- Confirmed action types:
wait:millisecondsorselectorrequiredscreenshot:fullPage,quality,viewportoptionalclick:selectorrequiredwrite:textrequired (click to focus the input first)press:keyrequiredscroll:direction(upordown) required,selectoroptionalscrape: no additional fieldsexecuteJavascript:scriptrequiredpdf:format(A0, A1, A2, A3, A4, A5, A6, Letter, Legal, Tabloid, Ledger),landscape,scaleoptional
options.location- Type: object with
countryandlanguages - Use when: you need geo or language-aware scraping.
- Type: object with
options.skipTlsVerification- Type: boolean
- Use when: you need to skip TLS verification.
options.removeBase64Images- Type: boolean
- Use when: you want to drop base64 images from markdown output.
options.fastMode- Type: boolean
- Use when: you want faster scrapes with reduced fidelity.
options.blockAds- Type: boolean
- Use when: you want ad and cookie popup blocking.
options.proxy- Type: string
- Use when: you need proxy control.
- Confirmed values:
"basic""stealth""enhanced""auto"- custom proxy URL string
options.maxAge- Type: number
- Use when: you want cached data up to a maximum age (milliseconds).
options.minAge- Type: number
- Use when: you want cached data only if it is at least this old (milliseconds).
options.storeInCache- Type: boolean
- Use when: you want Firecrawl to cache the result.
options.profile- Type: object with
nameand optionalsaveChanges - Use when: you want a persistent browser profile shared across scrapes and interactions.
- Type: object with
Interact
Why use it
Use interact for code or natural-language control of the browser session tied to a scrape job (via metadata.scrapeId). The SDK requires at least one of code or prompt. For flows that go beyond quick pre-scrape tweaks, prefer interact over scrape-time actions.
Preferred SDK method
client.interact(jobId, args) → Promise<ScrapeExecuteResponse>
Simple Example
ts
const doc = await client.scrape("https://example.com", { formats: ["markdown"] });
const jobId = doc.metadata?.scrapeId;
if (!jobId) throw new Error("Missing scrapeId from scrape response");
const result = await client.interact(jobId, {
prompt: "Click the pricing tab and summarize the plans."
});Complex Example
ts
const result = await client.interact("<scrapeJobId>", {
code: "console.log(await page.title());",
language: "node",
timeout: 60
});Parameters
jobId- Type: string
- Use when: you have a scrape job ID from
document.metadata.scrapeId.
args.code- Type: string
- Use when: you want to run code in the browser session (for example Playwright
pageusage in thenoderuntime).
args.prompt- Type: string
- Use when: you want the browser agent to follow a natural-language instruction.
At least one of
args.codeorargs.promptmust be non-empty (SDK throws otherwise).args.language- Type: string
- Use when: you need a specific runtime.
- Confirmed values:
"python","node","bash" - Default when omitted:
"node"(set by the SDK on the request body).
args.timeout- Type: number
- Use when: you need an execution timeout in seconds.
Return value (interact)
ScrapeExecuteResponse matches BrowserExecuteResponse. Confirmed fields include:
success: booleanoutput: string (aggregated output when present)stdout: stringresult: string (alias-style field alongside stdout in typings)stderr: stringexitCode: numberkilled: booleanliveViewUrl: stringinteractiveLiveViewUrl: stringerror: string
Stop session
client.stopInteraction(jobId) → Promise<ScrapeBrowserDeleteResponse>
jobId: scrape job id (same id used forinteract).- Response fields in typings include
success,sessionDurationMs,creditsBilled,error.
Ask (Agentic Debugging)
Why use it
Use ask when a Firecrawl API call fails or returns unexpected results. The AI support agent diagnoses the issue, proposes fix parameters, and optionally validates the fix against the live API. Typical latency: 15-30 seconds.
Preferred SDK method
Not yet available in the Node.js SDK. Use fetch directly.
Simple Example
ts
const response = await fetch("https://api.firecrawl.dev/v2/support/ask", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
question: "my scrape returned empty markdown for https://example.com",
}),
});
const result = await response.json();
console.log(result.answer);
console.log(result.fixParameters);Complex Example
ts
const response = await fetch("https://api.firecrawl.dev/v2/support/ask", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
question: "crawl returned 3 pages but I expected 50",
rationale: "user is on their third failed crawl attempt today",
context: { userPlan: "standard", retryCount: 3 },
}),
});
const result = await response.json();Agent retry pattern
ts
import Firecrawl from "@mendable/firecrawl-js";
const client = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const doc = await client.scrape("https://example.com/pricing", {
formats: ["markdown"],
});
if (!doc.markdown || doc.markdown.length < 100) {
const diagResponse = await fetch(
"https://api.firecrawl.dev/v2/support/ask",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
question: `scrape returned only ${doc.markdown?.length ?? 0} chars for https://example.com/pricing`,
}),
}
);
const diagnosis = await diagResponse.json();
if (diagnosis.fixParameters) {
const retryDoc = await client.scrape("https://example.com/pricing", {
formats: ["markdown"],
...diagnosis.fixParameters,
});
}
}Parameters
question- Type: string (required, 1-8000 chars)
- Use when: you need to describe the issue.
rationale- Type: string (1-2000 chars)
- Use when: you are an AI agent calling on behalf of a user.
context- Type: object (free-form)
- Use when: you want to pass metadata into the debugging prompt.
Docs Search
Why use it
Use docs-search to look up Firecrawl documentation.
Simple Example
ts
const response = await fetch(
"https://api.firecrawl.dev/v2/support/docs-search",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
question: "how do I verify webhook signatures?",
}),
}
);
const result = await response.json();
console.log(result.answer);Parameters
question- Type: string (required, 1-8000 chars)
- Use when: you need a docs-grounded answer.
Notes
- Deprecated client aliases:
scrapeExecute→interact;stopInteractiveBrowseranddeleteScrapeBrowser→stopInteraction. - The default
Firecrawlexport is the v2 client; v1 remains underclient.v1. - Zod schemas passed to
formats(forjsonorchangeTracking) are converted to JSON Schema by the SDK. - The package declares Node.js >= 22 in
engines.
Source Of Truth
firecrawl/apps/js-sdk/firecrawl/package.json(name@mendable/firecrawl-js, version)firecrawl/apps/js-sdk/firecrawl/src/index.tsfirecrawl/apps/js-sdk/firecrawl/src/v2/client.tsfirecrawl/apps/js-sdk/firecrawl/src/v2/types.tsfirecrawl/apps/js-sdk/firecrawl/src/v2/utils/validation.tsfirecrawl/apps/js-sdk/firecrawl/src/v2/methods/search.tsfirecrawl/apps/js-sdk/firecrawl/src/v2/methods/scrape.tsfirecrawl-docs/api-reference/v2-openapi.json