@mendable/firecrawl
Version:
JavaScript SDK for Firecrawl API
1,602 lines (1,594 loc) • 92.8 kB
TypeScript
import * as zt from 'zod';
import { ZodTypeAny } from 'zod';
import { AxiosResponse, AxiosRequestHeaders } from 'axios';
import { EventEmitter } from 'events';
import { TypedEventTarget } from 'typescript-event-target';
type FormatString = "markdown" | "html" | "rawHtml" | "links" | "images" | "screenshot" | "summary" | "changeTracking" | "json" | "attributes" | "branding" | "product" | "menu" | "audio" | "video";
interface Viewport {
width: number;
height: number;
}
interface Format {
type: FormatString;
}
interface JsonFormat extends Format {
type: "json";
prompt?: string;
schema?: Record<string, unknown> | ZodTypeAny;
}
interface ScreenshotFormat {
type: "screenshot";
fullPage?: boolean;
quality?: number;
viewport?: Viewport | {
width: number;
height: number;
};
}
interface ChangeTrackingFormat extends Format {
type: "changeTracking";
modes: ("git-diff" | "json")[];
/**
* Either a JSON Schema object or a Zod schema. Zod schemas are
* auto-converted to JSON Schema by the SDK before being sent — see
* `utils/validation.ts`.
*/
schema?: Record<string, unknown> | ZodTypeAny;
prompt?: string;
tag?: string;
}
interface AttributesFormat extends Format {
type: "attributes";
selectors: Array<{
selector: string;
attribute: string;
}>;
}
interface QuestionFormat {
type: "question";
question: string;
}
interface HighlightsFormat {
type: "highlights";
query: string;
}
/** @deprecated Use QuestionFormat or HighlightsFormat instead. */
interface QueryFormat {
type: "query";
prompt: string;
mode?: "freeform" | "directQuote";
}
type FormatOption = FormatString | Format | JsonFormat | ChangeTrackingFormat | ScreenshotFormat | AttributesFormat | QuestionFormat | HighlightsFormat | QueryFormat;
type ParseFormatString = Exclude<FormatString, "screenshot" | "changeTracking" | "branding" | "audio" | "video">;
interface ParseFormat {
type: ParseFormatString;
}
type ParseFormatOption = ParseFormatString | ParseFormat | JsonFormat | AttributesFormat | QuestionFormat | HighlightsFormat | QueryFormat;
interface LocationConfig$1 {
country?: string;
languages?: string[];
}
interface WaitAction {
type: "wait";
milliseconds?: number;
selector?: string;
}
interface ScreenshotAction {
type: "screenshot";
fullPage?: boolean;
quality?: number;
viewport?: Viewport | {
width: number;
height: number;
};
}
interface ClickAction {
type: "click";
selector: string;
}
interface WriteAction {
type: "write";
text: string;
}
interface PressAction {
type: "press";
key: string;
}
interface ScrollAction {
type: "scroll";
direction: "up" | "down";
selector?: string;
}
interface ScrapeAction {
type: "scrape";
}
interface ExecuteJavascriptAction {
type: "executeJavascript";
script: string;
}
interface PDFAction {
type: "pdf";
format?: "A0" | "A1" | "A2" | "A3" | "A4" | "A5" | "A6" | "Letter" | "Legal" | "Tabloid" | "Ledger";
landscape?: boolean;
scale?: number;
}
type ActionOption = WaitAction | ScreenshotAction | ClickAction | WriteAction | PressAction | ScrollAction | ScrapeAction | ExecuteJavascriptAction | PDFAction;
interface ScrapeOptions {
formats?: FormatOption[];
headers?: Record<string, string>;
includeTags?: string[];
excludeTags?: string[];
onlyMainContent?: boolean;
timeout?: number;
waitFor?: number;
mobile?: boolean;
parsers?: Array<string | {
type: "pdf";
mode?: "fast" | "auto" | "ocr";
maxPages?: number;
}>;
actions?: ActionOption[];
location?: LocationConfig$1;
skipTlsVerification?: boolean;
removeBase64Images?: boolean;
fastMode?: boolean;
useMock?: string;
blockAds?: boolean;
proxy?: "basic" | "stealth" | "enhanced" | "auto" | string;
maxAge?: number;
minAge?: number;
storeInCache?: boolean;
lockdown?: boolean;
redactPII?: boolean | RedactPIIOptions;
threatProtection?: ThreatProtectionOptions;
profile?: {
name: string;
saveChanges?: boolean;
};
integration?: string;
origin?: string;
}
type RedactPIIEntity = "PERSON" | "EMAIL" | "PHONE" | "LOCATION" | "FINANCIAL" | "SECRET";
interface RedactPIIOptions {
/**
* accurate (default): model-only redaction. Best precision, cleanest output.
* aggressive: model + Presidio + spaCy. Higher recall at the cost of precision.
* fast: Presidio only, no model call. Lower F1, ~2x throughput.
*/
mode?: "accurate" | "aggressive" | "fast";
/** Restrict redaction to these entity buckets. Unset means all entities. */
entities?: RedactPIIEntity[];
/**
* tag (default): replace spans with `<KIND>` placeholders.
* mask: replace spans with `*` of equal length.
* remove: drop span characters entirely.
*/
replaceStyle?: "tag" | "mask" | "remove";
}
/**
* Enterprise: per-request field-level override of your team's threat
* protection policy. Requires threat protection to be enabled for your team
* and request overrides to be allowed in the team configuration. Only the
* fields you provide replace the team policy's values.
*/
interface ThreatProtectionOptions {
/** "off" disables scanning for this request; "normal" applies the policy. */
mode?: "off" | "normal";
/** Block verdicts at or above this risk score (integer 0-100). */
riskScoreThreshold?: number;
/** Exact domains or globs like "*.example.com" to always block (max 1000). */
blacklist?: string[];
/** Exact domains or globs to always allow; wins over everything (max 1000). */
whitelist?: string[];
/** Lowercase TLDs without the leading dot, e.g. "zip" (max 1000). */
blockedTlds?: string[];
/** Behavior when scanning is unavailable: "closed" blocks, "open" allows. */
failurePolicy?: "open" | "closed";
}
type ParseFileData = Blob | File | Buffer | Uint8Array | ArrayBuffer | string;
interface ParseFile {
data: ParseFileData;
filename: string;
contentType?: string;
}
type ParseOptions = Omit<ScrapeOptions, "formats" | "waitFor" | "mobile" | "actions" | "location" | "maxAge" | "minAge" | "storeInCache" | "lockdown" | "proxy" | "threatProtection"> & {
formats?: ParseFormatOption[];
proxy?: "basic" | "auto";
};
interface WebhookConfig {
url: string;
headers?: Record<string, string>;
metadata?: Record<string, string>;
events?: Array<"completed" | "failed" | "page" | "started">;
}
type AgentWebhookEvent = "started" | "action" | "completed" | "failed" | "cancelled";
interface AgentWebhookConfig {
url: string;
headers?: Record<string, string>;
metadata?: Record<string, string>;
events?: AgentWebhookEvent[];
}
interface BrandingProfile {
colorScheme?: "light" | "dark";
logo?: string | null;
fonts?: Array<{
family: string;
[key: string]: unknown;
}>;
colors?: {
primary?: string;
secondary?: string;
accent?: string;
background?: string;
textPrimary?: string;
textSecondary?: string;
link?: string;
success?: string;
warning?: string;
error?: string;
[key: string]: string | undefined;
};
typography?: {
fontFamilies?: {
primary?: string;
heading?: string;
code?: string;
[key: string]: string | undefined;
};
fontStacks?: {
primary?: string[];
heading?: string[];
body?: string[];
paragraph?: string[];
[key: string]: string[] | undefined;
};
fontSizes?: {
h1?: string;
h2?: string;
h3?: string;
body?: string;
small?: string;
[key: string]: string | undefined;
};
lineHeights?: {
heading?: number;
body?: number;
[key: string]: number | undefined;
};
fontWeights?: {
light?: number;
regular?: number;
medium?: number;
bold?: number;
[key: string]: number | undefined;
};
};
spacing?: {
baseUnit?: number;
padding?: Record<string, number>;
margins?: Record<string, number>;
gridGutter?: number;
borderRadius?: string;
[key: string]: number | string | Record<string, number> | undefined;
};
components?: {
buttonPrimary?: {
background?: string;
textColor?: string;
borderColor?: string;
borderRadius?: string;
[key: string]: string | undefined;
};
buttonSecondary?: {
background?: string;
textColor?: string;
borderColor?: string;
borderRadius?: string;
[key: string]: string | undefined;
};
input?: {
borderColor?: string;
focusBorderColor?: string;
borderRadius?: string;
[key: string]: string | undefined;
};
[key: string]: unknown;
};
icons?: {
style?: string;
primaryColor?: string;
[key: string]: string | undefined;
};
images?: {
logo?: string | null;
favicon?: string | null;
ogImage?: string | null;
[key: string]: string | null | undefined;
};
animations?: {
transitionDuration?: string;
easing?: string;
[key: string]: string | undefined;
};
layout?: {
grid?: {
columns?: number;
maxWidth?: string;
[key: string]: number | string | undefined;
};
headerHeight?: string;
footerHeight?: string;
[key: string]: number | string | Record<string, number | string | undefined> | undefined;
};
tone?: {
voice?: string;
emojiUsage?: string;
[key: string]: string | undefined;
};
personality?: {
tone: "professional" | "playful" | "modern" | "traditional" | "minimalist" | "bold";
energy: "low" | "medium" | "high";
targetAudience: string;
};
[key: string]: unknown;
}
interface ProductPrice {
amount: number;
currency?: string;
formatted?: string;
}
interface ProductAvailability {
inStock: boolean;
text?: string;
}
interface ProductImage {
url: string;
alt?: string;
}
interface ProductSale {
originalPrice: ProductPrice;
}
interface ProductVariant {
id?: string;
sku?: string;
title?: string;
values?: Record<string, unknown>;
price?: ProductPrice;
sale?: ProductSale;
availability: ProductAvailability;
images?: ProductImage[];
}
interface ProductProfile {
title: string;
brand?: string;
category?: string;
url: string;
description?: string;
variants: ProductVariant[];
}
interface MenuPrice {
amount: number;
currency?: string;
formatted?: string;
}
interface MenuAvailability {
inStock: boolean;
text?: string;
}
interface MenuImage {
url: string;
alt?: string;
}
interface MenuItemIdentifiers {
merchantItemId?: string;
}
interface MenuItem {
id: string;
name: string;
description?: string;
images: MenuImage[];
price?: MenuPrice;
availability: MenuAvailability;
dietary: string[];
calories?: number;
optionGroups: unknown[];
identifiers: MenuItemIdentifiers;
url?: string;
sourceUrl: string;
}
interface MenuSection {
id: string;
name: string;
description?: string;
items: MenuItem[];
}
interface MenuMerchant {
name: string;
type?: string | null;
location?: unknown;
}
interface MenuProfile {
isMenu: boolean;
confidence: number;
merchant: MenuMerchant;
currency?: string | null;
sections: MenuSection[];
sourceUrl: string;
}
interface DocumentMetadata {
title?: string;
description?: string;
url?: string;
language?: string;
keywords?: string | string[];
robots?: string;
ogTitle?: string;
ogDescription?: string;
ogUrl?: string;
ogImage?: string;
ogAudio?: string;
ogDeterminer?: string;
ogLocale?: string;
ogLocaleAlternate?: string[];
ogSiteName?: string;
ogVideo?: string;
favicon?: string;
dcTermsCreated?: string;
dcDateCreated?: string;
dcDate?: string;
dcTermsType?: string;
dcType?: string;
dcTermsAudience?: string;
dcTermsSubject?: string;
dcSubject?: string;
dcDescription?: string;
dcTermsKeywords?: string;
modifiedTime?: string;
publishedTime?: string;
articleTag?: string;
articleSection?: string;
sourceURL?: string;
statusCode?: number;
scrapeId?: string;
numPages?: number;
totalPages?: number;
contentType?: string;
timezone?: string;
proxyUsed?: "basic" | "stealth";
cacheState?: "hit" | "miss";
cachedAt?: string;
creditsUsed?: number;
concurrencyLimited?: boolean;
concurrencyQueueDurationMs?: number;
error?: string;
[key: string]: unknown;
}
interface Document {
markdown?: string;
html?: string;
rawHtml?: string;
json?: unknown;
summary?: string;
metadata?: DocumentMetadata;
links?: string[];
images?: string[];
screenshot?: string;
audio?: string;
video?: string;
attributes?: Array<{
selector: string;
attribute: string;
values: string[];
}>;
actions?: Record<string, unknown>;
answer?: string;
highlights?: string;
warning?: string;
changeTracking?: Record<string, unknown>;
branding?: BrandingProfile;
product?: ProductProfile;
menu?: MenuProfile;
}
interface PaginationConfig {
/** When true (default), automatically follow `next` links and aggregate all documents. */
autoPaginate?: boolean;
/** Maximum number of additional pages to fetch after the first response. */
maxPages?: number;
/** Maximum total number of documents to return across all pages. */
maxResults?: number;
/** Maximum time to spend fetching additional pages (in seconds). */
maxWaitTime?: number;
}
interface SearchResultWeb {
url: string;
title?: string;
description?: string;
category?: string;
}
interface SearchResultNews {
title?: string;
url?: string;
snippet?: string;
date?: string;
imageUrl?: string;
position?: number;
category?: string;
}
interface SearchResultImages {
title?: string;
imageUrl?: string;
imageWidth?: number;
imageHeight?: number;
url?: string;
position?: number;
}
interface SearchData {
web?: Array<SearchResultWeb | Document>;
news?: Array<SearchResultNews | Document>;
images?: Array<SearchResultImages | Document>;
}
interface CategoryOption {
type: "github" | "research" | "pdf";
}
interface SearchRequest {
query: string;
sources?: Array<"web" | "news" | "images" | {
type: "web" | "news" | "images";
}>;
categories?: Array<"github" | "research" | "pdf" | CategoryOption>;
includeDomains?: string[];
excludeDomains?: string[];
limit?: number;
tbs?: string;
location?: string;
ignoreInvalidURLs?: boolean;
timeout?: number;
scrapeOptions?: ScrapeOptions;
/**
* Enterprise search options. Use `["zdr"]` for end-to-end Zero Data
* Retention or `["anon"]` for anonymized search. Must be enabled for
* your team.
*/
enterprise?: Array<"default" | "anon" | "zdr">;
threatProtection?: ThreatProtectionOptions;
integration?: string;
origin?: string;
}
interface CrawlOptions {
prompt?: string | null;
excludePaths?: string[] | null;
includePaths?: string[] | null;
maxDiscoveryDepth?: number | null;
sitemap?: "skip" | "include" | "only";
ignoreQueryParameters?: boolean;
deduplicateSimilarURLs?: boolean;
limit?: number | null;
crawlEntireDomain?: boolean;
allowExternalLinks?: boolean;
allowSubdomains?: boolean;
ignoreRobotsTxt?: boolean;
robotsUserAgent?: string | null;
delay?: number | null;
maxConcurrency?: number | null;
webhook?: string | WebhookConfig | null;
scrapeOptions?: ScrapeOptions | null;
regexOnFullURL?: boolean;
zeroDataRetention?: boolean;
integration?: string;
origin?: string;
}
interface CrawlResponse$1 {
id: string;
url: string;
}
interface CrawlJob {
id: string;
status: "scraping" | "completed" | "failed" | "cancelled";
total: number;
completed: number;
creditsUsed?: number;
expiresAt?: string;
next?: string | null;
data: Document[];
}
interface BatchScrapeOptions {
options?: ScrapeOptions;
webhook?: string | WebhookConfig;
appendToId?: string;
ignoreInvalidURLs?: boolean;
maxConcurrency?: number;
zeroDataRetention?: boolean;
idempotencyKey?: string;
integration?: string;
origin?: string;
}
interface BatchScrapeResponse$1 {
id: string;
url: string;
invalidURLs?: string[];
}
interface BatchScrapeJob {
id: string;
status: "scraping" | "completed" | "failed" | "cancelled";
completed: number;
total: number;
creditsUsed?: number;
expiresAt?: string;
next?: string | null;
data: Document[];
}
interface MapData {
id?: string;
links: SearchResultWeb[];
}
interface MapOptions {
search?: string;
sitemap?: "only" | "include" | "skip";
includeSubdomains?: boolean;
ignoreQueryParameters?: boolean;
limit?: number;
timeout?: number;
integration?: string;
origin?: string;
location?: LocationConfig$1;
threatProtection?: ThreatProtectionOptions;
}
type FeedbackRating = "good" | "partial" | "bad";
type EndpointFeedbackEndpoint = "search" | "scrape" | "parse" | "map";
interface FeedbackValuableSource {
url: string;
reason?: string;
}
interface FeedbackMissingContent {
topic: string;
description?: string;
}
interface SearchFeedbackRequest {
rating: FeedbackRating;
valuableSources?: FeedbackValuableSource[];
missingContent?: FeedbackMissingContent[];
querySuggestions?: string;
integration?: string | null;
origin?: string;
}
interface EndpointFeedbackRequest extends SearchFeedbackRequest {
endpoint: EndpointFeedbackEndpoint;
jobId: string;
issues?: string[];
tags?: string[];
note?: string;
url?: string;
pageNumbers?: number[];
/** Small endpoint-specific metadata object. Must be 8KB or smaller. */
metadata?: Record<string, unknown>;
}
interface FeedbackResponse {
success: true;
feedbackId: string;
creditsRefunded: number;
alreadySubmitted?: boolean;
dailyCapReached?: boolean;
creditsRefundedToday?: number;
dailyRefundCap?: number;
warning?: string;
}
/**
* Schedule for a monitor.
*
* On create/update, provide exactly one of `cron` or `text`:
* - `cron`: a 5-field cron expression (e.g. `"*\u002F30 * * * *"`).
* - `text`: a natural-language schedule (e.g. `"every 30 minutes"`,
* `"hourly"`, `"daily at 9:00"`). Firecrawl normalizes this to a cron
* expression server-side.
*
* On read, the API always returns the normalized `cron` value, so `cron`
* is populated in responses even when the monitor was created with `text`.
*/
interface MonitorSchedule {
cron?: string;
text?: string;
timezone?: string;
}
interface MonitorEmailNotification {
enabled?: boolean;
recipients?: string[];
includeDiffs?: boolean;
}
/**
* Per-recipient opt-in state for monitor email notifications.
*
* External recipients (not members of the team that owns the monitor) must
* confirm their subscription via a one-time email before they receive any
* monitor notifications. Team members are auto-confirmed.
*
* - `pending` → confirmation email sent, no notifications yet
* - `confirmed` → notifications enabled
* - `unsubscribed` → recipient opted out and cannot be re-added without a new
* confirmation flow
*/
interface MonitorEmailRecipientSubscription {
email: string;
status: "pending" | "confirmed" | "unsubscribed";
source: "team" | "opt_in" | "legacy";
confirmationEmailSent?: boolean;
}
interface MonitorNotification {
email?: MonitorEmailNotification;
}
interface MonitorWebhookConfig {
url: string;
headers?: Record<string, string>;
metadata?: Record<string, string>;
events?: string[];
}
interface MonitorScrapeTarget {
id?: string;
type: "scrape";
urls: string[];
scrapeOptions?: ScrapeOptions;
}
interface MonitorCrawlTarget {
id?: string;
type: "crawl";
url: string;
crawlOptions?: CrawlOptions;
scrapeOptions?: ScrapeOptions;
}
interface MonitorSearchTarget {
id?: string;
type: "search";
queries: string[];
searchWindow?: "5m" | "15m" | "1h" | "6h" | "24h" | "7d";
includeDomains?: string[];
excludeDomains?: string[];
maxResults?: number;
}
type MonitorTarget = MonitorScrapeTarget | MonitorCrawlTarget | MonitorSearchTarget;
interface CreateMonitorRequest {
name: string;
schedule: MonitorSchedule;
webhook?: MonitorWebhookConfig;
notification?: MonitorNotification;
targets: MonitorTarget[];
retentionDays?: number;
goal?: string;
judgeEnabled?: boolean;
}
interface UpdateMonitorRequest {
name?: string;
status?: "active" | "paused";
schedule?: MonitorSchedule;
webhook?: MonitorWebhookConfig | null;
notification?: MonitorNotification | null;
targets?: MonitorTarget[];
retentionDays?: number;
goal?: string | null;
judgeEnabled?: boolean;
}
interface MonitorSummary {
totalPages: number;
same: number;
changed: number;
new: number;
removed: number;
error: number;
}
interface Monitor {
id: string;
name: string;
status: "active" | "paused" | "deleted";
schedule: MonitorSchedule;
nextRunAt?: string | null;
lastRunAt?: string | null;
currentCheckId?: string | null;
targets: MonitorTarget[];
webhook?: MonitorWebhookConfig | null;
notification?: MonitorNotification | null;
/**
* Present on create/update/get responses. Reflects the opt-in state of every
* email recipient currently configured on the monitor. Absent when the API
* has not reconciled recipients (e.g. team-default delivery with no
* explicit recipients).
*/
emailRecipientSubscriptions?: MonitorEmailRecipientSubscription[];
retentionDays: number;
estimatedCreditsPerMonth?: number | null;
lastCheckSummary?: MonitorSummary | null;
goal?: string | null;
judgeEnabled?: boolean;
createdAt: string;
updatedAt: string;
}
interface MonitorPageJudgment {
meaningful: boolean;
confidence: "high" | "medium" | "low";
reason: string;
meaningfulChanges: Array<{
type: "added" | "removed" | "changed";
before: string | null;
after: string | null;
reason: string;
}>;
}
interface MonitorScrapeTargetResult {
targetId: string;
type: "scrape";
expectedJobs?: string[];
}
interface MonitorCrawlTargetResult {
targetId: string;
type: "crawl";
crawlId?: string;
}
interface MonitorSearchTargetResult {
targetId: string;
type: "search";
searchCompleted?: boolean;
resultCount?: number;
matches?: number;
summary?: string;
judgeDegraded?: boolean;
degradedReason?: string | null;
searchCredits?: number;
judgeCredits?: number;
resultsJudged?: number;
}
type MonitorTargetResult = MonitorScrapeTargetResult | MonitorCrawlTargetResult | MonitorSearchTargetResult;
interface MonitorCheck {
id: string;
monitorId: string;
status: "queued" | "running" | "completed" | "failed" | "partial" | "skipped_overlap" | "skipped_no_credits";
trigger: "scheduled" | "manual";
scheduledFor?: string | null;
startedAt?: string | null;
finishedAt?: string | null;
estimatedCredits?: number | null;
reservedCredits?: number | null;
actualCredits?: number | null;
billingStatus: "not_applicable" | "reserved" | "confirmed" | "released" | "failed";
summary: MonitorSummary;
targetResults?: MonitorTargetResult[];
notificationStatus?: unknown;
error?: string | null;
createdAt: string;
updatedAt: string;
}
/** Per-field diff for monitors that requested JSON extraction. */
interface MonitorJsonFieldDiff {
[field: string]: {
previous: unknown;
current: unknown;
};
}
/**
* Diff payload returned alongside a monitor page when its scrape produced
* a change. The shape depends on what the monitor's formats asked for:
*
* - markdown-only monitors → `{ text, json }` where `json` is the
* `parseDiff` AST (a `{ files: [...] }` object).
* - JSON-extraction monitors → `{ json }` where `json` is the per-field
* `{ previous, current }` map.
* - Mixed (JSON + git-diff) monitors → both `text` (markdown sidecar)
* and `json` (field-level diff) are present.
*/
interface MonitorPageDiff {
text?: string;
/** Markdown variants: parseDiff AST. JSON variants: per-field diff. */
json?: MonitorJsonFieldDiff | {
files: unknown[];
};
}
/**
* Snapshot of the current JSON extraction at this run. Present on JSON
* and mixed-mode monitors; absent for markdown-only.
*/
interface MonitorPageSnapshot {
json?: Record<string, unknown>;
}
interface MonitorCheckPage {
id: string;
targetId: string;
url: string;
status: "same" | "new" | "changed" | "removed" | "error";
previousScrapeId?: string | null;
currentScrapeId?: string | null;
statusCode?: number | null;
error?: string | null;
metadata?: unknown;
diff?: MonitorPageDiff | null;
snapshot?: MonitorPageSnapshot | null;
judgment?: MonitorPageJudgment | null;
createdAt: string;
}
interface MonitorCheckDetail extends MonitorCheck {
pages: MonitorCheckPage[];
next?: string | null;
}
interface ListMonitorsOptions {
limit?: number;
offset?: number;
}
type ListMonitorChecksOptions = ListMonitorsOptions;
type GetMonitorCheckOptions = PaginationConfig & {
limit?: number;
skip?: number;
status?: MonitorCheckPage["status"];
};
interface ExtractResponse$1 {
success?: boolean;
id?: string;
status?: "processing" | "completed" | "failed" | "cancelled";
data?: unknown;
error?: string;
warning?: string;
warnings?: string[];
replacement?: string;
sources?: Record<string, unknown>;
expiresAt?: string;
creditsUsed?: number;
}
interface AgentResponse {
success: boolean;
id: string;
error?: string;
}
interface AgentStatusResponse {
success: boolean;
status: "processing" | "completed" | "failed";
error?: string;
data?: unknown;
model?: "spark-1-pro" | "spark-1-mini";
expiresAt: string;
creditsUsed?: number;
}
interface AgentOptions$1 {
model: "FIRE-1" | "v3-beta";
}
interface ConcurrencyCheck {
concurrency: number;
maxConcurrency: number;
}
interface CreditUsage {
remainingCredits: number;
planCredits?: number;
billingPeriodStart?: string | null;
billingPeriodEnd?: string | null;
}
interface TokenUsage {
remainingTokens: number;
planTokens?: number;
billingPeriodStart?: string | null;
billingPeriodEnd?: string | null;
}
interface CreditUsageHistoricalPeriod {
startDate: string | null;
endDate: string | null;
apiKey?: string;
creditsUsed: number;
}
interface CreditUsageHistoricalResponse {
success: boolean;
periods: CreditUsageHistoricalPeriod[];
}
interface TokenUsageHistoricalPeriod {
startDate: string | null;
endDate: string | null;
apiKey?: string;
tokensUsed: number;
}
interface TokenUsageHistoricalResponse {
success: boolean;
periods: TokenUsageHistoricalPeriod[];
}
interface CrawlErrorsResponse$1 {
errors: {
id: string;
timestamp?: string;
url: string;
code?: string;
error: string;
}[];
robotsBlocked: string[];
}
interface ActiveCrawl {
id: string;
teamId: string;
url: string;
options?: Record<string, unknown> | null;
}
interface ActiveCrawlsResponse {
success: boolean;
crawls: ActiveCrawl[];
}
interface ErrorDetails {
code?: string;
message: string;
details?: Record<string, unknown>;
status?: number;
}
declare class SdkError extends Error {
status?: number;
code?: string;
details?: unknown;
jobId?: string;
constructor(message: string, status?: number, code?: string, details?: unknown, jobId?: string);
}
declare class JobTimeoutError extends SdkError {
timeoutSeconds: number;
constructor(jobId: string, timeoutSeconds: number, jobType?: "batch" | "crawl");
}
interface QueueStatusResponse$1 {
success: boolean;
jobsInQueue: number;
activeJobsInQueue: number;
waitingJobsInQueue: number;
maxConcurrency: number;
mostRecentSuccess: string | null;
}
interface BrowserCreateResponse {
success: boolean;
id?: string;
cdpUrl?: string;
liveViewUrl?: string;
interactiveLiveViewUrl?: string;
expiresAt?: string;
error?: string;
}
interface BrowserExecuteResponse {
success: boolean;
cdpUrl?: string;
liveViewUrl?: string;
interactiveLiveViewUrl?: string;
output?: string;
stdout?: string;
result?: string;
stderr?: string;
exitCode?: number;
killed?: boolean;
error?: string;
}
interface BrowserDeleteResponse {
success: boolean;
sessionDurationMs?: number;
creditsBilled?: number;
error?: string;
}
interface ScrapeExecuteRequest {
code?: string;
prompt?: string;
language?: "python" | "node" | "bash";
timeout?: number;
origin?: string;
}
type ScrapeExecuteResponse = BrowserExecuteResponse;
type ScrapeBrowserDeleteResponse = BrowserDeleteResponse;
interface BrowserSession {
id: string;
status: string;
cdpUrl: string;
liveViewUrl: string;
interactiveLiveViewUrl?: string;
streamWebView: boolean;
createdAt: string;
lastActivity: string;
}
interface BrowserListResponse {
success: boolean;
sessions?: BrowserSession[];
error?: string;
}
/**
* Source identifiers grouped by namespace. Currently only `arxiv` is
* populated; each value is an array of ids in that namespace.
*/
type IdMap = Record<string, string[]>;
/** Per-candidate ranking signals (present on similarity results). */
interface PaperSignals {
/** Raw structural strength (co-citation / coupling counts, or seed overlap). */
structural: number;
/** Semantic score from the intent abstract search (0 if absent). */
semantic: number;
/** Citation-graph article-rank score of the candidate. */
articleRank: number;
/** Number of distinct seeds connected to this candidate. */
seedOverlap: number;
}
/** A ranked paper. `paperId` is canonical; arXiv lives in `ids`. */
interface PaperResult {
/** Canonical paper id — the Milvus INT64 primary key as a decimal string. */
paperId: string;
/** Preferred cite/fetch identifier such as `arxiv:<id>`, `pmid:<id>`, or `doi:<id>`. */
primaryId: string;
ids?: IdMap;
title: string;
abstract: string;
/** Final ranking score (post-rerank when enabled). Not normalized. */
score: number;
/** Present on similarity results. */
signals?: PaperSignals;
}
interface PaperMetadata {
paperId: string;
ids?: IdMap;
title: string;
abstract: string;
/** Comma-joined author names. Omitted if unknown. */
authors?: string;
/** arXiv categories. Omitted if unknown. */
categories?: string[];
/** Original creation date string (format varies). Omitted if unknown. */
createdDate?: string;
/** Last-updated date string. Omitted if unknown. */
updateDate?: string;
}
interface Passage {
/** In-body passage text (may be markdown, including tables). */
text: string;
/** Dense similarity score for the passage. */
score: number;
}
interface SearchPapersResponse {
success: boolean;
results: PaperResult[];
}
interface PaperMetadataResponse {
success: boolean;
paper: PaperMetadata;
}
interface ReadPaperResponse {
success: boolean;
paper: PaperMetadata;
/** Resolved canonical paper id (empty string if not found via id-key). */
paperId: string;
/** Echo of the read query. */
query: string;
/** Top matching in-body passages. */
passages: Passage[];
}
interface SimilarPapersResponse {
success: boolean;
/** Ranked related papers; each carries `signals`. */
results: PaperResult[];
/** Number of resolved candidates considered before truncation to `k`. */
poolSize: number;
/** True if more resolved candidates existed than were returned. */
truncated: boolean;
/** Human-readable note when no results are produced. */
note?: string | null;
}
/** Component scores; each field is present only when that signal contributed. */
interface GitHubScoreBreakdown {
rrf?: number;
semantic?: number;
lexical?: number;
fusion?: number;
rerank?: number;
}
interface GitHubSearchItem {
resultType: "github_history" | "repo_readme" | "web";
/** `owner/name`; empty for web results whose URL is not a repo page. */
repo: string;
url: string;
/** History page type (e.g. `issue`, `pull`). Omitted for readmes. */
pageType?: string;
/** Issue/PR number. Omitted for readmes. */
number?: number;
/** Number of matched segments/chunks. Omitted when not applicable. */
segmentCount?: number;
/** Readme URL (readme results). Omitted otherwise. */
readmeUrl?: string;
/** SERP page title. Only set on web results. */
title?: string;
/** Short matched excerpt. */
snippet: string;
/** Full matched content in markdown. Omitted unless available. */
contentMd?: string;
scores: GitHubScoreBreakdown;
}
interface GitHubSearchResponse {
success: boolean;
results: GitHubSearchItem[];
}
/** Options for `research.searchPapers`. */
interface SearchPapersOptions {
/** Number of results to return (1–500, default 40). */
k?: number;
/** Author substring filter(s); ALL must match (case-insensitive). */
authors?: string[];
/** arXiv category filter(s) (e.g. `cs.LG`); ALL must match. */
categories?: string[];
/** Inclusive lower bound on created/updated date (ISO `YYYY-MM-DD`). */
from?: string;
/** Inclusive upper bound on created/updated date (lexicographic). */
to?: string;
}
/** Options for `research.getPaper`. */
interface GetPaperOptions {
/** When present, switches to read mode and returns in-body passages. */
query?: string;
/** Passage count (read mode only; 1–50, default 4). Requires `query`. */
k?: number;
}
/** Options for `research.similarPapers`. */
interface SimilarPapersOptions {
/** Natural-language intent used to semantically rerank candidates. Required. */
intent: string;
/** Traversal mode (default `similar`). */
mode?: "similar" | "citers" | "references";
/** Number of related papers to return (1–500, default 40). */
k?: number;
/** Apply an additional ZeroEntropy rerank over the fused candidates. */
rerank?: boolean;
/** Additional seed paper reference(s), same format as `id`. */
anchor?: string[];
}
/** Options for `research.searchGithub`. */
interface SearchGithubOptions {
/** Number of results to return (1–100, default 20). */
k?: number;
}
interface HttpClientOptions {
apiKey: string;
apiUrl: string;
timeoutMs?: number;
maxRetries?: number;
backoffFactor?: number;
}
interface RequestOptions {
headers?: Record<string, string>;
timeoutMs?: number;
}
declare class HttpClient {
private instance;
private readonly apiKey;
private readonly apiUrl;
private readonly maxRetries;
private readonly backoffFactor;
constructor(options: HttpClientOptions);
getApiUrl(): string;
getApiKey(): string;
private request;
private sleep;
post<T = any>(endpoint: string, body: Record<string, unknown>, options?: RequestOptions): Promise<AxiosResponse<T, any, {}>>;
postMultipart<T = any>(endpoint: string, formData: FormData, options?: RequestOptions): Promise<AxiosResponse<T, any, {}>>;
get<T = any>(endpoint: string, headers?: Record<string, string>): Promise<AxiosResponse<T, any, {}>>;
delete<T = any>(endpoint: string, headers?: Record<string, string>): Promise<AxiosResponse<T, any, {}>>;
patch<T = any>(endpoint: string, body: Record<string, unknown>, options?: RequestOptions): Promise<AxiosResponse<T, any, {}>>;
prepareHeaders(idempotencyKey?: string): Record<string, string>;
}
declare function prepareExtractPayload(args: {
urls?: string[];
prompt?: string;
schema?: Record<string, unknown> | ZodTypeAny;
systemPrompt?: string;
allowExternalLinks?: boolean;
enableWebSearch?: boolean;
showSources?: boolean;
scrapeOptions?: ScrapeOptions;
ignoreInvalidURLs?: boolean;
integration?: string;
origin?: string;
agent?: AgentOptions$1;
webhook?: string | WebhookConfig | null;
threatProtection?: ThreatProtectionOptions;
}): Record<string, unknown>;
/**
* @deprecated The extract endpoint is in maintenance mode and its use is discouraged.
* Review https://docs.firecrawl.dev/developer-guides/usage-guides/choosing-the-data-extractor to find a replacement.
*/
declare function startExtract(http: HttpClient, args: Parameters<typeof prepareExtractPayload>[0]): Promise<ExtractResponse$1>;
declare function prepareAgentPayload(args: {
urls?: string[];
prompt: string;
schema?: Record<string, unknown> | ZodTypeAny;
integration?: string;
origin?: string;
maxCredits?: number;
strictConstrainToURLs?: boolean;
model?: "spark-1-pro" | "spark-1-mini";
webhook?: string | AgentWebhookConfig;
threatProtection?: ThreatProtectionOptions;
}): Record<string, unknown>;
declare function startAgent(http: HttpClient, args: Parameters<typeof prepareAgentPayload>[0]): Promise<AgentResponse>;
declare function browser(http: HttpClient, args?: {
ttl?: number;
activityTtl?: number;
streamWebView?: boolean;
profile?: {
name: string;
saveChanges?: boolean;
};
integration?: string;
origin?: string;
}): Promise<BrowserCreateResponse>;
declare function browserExecute(http: HttpClient, sessionId: string, args: {
code: string;
language?: "python" | "node" | "bash";
timeout?: number;
}): Promise<BrowserExecuteResponse>;
declare function listBrowsers(http: HttpClient, args?: {
status?: "active" | "destroyed";
}): Promise<BrowserListResponse>;
/**
* Client for the v2 research endpoints (arXiv papers + GitHub history/readmes).
* Accessed via `firecrawl.research`.
*/
declare class ResearchClient {
private readonly http;
constructor(http: HttpClient);
/**
* Search papers by abstract relevance.
* @param query Natural-language search query.
* @param options Optional filters (k, authors, categories, from, to).
*/
searchPapers(query: string, options?: SearchPapersOptions): Promise<SearchPapersResponse>;
/**
* Get paper metadata (detail mode), or read in-body passages (when `query` is
* supplied). `k` is only valid together with `query`.
* @param id Paper reference: a canonical `paper_id`, an `arxiv:<id>` key, or a
* bare arXiv id / URL.
* @param options Optional `query` (switches to read mode) and `k`.
*/
getPaper(id: string, options?: {
query?: undefined;
k?: undefined;
}): Promise<PaperMetadataResponse>;
getPaper(id: string, options: {
query: string;
k?: number;
}): Promise<ReadPaperResponse>;
/**
* Find related papers via the citation graph.
* @param id Primary seed paper reference.
* @param options Required `intent` plus optional mode, k, rerank, anchor.
*/
similarPapers(id: string, options: SimilarPapersOptions): Promise<SimilarPapersResponse>;
/**
* Search GitHub issue/PR history and repository readmes.
* @param query Search query.
* @param options Optional `k`.
*/
searchGithub(query: string, options?: SearchGithubOptions): Promise<GitHubSearchResponse>;
}
type JobKind = "crawl" | "batch";
interface WatcherOptions {
kind?: JobKind;
pollInterval?: number;
timeout?: number;
}
declare class Watcher extends EventEmitter {
private readonly http;
private readonly jobId;
private readonly kind;
private readonly pollInterval;
private readonly timeout?;
private ws?;
private closed;
private readonly emittedDocumentKeys;
constructor(http: HttpClient, jobId: string, opts?: WatcherOptions);
private buildWsUrl;
start(): Promise<void>;
private attachWsHandlers;
private documentKey;
private emitDocuments;
private emitSnapshot;
private pollLoop;
close(): void;
}
type ExtractJsonSchemaFromFormats<Formats> = Formats extends readonly any[] ? Extract<Formats[number], {
type: "json";
schema?: unknown;
}>["schema"] : never;
type InferredJsonFromOptions<Opts> = Opts extends {
formats?: infer Fmts;
} ? ExtractJsonSchemaFromFormats<Fmts> extends zt.ZodTypeAny ? zt.infer<ExtractJsonSchemaFromFormats<Fmts>> : unknown : unknown;
/**
* Configuration for the v2 client transport.
*/
interface FirecrawlClientOptions {
/** API key (falls back to FIRECRAWL_API_KEY). */
apiKey?: string | null;
/** API base URL (falls back to FIRECRAWL_API_URL or https://api.firecrawl.dev). */
apiUrl?: string | null;
/** Per-request timeout in milliseconds (optional). */
timeoutMs?: number;
/** Max automatic retries for transient failures (optional). */
maxRetries?: number;
/** Exponential backoff factor for retries (optional). */
backoffFactor?: number;
}
/** Accepts a plain API key string or a full options object. */
type FirecrawlClientInput = FirecrawlClientOptions | string;
/**
* Firecrawl v2 client. Provides typed access to all v2 endpoints and utilities.
*/
declare class FirecrawlClient {
private readonly http;
private _research?;
private isCloudService;
/**
* Create a v2 client.
* @param options API key string or transport configuration object.
*/
constructor(options?: FirecrawlClientInput);
/**
* Scrape a single URL.
* @param url Target URL.
* @param options Optional scrape options (formats, headers, etc.).
* @returns Resolved document with requested formats.
*/
scrape<Opts extends ScrapeOptions>(url: string, options: Opts): Promise<Omit<Document, "json"> & {
json?: InferredJsonFromOptions<Opts>;
}>;
scrape(url: string, options?: ScrapeOptions): Promise<Document>;
/**
* Interact with the browser session associated with a scrape job.
* @param jobId Scrape job id.
* @param args Code or prompt to execute, with language/timeout options.
* @returns Execution result including output, stdout, stderr, exitCode, and killed status.
*/
interact(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
/**
* Stop the interaction session associated with a scrape job.
* @param jobId Scrape job id.
*/
stopInteraction(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
/**
* @deprecated Use interact().
*/
scrapeExecute(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
/**
* @deprecated Use stopInteraction().
*/
stopInteractiveBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
/**
* @deprecated Use stopInteraction().
*/
deleteScrapeBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
/**
* Parse an uploaded file via the v2 parse endpoint.
* @param file File payload (data, filename, optional contentType).
* @param options Optional parse options (formats, parsers, etc.).
* Note: parse does not support changeTracking, screenshot, branding,
* audio, video,
* actions, waitFor, location, or mobile options.
* @returns Parsed document with requested formats.
*/
parse<Opts extends ParseOptions>(file: ParseFile, options: Opts): Promise<Omit<Document, "json"> & {
json?: InferredJsonFromOptions<Opts>;
}>;
parse(file: ParseFile, options?: ParseOptions): Promise<Document>;
/**
* Search the web and optionally scrape each result.
* @param query Search query string.
* @param req Additional search options (sources, limit, scrapeOptions, etc.).
* @returns Structured search results.
*/
search(query: string, req?: Omit<SearchRequest, "query">): Promise<SearchData>;
/**
* Submit feedback for a v2 job.
* @param request Feedback payload with endpoint, job id, rating, and supporting signals.
* @returns Feedback record and refund details.
*/
feedback(request: EndpointFeedbackRequest): Promise<FeedbackResponse>;
/**
* Submit feedback for a search job.
* @param jobId Search job id returned by search.
* @param request Search feedback payload.
* @returns Feedback record and refund details.
*/
searchFeedback(jobId: string, request: SearchFeedbackRequest): Promise<FeedbackResponse>;
/**
* Access the v2 research endpoints (arXiv papers + GitHub history/readmes).
* Example: `firecrawl.research.searchPapers("diffusion models")`.
*/
get research(): ResearchClient;
/**
* Map a site to discover URLs (sitemap-aware).
* @param url Root URL to map.
* @param options Mapping options (sitemap mode, includeSubdomains, limit, timeout).
* @returns Discovered links.
*/
map(url: string, options?: MapOptions): Promise<MapData>;
/**
* Start a crawl job (async).
* @param url Root URL to crawl.
* @param req Crawl configuration (paths, limits, scrapeOptions, webhook, etc.).
* @returns Job id and url.
*/
startCrawl(url: string, req?: CrawlOptions): Promise<CrawlResponse$1>;
/**
* Get the status and partial data of a crawl job.
* @param jobId Crawl job id.
*/
getCrawlStatus(jobId: string, pagination?: PaginationConfig): Promise<CrawlJob>;
/**
* Cancel a crawl job.
* @param jobId Crawl job id.
* @returns True if cancelled.
*/
cancelCrawl(jobId: string): Promise<boolean>;
/**
* Convenience waiter: start a crawl and poll until it finishes.
* @param url Root URL to crawl.
* @param req Crawl configuration plus waiter controls (pollInterval, timeout seconds).
* @returns Final job snapshot.
*/
crawl(url: string, req?: CrawlOptions & {
pollInterval?: number;
timeout?: number;
}): Promise<CrawlJob>;
/**
* Retrieve crawl errors and robots.txt blocks.
* @param crawlId Crawl job id.
*/
getCrawlErrors(crawlId: string): Promise<CrawlErrorsResponse$1>;
/**
* List active crawls for the authenticated team.
*/
getActiveCrawls(): Promise<ActiveCrawlsResponse>;
/**
* Preview normalized crawl parameters produced by a natural-language prompt.
* @param url Root URL.
* @param prompt Natural-language instruction.
*/
crawlParamsPreview(url: string, prompt: string): Promise<Record<string, unknown>>;
/**
* Create a scheduled monitor.
*/
createMonitor(request: CreateMonitorRequest): Promise<Monitor>;
/**
* List monitors for the authenticated team.
*/
listMonitors(options?: ListMonitorsOptions): Promise<Monitor[]>;
/**
* Get a monitor by id.
*/
getMonitor(monitorId: string): Promise<Monitor>;
/**
* Update a monitor.
*/
updateMonitor(monitorId: string, request: UpdateMonitorRequest): Promise<Monitor>;
/**
* Delete a monitor.
*/
deleteMonitor(monitorId: string): Promise<boolean>;
/**
* Trigger a manual monitor check.
*/
runMonitor(monitorId: string): Promise<MonitorCheck>;
/**
* List checks for a monitor.
*/
listMonitorChecks(monitorId: string, options?: ListMonitorChecksOptions): Promise<MonitorCheck[]>;
/**
* Get a monitor check with paginated page results and inline diffs.
*/
getMonitorCheck(monitorId: string, checkId: string, options?: GetMonitorCheckOptions): Promise<MonitorCheckDetail>;
/**
* Start a batch scrape job for multiple URLs (async).
* @param urls URLs to scrape.
* @param opts Batch options (scrape options, webhook, concurrency, idempotency key, etc.).
* @returns Job id and url.
*/
startBatchScrape(urls: string[], opts?: BatchScrapeOptions): Promise<BatchScrapeResponse$1>;
/**
* Get the status and partial data of a batch scrape job.
* @param jobId Batch job id.
*/
getBatchScrapeStatus(jobId: string, pagination?: PaginationConfig): Promise<BatchScrapeJob>;
/**
* Retrieve batch scrape errors and robots.txt blocks.
* @param jobId Batch job id.
*/
getBatchScrapeErrors(jobId: string): Promise<CrawlErrorsResponse$1>;
/**
* Cancel a batch scrape job.
* @param jobId Batch job id.
* @returns True if cancelled.
*/
cancelBatchScrape(jobId: string): Promise<boolean>;
/**
* Convenience waiter: start a batch scrape and poll until it finishes.
* @param urls URLs to scrape.
* @param opts Batch options plus wait