import { HttpClient } from "./utils/httpClient"; import { scrape, interact as interactMethod, stopInteraction as stopInteractionMethod, } from "./methods/scrape"; import { parse as parseMethod } from "./methods/parse"; import { search } from "./methods/search"; import { map as mapMethod } from "./methods/map"; import { feedback as feedbackMethod, searchFeedback as searchFeedbackMethod } from "./methods/feedback"; import { startCrawl, getCrawlStatus, cancelCrawl, crawl as crawlWaiter, getCrawlErrors, getActiveCrawls, crawlParamsPreview, } from "./methods/crawl"; import { startBatchScrape, getBatchScrapeStatus, getBatchScrapeErrors, cancelBatchScrape, batchScrape as batchWaiter, } from "./methods/batch"; import { startExtract, getExtractStatus, extract as extractWaiter } from "./methods/extract"; import { startAgent, getAgentStatus, cancelAgent, agent as agentWaiter } from "./methods/agent"; import { browser as browserMethod, browserExecute, deleteBrowser, listBrowsers, } from "./methods/browser"; import { getConcurrency, getCreditUsage, getQueueStatus, getTokenUsage, getCreditUsageHistorical, getTokenUsageHistorical } from "./methods/usage"; import { ResearchClient } from "./methods/research"; import { createMonitor as createMonitorMethod, deleteMonitor as deleteMonitorMethod, getMonitor as getMonitorMethod, getMonitorCheck as getMonitorCheckMethod, listMonitorChecks as listMonitorChecksMethod, listMonitors as listMonitorsMethod, runMonitor as runMonitorMethod, updateMonitor as updateMonitorMethod, } from "./methods/monitor"; import type { Document, ParseFile, ParseOptions, ScrapeOptions, SearchData, SearchRequest, EndpointFeedbackRequest, FeedbackResponse, SearchFeedbackRequest, MapData, MapOptions, CrawlResponse, CrawlJob, CrawlErrorsResponse, ActiveCrawlsResponse, BatchScrapeResponse, BatchScrapeJob, ExtractResponse, AgentResponse, AgentStatusResponse, CrawlOptions, BatchScrapeOptions, PaginationConfig, BrowserCreateResponse, BrowserExecuteResponse, BrowserDeleteResponse, BrowserListResponse, ScrapeExecuteRequest, ScrapeExecuteResponse, ScrapeBrowserDeleteResponse, CreateMonitorRequest, ListMonitorChecksOptions, ListMonitorsOptions, Monitor, MonitorCheck, MonitorCheckDetail, GetMonitorCheckOptions, UpdateMonitorRequest, } from "./types"; import { Watcher } from "./watcher"; import type { WatcherOptions } from "./watcher"; import * as zt from "zod"; // Helper types to infer the `json` field from a Zod schema included in `formats` type ExtractJsonSchemaFromFormats = Formats extends readonly any[] ? Extract["schema"] : never; type InferredJsonFromOptions = Opts extends { formats?: infer Fmts } ? ExtractJsonSchemaFromFormats extends zt.ZodTypeAny ? zt.infer> : unknown : unknown; /** * Configuration for the v2 client transport. */ export 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. */ export type FirecrawlClientInput = FirecrawlClientOptions | string; /** * Firecrawl v2 client. Provides typed access to all v2 endpoints and utilities. */ export class FirecrawlClient { private readonly http: HttpClient; private _research?: ResearchClient; private isCloudService(url: string): boolean { return url.includes('api.firecrawl.dev'); } /** * Create a v2 client. * @param options API key string or transport configuration object. */ constructor(options: FirecrawlClientInput = {}) { const opts: FirecrawlClientOptions = typeof options === "string" ? { apiKey: options } : options; const apiKey = (opts.apiKey ?? process.env.FIRECRAWL_API_KEY ?? "").trim(); const apiUrl = (opts.apiUrl ?? process.env.FIRECRAWL_API_URL ?? "https://api.firecrawl.dev").replace(/\/$/, ""); // No API key is allowed: scrape, search, and interact fall back to the // keyless free tier (rate-limited per IP). Other methods will return 401 // from the API until a key is provided. this.http = new HttpClient({ apiKey, apiUrl, timeoutMs: opts.timeoutMs, maxRetries: opts.maxRetries, backoffFactor: opts.backoffFactor, }); } // Scrape /** * Scrape a single URL. * @param url Target URL. * @param options Optional scrape options (formats, headers, etc.). * @returns Resolved document with requested formats. */ async scrape( url: string, options: Opts ): Promise & { json?: InferredJsonFromOptions }>; async scrape(url: string, options?: ScrapeOptions): Promise; async scrape(url: string, options?: ScrapeOptions): Promise { return scrape(this.http, url, options); } /** * 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. */ async interact( jobId: string, args: ScrapeExecuteRequest ): Promise { return interactMethod(this.http, jobId, args); } /** * Stop the interaction session associated with a scrape job. * @param jobId Scrape job id. */ async stopInteraction(jobId: string): Promise { return stopInteractionMethod(this.http, jobId); } /** * @deprecated Use interact(). */ async scrapeExecute( jobId: string, args: ScrapeExecuteRequest ): Promise { return this.interact(jobId, args); } /** * @deprecated Use stopInteraction(). */ async stopInteractiveBrowser(jobId: string): Promise { return this.stopInteraction(jobId); } /** * @deprecated Use stopInteraction(). */ async deleteScrapeBrowser(jobId: string): Promise { return this.stopInteraction(jobId); } // Parse /** * 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. */ async parse( file: ParseFile, options: Opts ): Promise & { json?: InferredJsonFromOptions }>; async parse(file: ParseFile, options?: ParseOptions): Promise; async parse(file: ParseFile, options?: ParseOptions): Promise { return parseMethod(this.http, file, options); } // Search /** * 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. */ async search(query: string, req: Omit = {}): Promise { return search(this.http, { query, ...req }); } /** * Submit feedback for a v2 job. * @param request Feedback payload with endpoint, job id, rating, and supporting signals. * @returns Feedback record and refund details. */ async feedback(request: EndpointFeedbackRequest): Promise { return feedbackMethod(this.http, request); } /** * 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. */ async searchFeedback(jobId: string, request: SearchFeedbackRequest): Promise { return searchFeedbackMethod(this.http, jobId, request); } // Research /** * Access the v2 research endpoints (arXiv papers + GitHub history/readmes). * Example: `firecrawl.research.searchPapers("diffusion models")`. */ get research(): ResearchClient { if (!this._research) this._research = new ResearchClient(this.http); return this._research; } // Map /** * 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. */ async map(url: string, options?: MapOptions): Promise { return mapMethod(this.http, url, options); } // Crawl /** * 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. */ async startCrawl(url: string, req: CrawlOptions = {}): Promise { return startCrawl(this.http, { url, ...req }); } /** * Get the status and partial data of a crawl job. * @param jobId Crawl job id. */ async getCrawlStatus(jobId: string, pagination?: PaginationConfig): Promise { return getCrawlStatus(this.http, jobId, pagination); } /** * Cancel a crawl job. * @param jobId Crawl job id. * @returns True if cancelled. */ async cancelCrawl(jobId: string): Promise { return cancelCrawl(this.http, jobId); } /** * 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. */ async crawl(url: string, req: CrawlOptions & { pollInterval?: number; timeout?: number } = {}): Promise { return crawlWaiter(this.http, { url, ...req }, req.pollInterval, req.timeout); } /** * Retrieve crawl errors and robots.txt blocks. * @param crawlId Crawl job id. */ async getCrawlErrors(crawlId: string): Promise { return getCrawlErrors(this.http, crawlId); } /** * List active crawls for the authenticated team. */ async getActiveCrawls(): Promise { return getActiveCrawls(this.http); } /** * Preview normalized crawl parameters produced by a natural-language prompt. * @param url Root URL. * @param prompt Natural-language instruction. */ async crawlParamsPreview(url: string, prompt: string): Promise> { return crawlParamsPreview(this.http, url, prompt); } // Monitor /** * Create a scheduled monitor. */ async createMonitor(request: CreateMonitorRequest): Promise { return createMonitorMethod(this.http, request); } /** * List monitors for the authenticated team. */ async listMonitors(options?: ListMonitorsOptions): Promise { return listMonitorsMethod(this.http, options); } /** * Get a monitor by id. */ async getMonitor(monitorId: string): Promise { return getMonitorMethod(this.http, monitorId); } /** * Update a monitor. */ async updateMonitor( monitorId: string, request: UpdateMonitorRequest, ): Promise { return updateMonitorMethod(this.http, monitorId, request); } /** * Delete a monitor. */ async deleteMonitor(monitorId: string): Promise { return deleteMonitorMethod(this.http, monitorId); } /** * Trigger a manual monitor check. */ async runMonitor(monitorId: string): Promise { return runMonitorMethod(this.http, monitorId); } /** * List checks for a monitor. */ async listMonitorChecks( monitorId: string, options?: ListMonitorChecksOptions, ): Promise { return listMonitorChecksMethod(this.http, monitorId, options); } /** * Get a monitor check with paginated page results and inline diffs. */ async getMonitorCheck( monitorId: string, checkId: string, options?: GetMonitorCheckOptions, ): Promise { return getMonitorCheckMethod(this.http, monitorId, checkId, options); } // Batch /** * 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. */ async startBatchScrape(urls: string[], opts?: BatchScrapeOptions): Promise { return startBatchScrape(this.http, urls, opts); } /** * Get the status and partial data of a batch scrape job. * @param jobId Batch job id. */ async getBatchScrapeStatus(jobId: string, pagination?: PaginationConfig): Promise { return getBatchScrapeStatus(this.http, jobId, pagination); } /** * Retrieve batch scrape errors and robots.txt blocks. * @param jobId Batch job id. */ async getBatchScrapeErrors(jobId: string): Promise { return getBatchScrapeErrors(this.http, jobId); } /** * Cancel a batch scrape job. * @param jobId Batch job id. * @returns True if cancelled. */ async cancelBatchScrape(jobId: string): Promise { return cancelBatchScrape(this.http, jobId); } /** * Convenience waiter: start a batch scrape and poll until it finishes. * @param urls URLs to scrape. * @param opts Batch options plus waiter controls (pollInterval, timeout seconds). * @returns Final job snapshot. */ async batchScrape(urls: string[], opts?: BatchScrapeOptions & { pollInterval?: number; timeout?: number }): Promise { return batchWaiter(this.http, urls, opts); } // Extract /** * Start an extract job (async). * @param args Extraction request (urls, schema or prompt, flags). * @returns Job id or processing state. * @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. */ async startExtract(args: Parameters[1]): Promise { return startExtract(this.http, args); } /** * Get extract job status/data. * @param jobId Extract job id. * @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. */ async getExtractStatus(jobId: string): Promise { return getExtractStatus(this.http, jobId); } /** * Convenience waiter: start an extract and poll until it finishes. * @param args Extraction request plus waiter controls (pollInterval, timeout seconds). * @returns Final extract response. * @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. */ async extract(args: Parameters[1] & { pollInterval?: number; timeout?: number }): Promise { return extractWaiter(this.http, args); } // Agent /** * Start an agent job (async). * @param args Agent request (urls, prompt, schema). * @returns Job id or processing state. */ async startAgent(args: Parameters[1]): Promise { return startAgent(this.http, args); } /** * Get agent job status/data. * @param jobId Agent job id. */ async getAgentStatus(jobId: string): Promise { return getAgentStatus(this.http, jobId); } /** * Convenience waiter: start an agent and poll until it finishes. * @param args Agent request plus waiter controls (pollInterval, timeout seconds). * @returns Final agent response. */ async agent(args: Parameters[1] & { pollInterval?: number; timeout?: number }): Promise { return agentWaiter(this.http, args); } /** * Cancel an agent job. * @param jobId Agent job id. * @returns True if cancelled. */ async cancelAgent(jobId: string): Promise { return cancelAgent(this.http, jobId); } // Browser /** * Create a new browser session. * @param args Session options (ttl, activityTtl, streamWebView, profile). * @returns Session id, CDP URL, live view URL, and expiration time. */ async browser( args: Parameters[1] = {} ): Promise { return browserMethod(this.http, args); } /** * Execute code in a browser session. * @param sessionId Browser session id. * @param args Code, language ("python" | "node" | "bash"), and optional timeout. * @returns Execution result including stdout, stderr, exitCode, and killed status. */ async browserExecute( sessionId: string, args: Parameters[2] ): Promise { return browserExecute(this.http, sessionId, args); } /** * Delete a browser session. * @param sessionId Browser session id. */ async deleteBrowser(sessionId: string): Promise { return deleteBrowser(this.http, sessionId); } /** * List browser sessions. * @param args Optional filter (status: "active" | "destroyed"). * @returns List of browser sessions. */ async listBrowsers( args: Parameters[1] = {} ): Promise { return listBrowsers(this.http, args); } // Usage /** Current concurrency usage. */ async getConcurrency() { return getConcurrency(this.http); } /** Current credit usage. */ async getCreditUsage() { return getCreditUsage(this.http); } /** Recent token usage. */ async getTokenUsage() { return getTokenUsage(this.http); } /** Historical credit usage by month; set byApiKey to true to break down by API key. */ async getCreditUsageHistorical(byApiKey?: boolean) { return getCreditUsageHistorical(this.http, byApiKey); } /** Historical token usage by month; set byApiKey to true to break down by API key. */ async getTokenUsageHistorical(byApiKey?: boolean) { return getTokenUsageHistorical(this.http, byApiKey); } /** Metrics about the team's scrape queue. */ async getQueueStatus() { return getQueueStatus(this.http); } // Watcher /** * Create a watcher for a crawl or batch job. Emits: `document`, `snapshot`, `done`, `error`. * @param jobId Job id. * @param opts Watcher options (kind, pollInterval, timeout seconds). */ watcher(jobId: string, opts: WatcherOptions = {}): Watcher { return new Watcher(this.http, jobId, opts); } /** @deprecated V1 compatibility alias for agent recovery. Prefer scrape(). */ async scrapeUrl(url: string, options?: ScrapeOptions): Promise { return this.scrape(url, options); } /** @deprecated V1 compatibility alias for agent recovery. Prefer crawl(). */ async crawlUrl(url: string, req: CrawlOptions & { pollInterval?: number; timeout?: number } = {}): Promise { return this.crawl(url, req); } /** @deprecated V1 compatibility alias for agent recovery. Prefer startCrawl(). */ async asyncCrawlUrl(url: string, req: CrawlOptions = {}): Promise { return this.startCrawl(url, req); } /** @deprecated V1 compatibility alias for agent recovery. Prefer getCrawlStatus(). */ async checkCrawlStatus(jobId: string, pagination?: PaginationConfig): Promise { return this.getCrawlStatus(jobId, pagination); } /** @deprecated V1 compatibility alias for agent recovery. Prefer getCrawlErrors(). */ async checkCrawlErrors(crawlId: string): Promise { return this.getCrawlErrors(crawlId); } /** @deprecated V1 compatibility alias for agent recovery. Prefer map(). */ async mapUrl(url: string, options?: MapOptions): Promise { return this.map(url, options); } /** @deprecated V1 compatibility alias for agent recovery. Prefer batchScrape(). */ async batchScrapeUrls(urls: string[], opts?: BatchScrapeOptions & { pollInterval?: number; timeout?: number }): Promise { return this.batchScrape(urls, opts); } /** @deprecated V1 compatibility alias for agent recovery. Prefer startBatchScrape(). */ async asyncBatchScrapeUrls(urls: string[], opts?: BatchScrapeOptions): Promise { return this.startBatchScrape(urls, opts); } /** @deprecated V1 compatibility alias for agent recovery. Prefer getBatchScrapeStatus(). */ async checkBatchScrapeStatus(jobId: string, pagination?: PaginationConfig): Promise { return this.getBatchScrapeStatus(jobId, pagination); } /** @deprecated V1 compatibility alias for agent recovery. Prefer getBatchScrapeErrors(). */ async checkBatchScrapeErrors(jobId: string): Promise { return this.getBatchScrapeErrors(jobId); } } export default FirecrawlClient;