firecrawl
Advanced tools
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __commonJS = (cb, mod) => function __require() { | ||
| return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; | ||
| }; | ||
| // package.json | ||
| var require_package = __commonJS({ | ||
| "package.json"(exports, module) { | ||
| module.exports = { | ||
| name: "@mendable/firecrawl-js", | ||
| version: "4.17.0", | ||
| description: "JavaScript SDK for Firecrawl API", | ||
| main: "dist/index.js", | ||
| types: "dist/index.d.ts", | ||
| exports: { | ||
| "./package.json": "./package.json", | ||
| ".": { | ||
| import: "./dist/index.js", | ||
| default: "./dist/index.cjs" | ||
| } | ||
| }, | ||
| type: "module", | ||
| scripts: { | ||
| build: "tsup", | ||
| "build-and-publish": "pnpm run build && pnpm publish --access public", | ||
| "publish-beta": "pnpm run build && pnpm publish --access public --tag beta", | ||
| test: "NODE_OPTIONS=--experimental-vm-modules jest --verbose src/__tests__/e2e/v2/*.test.ts --detectOpenHandles", | ||
| "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --verbose src/__tests__/unit/v2/*.test.ts" | ||
| }, | ||
| repository: { | ||
| type: "git", | ||
| url: "git+https://github.com/firecrawl/firecrawl.git" | ||
| }, | ||
| author: "Mendable.ai", | ||
| license: "MIT", | ||
| dependencies: { | ||
| axios: "^1.13.5", | ||
| firecrawl: "4.16.0", | ||
| "typescript-event-target": "^1.1.1", | ||
| zod: "^3.23.8", | ||
| "zod-to-json-schema": "^3.23.0" | ||
| }, | ||
| bugs: { | ||
| url: "https://github.com/firecrawl/firecrawl/issues" | ||
| }, | ||
| homepage: "https://github.com/firecrawl/firecrawl#readme", | ||
| devDependencies: { | ||
| "@jest/globals": "^30.2.0", | ||
| "@types/dotenv": "^8.2.0", | ||
| "@types/jest": "^30.0.0", | ||
| "@types/mocha": "^10.0.6", | ||
| "@types/node": "^20.12.12", | ||
| "@types/uuid": "^9.0.8", | ||
| dotenv: "^16.4.5", | ||
| jest: "^30.2.0", | ||
| "ts-jest": "^29.4.5", | ||
| tsup: "^8.5.0", | ||
| typescript: "^5.4.5", | ||
| uuid: "^9.0.1" | ||
| }, | ||
| keywords: [ | ||
| "firecrawl", | ||
| "mendable", | ||
| "crawler", | ||
| "web", | ||
| "scraper", | ||
| "api", | ||
| "sdk" | ||
| ], | ||
| engines: { | ||
| node: ">=22.0.0" | ||
| }, | ||
| pnpm: { | ||
| overrides: { | ||
| "@isaacs/brace-expansion@<=5.0.0": ">=5.0.1", | ||
| "minimatch@<10.2.3": ">=10.2.3", | ||
| "rollup@<4.59.0": ">=4.59.0" | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| }); | ||
| export { | ||
| require_package | ||
| }; |
| import { | ||
| require_package | ||
| } from "./chunk-2UJCMTR4.js"; | ||
| export default require_package(); |
| import { describe, test, expect, jest } from "@jest/globals"; | ||
| import { interact, stopInteraction } from "../../../v2/methods/scrape"; | ||
| import { SdkError } from "../../../v2/types"; | ||
| describe("JS SDK v2 scrape-browser methods", () => { | ||
| test("interact posts to scrape interact endpoint", async () => { | ||
| const post = jest.fn(async () => ({ | ||
| status: 200, | ||
| data: { | ||
| success: true, | ||
| stdout: "ok", | ||
| exitCode: 0, | ||
| }, | ||
| })); | ||
| const http = { post } as any; | ||
| const response = await interact(http, "job-123", { code: "console.log('ok')" }); | ||
| expect(post).toHaveBeenCalledWith("/v2/scrape/job-123/interact", { | ||
| code: "console.log('ok')", | ||
| language: "node", | ||
| }); | ||
| expect(response.success).toBe(true); | ||
| expect(response.exitCode).toBe(0); | ||
| }); | ||
| test("interact with prompt posts prompt to endpoint", async () => { | ||
| const post = jest.fn(async () => ({ | ||
| status: 200, | ||
| data: { | ||
| success: true, | ||
| output: "Clicked the button", | ||
| liveViewUrl: "https://live.example.com/view", | ||
| interactiveLiveViewUrl: "https://live.example.com/interactive", | ||
| stdout: "", | ||
| exitCode: 0, | ||
| }, | ||
| })); | ||
| const http = { post } as any; | ||
| const response = await interact(http, "job-456", { prompt: "Click the login button" }); | ||
| expect(post).toHaveBeenCalledWith("/v2/scrape/job-456/interact", { | ||
| prompt: "Click the login button", | ||
| language: "node", | ||
| }); | ||
| expect(response.success).toBe(true); | ||
| expect(response.output).toBe("Clicked the button"); | ||
| expect(response.liveViewUrl).toBe("https://live.example.com/view"); | ||
| expect(response.interactiveLiveViewUrl).toBe("https://live.example.com/interactive"); | ||
| }); | ||
| test("interact throws when neither code nor prompt provided", async () => { | ||
| const http = { post: jest.fn() } as any; | ||
| await expect(interact(http, "job-123", {})).rejects.toThrow( | ||
| "Either 'code' or 'prompt' must be provided" | ||
| ); | ||
| }); | ||
| test("interact throws on non-200 response", async () => { | ||
| const post = jest.fn(async () => ({ | ||
| status: 400, | ||
| data: { | ||
| success: false, | ||
| error: "Invalid job ID format", | ||
| }, | ||
| })); | ||
| const http = { post } as any; | ||
| await expect( | ||
| interact(http, "bad-id", { code: "console.log('ok')" }) | ||
| ).rejects.toBeInstanceOf(SdkError); | ||
| }); | ||
| test("stopInteraction calls delete endpoint", async () => { | ||
| const del = jest.fn(async () => ({ | ||
| status: 200, | ||
| data: { | ||
| success: true, | ||
| }, | ||
| })); | ||
| const http = { delete: del } as any; | ||
| const response = await stopInteraction(http, "job-123"); | ||
| expect(del).toHaveBeenCalledWith("/v2/scrape/job-123/interact"); | ||
| expect(response.success).toBe(true); | ||
| }); | ||
| test("stopInteraction throws on non-200 response", async () => { | ||
| const del = jest.fn(async () => ({ | ||
| status: 404, | ||
| data: { | ||
| success: false, | ||
| error: "Browser session not found.", | ||
| }, | ||
| })); | ||
| const http = { delete: del } as any; | ||
| await expect(stopInteraction(http, "job-123")).rejects.toBeInstanceOf( | ||
| SdkError | ||
| ); | ||
| }); | ||
| }); |
+1
-1
| { | ||
| "name": "firecrawl", | ||
| "version": "4.16.0", | ||
| "version": "4.17.0", | ||
| "description": "JavaScript SDK for Firecrawl API", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
+22
-0
@@ -113,2 +113,24 @@ # Firecrawl Node SDK | ||
| ### Scrape-bound interactive browsing (v2) | ||
| Use a scrape job ID to keep interacting with the replayed browser context: | ||
| ```js | ||
| const doc = await app.scrape('https://example.com', { | ||
| actions: [{ type: 'click', selector: 'a[href="/pricing"]' }], | ||
| }); | ||
| const scrapeJobId = doc?.metadata?.scrapeId; | ||
| if (!scrapeJobId) throw new Error('Missing scrapeId'); | ||
| const run = await app.interact(scrapeJobId, { | ||
| code: 'console.log(await page.url())', | ||
| language: 'node', | ||
| timeout: 60, | ||
| }); | ||
| console.log(run.stdout); | ||
| await app.stopInteraction(scrapeJobId); | ||
| ``` | ||
| ### Crawl a website with real‑time updates | ||
@@ -115,0 +137,0 @@ |
+48
-1
| import { HttpClient } from "./utils/httpClient"; | ||
| import { scrape } from "./methods/scrape"; | ||
| import { | ||
| scrape, | ||
| interact as interactMethod, | ||
| stopInteraction as stopInteractionMethod, | ||
| } from "./methods/scrape"; | ||
| import { search } from "./methods/search"; | ||
@@ -53,2 +57,5 @@ import { map as mapMethod } from "./methods/map"; | ||
| BrowserListResponse, | ||
| ScrapeExecuteRequest, | ||
| ScrapeExecuteResponse, | ||
| ScrapeBrowserDeleteResponse, | ||
| } from "./types"; | ||
@@ -133,2 +140,42 @@ import { Watcher } from "./watcher"; | ||
| } | ||
| /** | ||
| * 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<ScrapeExecuteResponse> { | ||
| 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<ScrapeBrowserDeleteResponse> { | ||
| return stopInteractionMethod(this.http, jobId); | ||
| } | ||
| /** | ||
| * @deprecated Use interact(). | ||
| */ | ||
| async scrapeExecute( | ||
| jobId: string, | ||
| args: ScrapeExecuteRequest | ||
| ): Promise<ScrapeExecuteResponse> { | ||
| return this.interact(jobId, args); | ||
| } | ||
| /** | ||
| * @deprecated Use stopInteraction(). | ||
| */ | ||
| async stopInteractiveBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse> { | ||
| return this.stopInteraction(jobId); | ||
| } | ||
| /** | ||
| * @deprecated Use stopInteraction(). | ||
| */ | ||
| async deleteScrapeBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse> { | ||
| return this.stopInteraction(jobId); | ||
| } | ||
@@ -135,0 +182,0 @@ // Search |
@@ -1,2 +0,8 @@ | ||
| import { type Document, type ScrapeOptions } from "../types"; | ||
| import { | ||
| type Document, | ||
| type ScrapeBrowserDeleteResponse, | ||
| type ScrapeExecuteRequest, | ||
| type ScrapeExecuteResponse, | ||
| type ScrapeOptions, | ||
| } from "../types"; | ||
| import { HttpClient } from "../utils/httpClient"; | ||
@@ -27,1 +33,80 @@ import { ensureValidScrapeOptions } from "../utils/validation"; | ||
| export async function interact( | ||
| http: HttpClient, | ||
| jobId: string, | ||
| args: ScrapeExecuteRequest | ||
| ): Promise<ScrapeExecuteResponse> { | ||
| if (!jobId || !jobId.trim()) { | ||
| throw new Error("Job ID cannot be empty"); | ||
| } | ||
| const hasCode = args?.code && args.code.trim(); | ||
| const hasPrompt = args?.prompt && args.prompt.trim(); | ||
| if (!hasCode && !hasPrompt) { | ||
| throw new Error("Either 'code' or 'prompt' must be provided"); | ||
| } | ||
| const body: Record<string, unknown> = {}; | ||
| if (hasCode) body.code = args.code; | ||
| if (hasPrompt) body.prompt = args.prompt; | ||
| body.language = args.language ?? "node"; | ||
| if (args.timeout != null) body.timeout = args.timeout; | ||
| if (args.origin) body.origin = args.origin; | ||
| try { | ||
| const res = await http.post<ScrapeExecuteResponse>( | ||
| `/v2/scrape/${jobId}/interact`, | ||
| body | ||
| ); | ||
| if (res.status !== 200) throwForBadResponse(res, "interact with scrape browser"); | ||
| return res.data; | ||
| } catch (err: any) { | ||
| if (err?.isAxiosError) return normalizeAxiosError(err, "interact with scrape browser"); | ||
| throw err; | ||
| } | ||
| } | ||
| export async function stopInteraction( | ||
| http: HttpClient, | ||
| jobId: string | ||
| ): Promise<ScrapeBrowserDeleteResponse> { | ||
| if (!jobId || !jobId.trim()) { | ||
| throw new Error("Job ID cannot be empty"); | ||
| } | ||
| try { | ||
| const res = await http.delete<ScrapeBrowserDeleteResponse>( | ||
| `/v2/scrape/${jobId}/interact` | ||
| ); | ||
| if (res.status !== 200) throwForBadResponse(res, "stop interaction"); | ||
| return res.data; | ||
| } catch (err: any) { | ||
| if (err?.isAxiosError) return normalizeAxiosError(err, "stop interaction"); | ||
| throw err; | ||
| } | ||
| } | ||
| /** @deprecated Use interact(). */ | ||
| export async function scrapeExecute( | ||
| http: HttpClient, | ||
| jobId: string, | ||
| args: ScrapeExecuteRequest | ||
| ): Promise<ScrapeExecuteResponse> { | ||
| return interact(http, jobId, args); | ||
| } | ||
| /** @deprecated Use stopInteraction(). */ | ||
| export async function stopInteractiveBrowser( | ||
| http: HttpClient, | ||
| jobId: string | ||
| ): Promise<ScrapeBrowserDeleteResponse> { | ||
| return stopInteraction(http, jobId); | ||
| } | ||
| /** @deprecated Use stopInteraction(). */ | ||
| export async function deleteScrapeBrowser( | ||
| http: HttpClient, | ||
| jobId: string | ||
| ): Promise<ScrapeBrowserDeleteResponse> { | ||
| return stopInteraction(http, jobId); | ||
| } | ||
+18
-0
@@ -166,2 +166,6 @@ import type { ZodTypeAny } from 'zod'; | ||
| storeInCache?: boolean; | ||
| profile?: { | ||
| name: string; | ||
| saveChanges?: boolean; | ||
| }; | ||
| integration?: string; | ||
@@ -715,2 +719,5 @@ origin?: string; | ||
| success: boolean; | ||
| liveViewUrl?: string; | ||
| interactiveLiveViewUrl?: string; | ||
| output?: string; | ||
| stdout?: string; | ||
@@ -731,2 +738,13 @@ result?: string; | ||
| export interface ScrapeExecuteRequest { | ||
| code?: string; | ||
| prompt?: string; | ||
| language?: "python" | "node" | "bash"; | ||
| timeout?: number; | ||
| origin?: string; | ||
| } | ||
| export type ScrapeExecuteResponse = BrowserExecuteResponse; | ||
| export type ScrapeBrowserDeleteResponse = BrowserDeleteResponse; | ||
| export interface BrowserSession { | ||
@@ -733,0 +751,0 @@ id: string; |
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __commonJS = (cb, mod) => function __require() { | ||
| return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; | ||
| }; | ||
| // package.json | ||
| var require_package = __commonJS({ | ||
| "package.json"(exports, module) { | ||
| module.exports = { | ||
| name: "@mendable/firecrawl-js", | ||
| version: "4.16.0", | ||
| description: "JavaScript SDK for Firecrawl API", | ||
| main: "dist/index.js", | ||
| types: "dist/index.d.ts", | ||
| exports: { | ||
| "./package.json": "./package.json", | ||
| ".": { | ||
| import: "./dist/index.js", | ||
| default: "./dist/index.cjs" | ||
| } | ||
| }, | ||
| type: "module", | ||
| scripts: { | ||
| build: "tsup", | ||
| "build-and-publish": "pnpm run build && pnpm publish --access public", | ||
| "publish-beta": "pnpm run build && pnpm publish --access public --tag beta", | ||
| test: "NODE_OPTIONS=--experimental-vm-modules jest --verbose src/__tests__/e2e/v2/*.test.ts --detectOpenHandles", | ||
| "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --verbose src/__tests__/unit/v2/*.test.ts" | ||
| }, | ||
| repository: { | ||
| type: "git", | ||
| url: "git+https://github.com/firecrawl/firecrawl.git" | ||
| }, | ||
| author: "Mendable.ai", | ||
| license: "MIT", | ||
| dependencies: { | ||
| axios: "^1.13.5", | ||
| firecrawl: "4.15.2", | ||
| "typescript-event-target": "^1.1.1", | ||
| zod: "^3.23.8", | ||
| "zod-to-json-schema": "^3.23.0" | ||
| }, | ||
| bugs: { | ||
| url: "https://github.com/firecrawl/firecrawl/issues" | ||
| }, | ||
| homepage: "https://github.com/firecrawl/firecrawl#readme", | ||
| devDependencies: { | ||
| "@jest/globals": "^30.2.0", | ||
| "@types/dotenv": "^8.2.0", | ||
| "@types/jest": "^30.0.0", | ||
| "@types/mocha": "^10.0.6", | ||
| "@types/node": "^20.12.12", | ||
| "@types/uuid": "^9.0.8", | ||
| dotenv: "^16.4.5", | ||
| jest: "^30.2.0", | ||
| "ts-jest": "^29.4.5", | ||
| tsup: "^8.5.0", | ||
| typescript: "^5.4.5", | ||
| uuid: "^9.0.1" | ||
| }, | ||
| keywords: [ | ||
| "firecrawl", | ||
| "mendable", | ||
| "crawler", | ||
| "web", | ||
| "scraper", | ||
| "api", | ||
| "sdk" | ||
| ], | ||
| engines: { | ||
| node: ">=22.0.0" | ||
| }, | ||
| pnpm: { | ||
| overrides: { | ||
| "@isaacs/brace-expansion@<=5.0.0": ">=5.0.1", | ||
| "minimatch@<10.2.3": ">=10.2.3", | ||
| "rollup@<4.59.0": ">=4.59.0" | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| }); | ||
| export { | ||
| require_package | ||
| }; |
| import { | ||
| require_package | ||
| } from "./chunk-OM7BT4QE.js"; | ||
| export default require_package(); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 13 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 13 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
673729
2.35%56
1.82%16622
2.6%230
10.58%