@mendable/firecrawl-js 4.15.4 → 4.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -110,6 +110,28 @@ const mapResult = await app.map('https://example.com');
110
110
  console.log(mapResult);
111
111
  ```
112
112
 
113
+ ### Scrape-bound interactive browsing (v2)
114
+
115
+ Use a scrape job ID to keep interacting with the replayed browser context:
116
+
117
+ ```js
118
+ const doc = await app.scrape('https://example.com', {
119
+ actions: [{ type: 'click', selector: 'a[href="/pricing"]' }],
120
+ });
121
+
122
+ const scrapeJobId = doc?.metadata?.scrapeId;
123
+ if (!scrapeJobId) throw new Error('Missing scrapeId');
124
+
125
+ const run = await app.interact(scrapeJobId, {
126
+ code: 'console.log(await page.url())',
127
+ language: 'node',
128
+ timeout: 60,
129
+ });
130
+ console.log(run.stdout);
131
+
132
+ await app.stopInteraction(scrapeJobId);
133
+ ```
134
+
113
135
  ### Crawl a website with real‑time updates
114
136
 
115
137
  To receive real‑time updates, start a crawl and attach a watcher.
@@ -8,7 +8,7 @@ var require_package = __commonJS({
8
8
  "package.json"(exports, module) {
9
9
  module.exports = {
10
10
  name: "@mendable/firecrawl-js",
11
- version: "4.15.4",
11
+ version: "4.17.0",
12
12
  description: "JavaScript SDK for Firecrawl API",
13
13
  main: "dist/index.js",
14
14
  types: "dist/index.d.ts",
@@ -35,7 +35,7 @@ var require_package = __commonJS({
35
35
  license: "MIT",
36
36
  dependencies: {
37
37
  axios: "^1.13.5",
38
- firecrawl: "4.15.2",
38
+ firecrawl: "4.16.0",
39
39
  "typescript-event-target": "^1.1.1",
40
40
  zod: "^3.23.8",
41
41
  "zod-to-json-schema": "^3.23.0"
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ var require_package = __commonJS({
35
35
  "package.json"(exports2, module2) {
36
36
  module2.exports = {
37
37
  name: "@mendable/firecrawl-js",
38
- version: "4.15.4",
38
+ version: "4.17.0",
39
39
  description: "JavaScript SDK for Firecrawl API",
40
40
  main: "dist/index.js",
41
41
  types: "dist/index.d.ts",
@@ -62,7 +62,7 @@ var require_package = __commonJS({
62
62
  license: "MIT",
63
63
  dependencies: {
64
64
  axios: "^1.13.5",
65
- firecrawl: "4.15.2",
65
+ firecrawl: "4.16.0",
66
66
  "typescript-event-target": "^1.1.1",
67
67
  zod: "^3.23.8",
68
68
  "zod-to-json-schema": "^3.23.0"
@@ -408,6 +408,48 @@ async function scrape(http, url, options) {
408
408
  throw err;
409
409
  }
410
410
  }
411
+ async function interact(http, jobId, args) {
412
+ if (!jobId || !jobId.trim()) {
413
+ throw new Error("Job ID cannot be empty");
414
+ }
415
+ const hasCode = args?.code && args.code.trim();
416
+ const hasPrompt = args?.prompt && args.prompt.trim();
417
+ if (!hasCode && !hasPrompt) {
418
+ throw new Error("Either 'code' or 'prompt' must be provided");
419
+ }
420
+ const body = {};
421
+ if (hasCode) body.code = args.code;
422
+ if (hasPrompt) body.prompt = args.prompt;
423
+ body.language = args.language ?? "node";
424
+ if (args.timeout != null) body.timeout = args.timeout;
425
+ if (args.origin) body.origin = args.origin;
426
+ try {
427
+ const res = await http.post(
428
+ `/v2/scrape/${jobId}/interact`,
429
+ body
430
+ );
431
+ if (res.status !== 200) throwForBadResponse(res, "interact with scrape browser");
432
+ return res.data;
433
+ } catch (err) {
434
+ if (err?.isAxiosError) return normalizeAxiosError(err, "interact with scrape browser");
435
+ throw err;
436
+ }
437
+ }
438
+ async function stopInteraction(http, jobId) {
439
+ if (!jobId || !jobId.trim()) {
440
+ throw new Error("Job ID cannot be empty");
441
+ }
442
+ try {
443
+ const res = await http.delete(
444
+ `/v2/scrape/${jobId}/interact`
445
+ );
446
+ if (res.status !== 200) throwForBadResponse(res, "stop interaction");
447
+ return res.data;
448
+ } catch (err) {
449
+ if (err?.isAxiosError) return normalizeAxiosError(err, "stop interaction");
450
+ throw err;
451
+ }
452
+ }
411
453
 
412
454
  // src/v2/methods/search.ts
413
455
  function prepareSearchPayload(req) {
@@ -1322,6 +1364,40 @@ var FirecrawlClient = class {
1322
1364
  async scrape(url, options) {
1323
1365
  return scrape(this.http, url, options);
1324
1366
  }
1367
+ /**
1368
+ * Interact with the browser session associated with a scrape job.
1369
+ * @param jobId Scrape job id.
1370
+ * @param args Code or prompt to execute, with language/timeout options.
1371
+ * @returns Execution result including output, stdout, stderr, exitCode, and killed status.
1372
+ */
1373
+ async interact(jobId, args) {
1374
+ return interact(this.http, jobId, args);
1375
+ }
1376
+ /**
1377
+ * Stop the interaction session associated with a scrape job.
1378
+ * @param jobId Scrape job id.
1379
+ */
1380
+ async stopInteraction(jobId) {
1381
+ return stopInteraction(this.http, jobId);
1382
+ }
1383
+ /**
1384
+ * @deprecated Use interact().
1385
+ */
1386
+ async scrapeExecute(jobId, args) {
1387
+ return this.interact(jobId, args);
1388
+ }
1389
+ /**
1390
+ * @deprecated Use stopInteraction().
1391
+ */
1392
+ async stopInteractiveBrowser(jobId) {
1393
+ return this.stopInteraction(jobId);
1394
+ }
1395
+ /**
1396
+ * @deprecated Use stopInteraction().
1397
+ */
1398
+ async deleteScrapeBrowser(jobId) {
1399
+ return this.stopInteraction(jobId);
1400
+ }
1325
1401
  // Search
1326
1402
  /**
1327
1403
  * Search the web and optionally scrape each result.
package/dist/index.d.cts CHANGED
@@ -40,7 +40,11 @@ interface AttributesFormat extends Format {
40
40
  attribute: string;
41
41
  }>;
42
42
  }
43
- type FormatOption = FormatString | Format | JsonFormat | ChangeTrackingFormat | ScreenshotFormat | AttributesFormat;
43
+ interface QueryFormat {
44
+ type: 'query';
45
+ prompt: string;
46
+ }
47
+ type FormatOption = FormatString | Format | JsonFormat | ChangeTrackingFormat | ScreenshotFormat | AttributesFormat | QueryFormat;
44
48
  interface LocationConfig$1 {
45
49
  country?: string;
46
50
  languages?: string[];
@@ -115,6 +119,10 @@ interface ScrapeOptions {
115
119
  maxAge?: number;
116
120
  minAge?: number;
117
121
  storeInCache?: boolean;
122
+ profile?: {
123
+ name: string;
124
+ saveChanges?: boolean;
125
+ };
118
126
  integration?: string;
119
127
  origin?: string;
120
128
  }
@@ -318,6 +326,7 @@ interface Document {
318
326
  values: string[];
319
327
  }>;
320
328
  actions?: Record<string, unknown>;
329
+ answer?: string;
321
330
  warning?: string;
322
331
  changeTracking?: Record<string, unknown>;
323
332
  branding?: BrandingProfile;
@@ -573,6 +582,9 @@ interface BrowserCreateResponse {
573
582
  }
574
583
  interface BrowserExecuteResponse {
575
584
  success: boolean;
585
+ liveViewUrl?: string;
586
+ interactiveLiveViewUrl?: string;
587
+ output?: string;
576
588
  stdout?: string;
577
589
  result?: string;
578
590
  stderr?: string;
@@ -586,6 +598,15 @@ interface BrowserDeleteResponse {
586
598
  creditsBilled?: number;
587
599
  error?: string;
588
600
  }
601
+ interface ScrapeExecuteRequest {
602
+ code?: string;
603
+ prompt?: string;
604
+ language?: "python" | "node" | "bash";
605
+ timeout?: number;
606
+ origin?: string;
607
+ }
608
+ type ScrapeExecuteResponse = BrowserExecuteResponse;
609
+ type ScrapeBrowserDeleteResponse = BrowserDeleteResponse;
589
610
  interface BrowserSession {
590
611
  id: string;
591
612
  status: string;
@@ -748,6 +769,30 @@ declare class FirecrawlClient {
748
769
  json?: InferredJsonFromOptions<Opts>;
749
770
  }>;
750
771
  scrape(url: string, options?: ScrapeOptions): Promise<Document>;
772
+ /**
773
+ * Interact with the browser session associated with a scrape job.
774
+ * @param jobId Scrape job id.
775
+ * @param args Code or prompt to execute, with language/timeout options.
776
+ * @returns Execution result including output, stdout, stderr, exitCode, and killed status.
777
+ */
778
+ interact(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
779
+ /**
780
+ * Stop the interaction session associated with a scrape job.
781
+ * @param jobId Scrape job id.
782
+ */
783
+ stopInteraction(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
784
+ /**
785
+ * @deprecated Use interact().
786
+ */
787
+ scrapeExecute(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
788
+ /**
789
+ * @deprecated Use stopInteraction().
790
+ */
791
+ stopInteractiveBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
792
+ /**
793
+ * @deprecated Use stopInteraction().
794
+ */
795
+ deleteScrapeBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
751
796
  /**
752
797
  * Search the web and optionally scrape each result.
753
798
  * @param query Search query string.
@@ -1844,4 +1889,4 @@ declare class Firecrawl extends FirecrawlClient {
1844
1889
  get v1(): FirecrawlApp;
1845
1890
  }
1846
1891
 
1847
- export { type ActionOption, type ActiveCrawl, type ActiveCrawlsResponse, type AgentOptions$1 as AgentOptions, type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig, type AgentWebhookEvent, type AttributesFormat, type BatchScrapeJob, type BatchScrapeOptions, type BatchScrapeResponse$1 as BatchScrapeResponse, type BrandingProfile, type BrowserCreateResponse, type BrowserDeleteResponse, type BrowserExecuteResponse, type BrowserListResponse, type BrowserSession, type CategoryOption, type ChangeTrackingFormat, type ClickAction, type ConcurrencyCheck, type CrawlErrorsResponse$1 as CrawlErrorsResponse, type CrawlJob, type CrawlOptions, type CrawlResponse$1 as CrawlResponse, type CreditUsage, type CreditUsageHistoricalPeriod, type CreditUsageHistoricalResponse, type Document, type DocumentMetadata, type ErrorDetails, type ExecuteJavascriptAction, type ExtractResponse$1 as ExtractResponse, Firecrawl, FirecrawlApp as FirecrawlAppV1, FirecrawlClient, type FirecrawlClientOptions, type Format, type FormatOption, type FormatString, JobTimeoutError, type JsonFormat, type LocationConfig$1 as LocationConfig, type MapData, type MapOptions, type PDFAction, type PaginationConfig, type PressAction, type QueueStatusResponse$1 as QueueStatusResponse, type ScrapeAction, type ScrapeOptions, type ScreenshotAction, type ScreenshotFormat, type ScrollAction, SdkError, type SearchData, type SearchRequest, type SearchResultImages, type SearchResultNews, type SearchResultWeb, type TokenUsage, type TokenUsageHistoricalPeriod, type TokenUsageHistoricalResponse, type Viewport, type WaitAction, Watcher, type WatcherOptions, type WebhookConfig, type WriteAction, Firecrawl as default };
1892
+ export { type ActionOption, type ActiveCrawl, type ActiveCrawlsResponse, type AgentOptions$1 as AgentOptions, type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig, type AgentWebhookEvent, type AttributesFormat, type BatchScrapeJob, type BatchScrapeOptions, type BatchScrapeResponse$1 as BatchScrapeResponse, type BrandingProfile, type BrowserCreateResponse, type BrowserDeleteResponse, type BrowserExecuteResponse, type BrowserListResponse, type BrowserSession, type CategoryOption, type ChangeTrackingFormat, type ClickAction, type ConcurrencyCheck, type CrawlErrorsResponse$1 as CrawlErrorsResponse, type CrawlJob, type CrawlOptions, type CrawlResponse$1 as CrawlResponse, type CreditUsage, type CreditUsageHistoricalPeriod, type CreditUsageHistoricalResponse, type Document, type DocumentMetadata, type ErrorDetails, type ExecuteJavascriptAction, type ExtractResponse$1 as ExtractResponse, Firecrawl, FirecrawlApp as FirecrawlAppV1, FirecrawlClient, type FirecrawlClientOptions, type Format, type FormatOption, type FormatString, JobTimeoutError, type JsonFormat, type LocationConfig$1 as LocationConfig, type MapData, type MapOptions, type PDFAction, type PaginationConfig, type PressAction, type QueryFormat, type QueueStatusResponse$1 as QueueStatusResponse, type ScrapeAction, type ScrapeBrowserDeleteResponse, type ScrapeExecuteRequest, type ScrapeExecuteResponse, type ScrapeOptions, type ScreenshotAction, type ScreenshotFormat, type ScrollAction, SdkError, type SearchData, type SearchRequest, type SearchResultImages, type SearchResultNews, type SearchResultWeb, type TokenUsage, type TokenUsageHistoricalPeriod, type TokenUsageHistoricalResponse, type Viewport, type WaitAction, Watcher, type WatcherOptions, type WebhookConfig, type WriteAction, Firecrawl as default };
package/dist/index.d.ts CHANGED
@@ -40,7 +40,11 @@ interface AttributesFormat extends Format {
40
40
  attribute: string;
41
41
  }>;
42
42
  }
43
- type FormatOption = FormatString | Format | JsonFormat | ChangeTrackingFormat | ScreenshotFormat | AttributesFormat;
43
+ interface QueryFormat {
44
+ type: 'query';
45
+ prompt: string;
46
+ }
47
+ type FormatOption = FormatString | Format | JsonFormat | ChangeTrackingFormat | ScreenshotFormat | AttributesFormat | QueryFormat;
44
48
  interface LocationConfig$1 {
45
49
  country?: string;
46
50
  languages?: string[];
@@ -115,6 +119,10 @@ interface ScrapeOptions {
115
119
  maxAge?: number;
116
120
  minAge?: number;
117
121
  storeInCache?: boolean;
122
+ profile?: {
123
+ name: string;
124
+ saveChanges?: boolean;
125
+ };
118
126
  integration?: string;
119
127
  origin?: string;
120
128
  }
@@ -318,6 +326,7 @@ interface Document {
318
326
  values: string[];
319
327
  }>;
320
328
  actions?: Record<string, unknown>;
329
+ answer?: string;
321
330
  warning?: string;
322
331
  changeTracking?: Record<string, unknown>;
323
332
  branding?: BrandingProfile;
@@ -573,6 +582,9 @@ interface BrowserCreateResponse {
573
582
  }
574
583
  interface BrowserExecuteResponse {
575
584
  success: boolean;
585
+ liveViewUrl?: string;
586
+ interactiveLiveViewUrl?: string;
587
+ output?: string;
576
588
  stdout?: string;
577
589
  result?: string;
578
590
  stderr?: string;
@@ -586,6 +598,15 @@ interface BrowserDeleteResponse {
586
598
  creditsBilled?: number;
587
599
  error?: string;
588
600
  }
601
+ interface ScrapeExecuteRequest {
602
+ code?: string;
603
+ prompt?: string;
604
+ language?: "python" | "node" | "bash";
605
+ timeout?: number;
606
+ origin?: string;
607
+ }
608
+ type ScrapeExecuteResponse = BrowserExecuteResponse;
609
+ type ScrapeBrowserDeleteResponse = BrowserDeleteResponse;
589
610
  interface BrowserSession {
590
611
  id: string;
591
612
  status: string;
@@ -748,6 +769,30 @@ declare class FirecrawlClient {
748
769
  json?: InferredJsonFromOptions<Opts>;
749
770
  }>;
750
771
  scrape(url: string, options?: ScrapeOptions): Promise<Document>;
772
+ /**
773
+ * Interact with the browser session associated with a scrape job.
774
+ * @param jobId Scrape job id.
775
+ * @param args Code or prompt to execute, with language/timeout options.
776
+ * @returns Execution result including output, stdout, stderr, exitCode, and killed status.
777
+ */
778
+ interact(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
779
+ /**
780
+ * Stop the interaction session associated with a scrape job.
781
+ * @param jobId Scrape job id.
782
+ */
783
+ stopInteraction(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
784
+ /**
785
+ * @deprecated Use interact().
786
+ */
787
+ scrapeExecute(jobId: string, args: ScrapeExecuteRequest): Promise<ScrapeExecuteResponse>;
788
+ /**
789
+ * @deprecated Use stopInteraction().
790
+ */
791
+ stopInteractiveBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
792
+ /**
793
+ * @deprecated Use stopInteraction().
794
+ */
795
+ deleteScrapeBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse>;
751
796
  /**
752
797
  * Search the web and optionally scrape each result.
753
798
  * @param query Search query string.
@@ -1844,4 +1889,4 @@ declare class Firecrawl extends FirecrawlClient {
1844
1889
  get v1(): FirecrawlApp;
1845
1890
  }
1846
1891
 
1847
- export { type ActionOption, type ActiveCrawl, type ActiveCrawlsResponse, type AgentOptions$1 as AgentOptions, type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig, type AgentWebhookEvent, type AttributesFormat, type BatchScrapeJob, type BatchScrapeOptions, type BatchScrapeResponse$1 as BatchScrapeResponse, type BrandingProfile, type BrowserCreateResponse, type BrowserDeleteResponse, type BrowserExecuteResponse, type BrowserListResponse, type BrowserSession, type CategoryOption, type ChangeTrackingFormat, type ClickAction, type ConcurrencyCheck, type CrawlErrorsResponse$1 as CrawlErrorsResponse, type CrawlJob, type CrawlOptions, type CrawlResponse$1 as CrawlResponse, type CreditUsage, type CreditUsageHistoricalPeriod, type CreditUsageHistoricalResponse, type Document, type DocumentMetadata, type ErrorDetails, type ExecuteJavascriptAction, type ExtractResponse$1 as ExtractResponse, Firecrawl, FirecrawlApp as FirecrawlAppV1, FirecrawlClient, type FirecrawlClientOptions, type Format, type FormatOption, type FormatString, JobTimeoutError, type JsonFormat, type LocationConfig$1 as LocationConfig, type MapData, type MapOptions, type PDFAction, type PaginationConfig, type PressAction, type QueueStatusResponse$1 as QueueStatusResponse, type ScrapeAction, type ScrapeOptions, type ScreenshotAction, type ScreenshotFormat, type ScrollAction, SdkError, type SearchData, type SearchRequest, type SearchResultImages, type SearchResultNews, type SearchResultWeb, type TokenUsage, type TokenUsageHistoricalPeriod, type TokenUsageHistoricalResponse, type Viewport, type WaitAction, Watcher, type WatcherOptions, type WebhookConfig, type WriteAction, Firecrawl as default };
1892
+ export { type ActionOption, type ActiveCrawl, type ActiveCrawlsResponse, type AgentOptions$1 as AgentOptions, type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig, type AgentWebhookEvent, type AttributesFormat, type BatchScrapeJob, type BatchScrapeOptions, type BatchScrapeResponse$1 as BatchScrapeResponse, type BrandingProfile, type BrowserCreateResponse, type BrowserDeleteResponse, type BrowserExecuteResponse, type BrowserListResponse, type BrowserSession, type CategoryOption, type ChangeTrackingFormat, type ClickAction, type ConcurrencyCheck, type CrawlErrorsResponse$1 as CrawlErrorsResponse, type CrawlJob, type CrawlOptions, type CrawlResponse$1 as CrawlResponse, type CreditUsage, type CreditUsageHistoricalPeriod, type CreditUsageHistoricalResponse, type Document, type DocumentMetadata, type ErrorDetails, type ExecuteJavascriptAction, type ExtractResponse$1 as ExtractResponse, Firecrawl, FirecrawlApp as FirecrawlAppV1, FirecrawlClient, type FirecrawlClientOptions, type Format, type FormatOption, type FormatString, JobTimeoutError, type JsonFormat, type LocationConfig$1 as LocationConfig, type MapData, type MapOptions, type PDFAction, type PaginationConfig, type PressAction, type QueryFormat, type QueueStatusResponse$1 as QueueStatusResponse, type ScrapeAction, type ScrapeBrowserDeleteResponse, type ScrapeExecuteRequest, type ScrapeExecuteResponse, type ScrapeOptions, type ScreenshotAction, type ScreenshotFormat, type ScrollAction, SdkError, type SearchData, type SearchRequest, type SearchResultImages, type SearchResultNews, type SearchResultWeb, type TokenUsage, type TokenUsageHistoricalPeriod, type TokenUsageHistoricalResponse, type Viewport, type WaitAction, Watcher, type WatcherOptions, type WebhookConfig, type WriteAction, Firecrawl as default };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  require_package
3
- } from "./chunk-LHLOMVKV.js";
3
+ } from "./chunk-2UJCMTR4.js";
4
4
 
5
5
  // src/v2/utils/httpClient.ts
6
6
  import axios from "axios";
@@ -289,6 +289,48 @@ async function scrape(http, url, options) {
289
289
  throw err;
290
290
  }
291
291
  }
292
+ async function interact(http, jobId, args) {
293
+ if (!jobId || !jobId.trim()) {
294
+ throw new Error("Job ID cannot be empty");
295
+ }
296
+ const hasCode = args?.code && args.code.trim();
297
+ const hasPrompt = args?.prompt && args.prompt.trim();
298
+ if (!hasCode && !hasPrompt) {
299
+ throw new Error("Either 'code' or 'prompt' must be provided");
300
+ }
301
+ const body = {};
302
+ if (hasCode) body.code = args.code;
303
+ if (hasPrompt) body.prompt = args.prompt;
304
+ body.language = args.language ?? "node";
305
+ if (args.timeout != null) body.timeout = args.timeout;
306
+ if (args.origin) body.origin = args.origin;
307
+ try {
308
+ const res = await http.post(
309
+ `/v2/scrape/${jobId}/interact`,
310
+ body
311
+ );
312
+ if (res.status !== 200) throwForBadResponse(res, "interact with scrape browser");
313
+ return res.data;
314
+ } catch (err) {
315
+ if (err?.isAxiosError) return normalizeAxiosError(err, "interact with scrape browser");
316
+ throw err;
317
+ }
318
+ }
319
+ async function stopInteraction(http, jobId) {
320
+ if (!jobId || !jobId.trim()) {
321
+ throw new Error("Job ID cannot be empty");
322
+ }
323
+ try {
324
+ const res = await http.delete(
325
+ `/v2/scrape/${jobId}/interact`
326
+ );
327
+ if (res.status !== 200) throwForBadResponse(res, "stop interaction");
328
+ return res.data;
329
+ } catch (err) {
330
+ if (err?.isAxiosError) return normalizeAxiosError(err, "stop interaction");
331
+ throw err;
332
+ }
333
+ }
292
334
 
293
335
  // src/v2/methods/search.ts
294
336
  function prepareSearchPayload(req) {
@@ -1203,6 +1245,40 @@ var FirecrawlClient = class {
1203
1245
  async scrape(url, options) {
1204
1246
  return scrape(this.http, url, options);
1205
1247
  }
1248
+ /**
1249
+ * Interact with the browser session associated with a scrape job.
1250
+ * @param jobId Scrape job id.
1251
+ * @param args Code or prompt to execute, with language/timeout options.
1252
+ * @returns Execution result including output, stdout, stderr, exitCode, and killed status.
1253
+ */
1254
+ async interact(jobId, args) {
1255
+ return interact(this.http, jobId, args);
1256
+ }
1257
+ /**
1258
+ * Stop the interaction session associated with a scrape job.
1259
+ * @param jobId Scrape job id.
1260
+ */
1261
+ async stopInteraction(jobId) {
1262
+ return stopInteraction(this.http, jobId);
1263
+ }
1264
+ /**
1265
+ * @deprecated Use interact().
1266
+ */
1267
+ async scrapeExecute(jobId, args) {
1268
+ return this.interact(jobId, args);
1269
+ }
1270
+ /**
1271
+ * @deprecated Use stopInteraction().
1272
+ */
1273
+ async stopInteractiveBrowser(jobId) {
1274
+ return this.stopInteraction(jobId);
1275
+ }
1276
+ /**
1277
+ * @deprecated Use stopInteraction().
1278
+ */
1279
+ async deleteScrapeBrowser(jobId) {
1280
+ return this.stopInteraction(jobId);
1281
+ }
1206
1282
  // Search
1207
1283
  /**
1208
1284
  * Search the web and optionally scrape each result.
@@ -1483,7 +1559,7 @@ var FirecrawlApp = class {
1483
1559
  if (typeof process !== "undefined" && process.env && process.env.npm_package_version) {
1484
1560
  return process.env.npm_package_version;
1485
1561
  }
1486
- const packageJson = await import("./package-5WBMC2X6.js");
1562
+ const packageJson = await import("./package-UDBWBSIB.js");
1487
1563
  return packageJson.default.version;
1488
1564
  } catch (error) {
1489
1565
  const isTest = typeof process !== "undefined" && (process.env.JEST_WORKER_ID != null || false);
@@ -1,4 +1,4 @@
1
1
  import {
2
2
  require_package
3
- } from "./chunk-LHLOMVKV.js";
3
+ } from "./chunk-2UJCMTR4.js";
4
4
  export default require_package();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mendable/firecrawl-js",
3
- "version": "4.15.4",
3
+ "version": "4.17.0",
4
4
  "description": "JavaScript SDK for Firecrawl API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
22
  "axios": "^1.13.5",
23
- "firecrawl": "4.15.2",
23
+ "firecrawl": "4.16.0",
24
24
  "typescript-event-target": "^1.1.1",
25
25
  "zod": "^3.23.8",
26
26
  "zod-to-json-schema": "^3.23.0"
@@ -0,0 +1,104 @@
1
+ import { describe, test, expect, jest } from "@jest/globals";
2
+ import { interact, stopInteraction } from "../../../v2/methods/scrape";
3
+ import { SdkError } from "../../../v2/types";
4
+
5
+ describe("JS SDK v2 scrape-browser methods", () => {
6
+ test("interact posts to scrape interact endpoint", async () => {
7
+ const post = jest.fn(async () => ({
8
+ status: 200,
9
+ data: {
10
+ success: true,
11
+ stdout: "ok",
12
+ exitCode: 0,
13
+ },
14
+ }));
15
+
16
+ const http = { post } as any;
17
+ const response = await interact(http, "job-123", { code: "console.log('ok')" });
18
+
19
+ expect(post).toHaveBeenCalledWith("/v2/scrape/job-123/interact", {
20
+ code: "console.log('ok')",
21
+ language: "node",
22
+ });
23
+ expect(response.success).toBe(true);
24
+ expect(response.exitCode).toBe(0);
25
+ });
26
+
27
+ test("interact with prompt posts prompt to endpoint", async () => {
28
+ const post = jest.fn(async () => ({
29
+ status: 200,
30
+ data: {
31
+ success: true,
32
+ output: "Clicked the button",
33
+ liveViewUrl: "https://live.example.com/view",
34
+ interactiveLiveViewUrl: "https://live.example.com/interactive",
35
+ stdout: "",
36
+ exitCode: 0,
37
+ },
38
+ }));
39
+
40
+ const http = { post } as any;
41
+ const response = await interact(http, "job-456", { prompt: "Click the login button" });
42
+
43
+ expect(post).toHaveBeenCalledWith("/v2/scrape/job-456/interact", {
44
+ prompt: "Click the login button",
45
+ language: "node",
46
+ });
47
+ expect(response.success).toBe(true);
48
+ expect(response.output).toBe("Clicked the button");
49
+ expect(response.liveViewUrl).toBe("https://live.example.com/view");
50
+ expect(response.interactiveLiveViewUrl).toBe("https://live.example.com/interactive");
51
+ });
52
+
53
+ test("interact throws when neither code nor prompt provided", async () => {
54
+ const http = { post: jest.fn() } as any;
55
+ await expect(interact(http, "job-123", {})).rejects.toThrow(
56
+ "Either 'code' or 'prompt' must be provided"
57
+ );
58
+ });
59
+
60
+ test("interact throws on non-200 response", async () => {
61
+ const post = jest.fn(async () => ({
62
+ status: 400,
63
+ data: {
64
+ success: false,
65
+ error: "Invalid job ID format",
66
+ },
67
+ }));
68
+
69
+ const http = { post } as any;
70
+ await expect(
71
+ interact(http, "bad-id", { code: "console.log('ok')" })
72
+ ).rejects.toBeInstanceOf(SdkError);
73
+ });
74
+
75
+ test("stopInteraction calls delete endpoint", async () => {
76
+ const del = jest.fn(async () => ({
77
+ status: 200,
78
+ data: {
79
+ success: true,
80
+ },
81
+ }));
82
+
83
+ const http = { delete: del } as any;
84
+ const response = await stopInteraction(http, "job-123");
85
+
86
+ expect(del).toHaveBeenCalledWith("/v2/scrape/job-123/interact");
87
+ expect(response.success).toBe(true);
88
+ });
89
+
90
+ test("stopInteraction throws on non-200 response", async () => {
91
+ const del = jest.fn(async () => ({
92
+ status: 404,
93
+ data: {
94
+ success: false,
95
+ error: "Browser session not found.",
96
+ },
97
+ }));
98
+
99
+ const http = { delete: del } as any;
100
+ await expect(stopInteraction(http, "job-123")).rejects.toBeInstanceOf(
101
+ SdkError
102
+ );
103
+ });
104
+ });
package/src/v2/client.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import { HttpClient } from "./utils/httpClient";
2
- import { scrape } from "./methods/scrape";
2
+ import {
3
+ scrape,
4
+ interact as interactMethod,
5
+ stopInteraction as stopInteractionMethod,
6
+ } from "./methods/scrape";
3
7
  import { search } from "./methods/search";
4
8
  import { map as mapMethod } from "./methods/map";
5
9
  import {
@@ -50,6 +54,9 @@ import type {
50
54
  BrowserExecuteResponse,
51
55
  BrowserDeleteResponse,
52
56
  BrowserListResponse,
57
+ ScrapeExecuteRequest,
58
+ ScrapeExecuteResponse,
59
+ ScrapeBrowserDeleteResponse,
53
60
  } from "./types";
54
61
  import { Watcher } from "./watcher";
55
62
  import type { WatcherOptions } from "./watcher";
@@ -129,6 +136,46 @@ export class FirecrawlClient {
129
136
  async scrape(url: string, options?: ScrapeOptions): Promise<Document> {
130
137
  return scrape(this.http, url, options);
131
138
  }
139
+ /**
140
+ * Interact with the browser session associated with a scrape job.
141
+ * @param jobId Scrape job id.
142
+ * @param args Code or prompt to execute, with language/timeout options.
143
+ * @returns Execution result including output, stdout, stderr, exitCode, and killed status.
144
+ */
145
+ async interact(
146
+ jobId: string,
147
+ args: ScrapeExecuteRequest
148
+ ): Promise<ScrapeExecuteResponse> {
149
+ return interactMethod(this.http, jobId, args);
150
+ }
151
+ /**
152
+ * Stop the interaction session associated with a scrape job.
153
+ * @param jobId Scrape job id.
154
+ */
155
+ async stopInteraction(jobId: string): Promise<ScrapeBrowserDeleteResponse> {
156
+ return stopInteractionMethod(this.http, jobId);
157
+ }
158
+ /**
159
+ * @deprecated Use interact().
160
+ */
161
+ async scrapeExecute(
162
+ jobId: string,
163
+ args: ScrapeExecuteRequest
164
+ ): Promise<ScrapeExecuteResponse> {
165
+ return this.interact(jobId, args);
166
+ }
167
+ /**
168
+ * @deprecated Use stopInteraction().
169
+ */
170
+ async stopInteractiveBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse> {
171
+ return this.stopInteraction(jobId);
172
+ }
173
+ /**
174
+ * @deprecated Use stopInteraction().
175
+ */
176
+ async deleteScrapeBrowser(jobId: string): Promise<ScrapeBrowserDeleteResponse> {
177
+ return this.stopInteraction(jobId);
178
+ }
132
179
 
133
180
  // Search
134
181
  /**
@@ -1,4 +1,10 @@
1
- import { type Document, type ScrapeOptions } from "../types";
1
+ import {
2
+ type Document,
3
+ type ScrapeBrowserDeleteResponse,
4
+ type ScrapeExecuteRequest,
5
+ type ScrapeExecuteResponse,
6
+ type ScrapeOptions,
7
+ } from "../types";
2
8
  import { HttpClient } from "../utils/httpClient";
3
9
  import { ensureValidScrapeOptions } from "../utils/validation";
4
10
  import { throwForBadResponse, normalizeAxiosError } from "../utils/errorHandler";
@@ -24,3 +30,82 @@ export async function scrape(http: HttpClient, url: string, options?: ScrapeOpti
24
30
  }
25
31
  }
26
32
 
33
+ export async function interact(
34
+ http: HttpClient,
35
+ jobId: string,
36
+ args: ScrapeExecuteRequest
37
+ ): Promise<ScrapeExecuteResponse> {
38
+ if (!jobId || !jobId.trim()) {
39
+ throw new Error("Job ID cannot be empty");
40
+ }
41
+ const hasCode = args?.code && args.code.trim();
42
+ const hasPrompt = args?.prompt && args.prompt.trim();
43
+ if (!hasCode && !hasPrompt) {
44
+ throw new Error("Either 'code' or 'prompt' must be provided");
45
+ }
46
+
47
+ const body: Record<string, unknown> = {};
48
+ if (hasCode) body.code = args.code;
49
+ if (hasPrompt) body.prompt = args.prompt;
50
+ body.language = args.language ?? "node";
51
+ if (args.timeout != null) body.timeout = args.timeout;
52
+ if (args.origin) body.origin = args.origin;
53
+
54
+ try {
55
+ const res = await http.post<ScrapeExecuteResponse>(
56
+ `/v2/scrape/${jobId}/interact`,
57
+ body
58
+ );
59
+ if (res.status !== 200) throwForBadResponse(res, "interact with scrape browser");
60
+ return res.data;
61
+ } catch (err: any) {
62
+ if (err?.isAxiosError) return normalizeAxiosError(err, "interact with scrape browser");
63
+ throw err;
64
+ }
65
+ }
66
+
67
+ export async function stopInteraction(
68
+ http: HttpClient,
69
+ jobId: string
70
+ ): Promise<ScrapeBrowserDeleteResponse> {
71
+ if (!jobId || !jobId.trim()) {
72
+ throw new Error("Job ID cannot be empty");
73
+ }
74
+
75
+ try {
76
+ const res = await http.delete<ScrapeBrowserDeleteResponse>(
77
+ `/v2/scrape/${jobId}/interact`
78
+ );
79
+ if (res.status !== 200) throwForBadResponse(res, "stop interaction");
80
+ return res.data;
81
+ } catch (err: any) {
82
+ if (err?.isAxiosError) return normalizeAxiosError(err, "stop interaction");
83
+ throw err;
84
+ }
85
+ }
86
+
87
+ /** @deprecated Use interact(). */
88
+ export async function scrapeExecute(
89
+ http: HttpClient,
90
+ jobId: string,
91
+ args: ScrapeExecuteRequest
92
+ ): Promise<ScrapeExecuteResponse> {
93
+ return interact(http, jobId, args);
94
+ }
95
+
96
+ /** @deprecated Use stopInteraction(). */
97
+ export async function stopInteractiveBrowser(
98
+ http: HttpClient,
99
+ jobId: string
100
+ ): Promise<ScrapeBrowserDeleteResponse> {
101
+ return stopInteraction(http, jobId);
102
+ }
103
+
104
+ /** @deprecated Use stopInteraction(). */
105
+ export async function deleteScrapeBrowser(
106
+ http: HttpClient,
107
+ jobId: string
108
+ ): Promise<ScrapeBrowserDeleteResponse> {
109
+ return stopInteraction(http, jobId);
110
+ }
111
+
package/src/v2/types.ts CHANGED
@@ -51,13 +51,19 @@ export interface AttributesFormat extends Format {
51
51
  }>;
52
52
  }
53
53
 
54
+ export interface QueryFormat {
55
+ type: 'query';
56
+ prompt: string;
57
+ }
58
+
54
59
  export type FormatOption =
55
60
  | FormatString
56
61
  | Format
57
62
  | JsonFormat
58
63
  | ChangeTrackingFormat
59
64
  | ScreenshotFormat
60
- | AttributesFormat;
65
+ | AttributesFormat
66
+ | QueryFormat;
61
67
 
62
68
  export interface LocationConfig {
63
69
  country?: string;
@@ -157,6 +163,10 @@ export interface ScrapeOptions {
157
163
  maxAge?: number;
158
164
  minAge?: number;
159
165
  storeInCache?: boolean;
166
+ profile?: {
167
+ name: string;
168
+ saveChanges?: boolean;
169
+ };
160
170
  integration?: string;
161
171
  origin?: string;
162
172
  }
@@ -388,6 +398,7 @@ export interface Document {
388
398
  values: string[];
389
399
  }>;
390
400
  actions?: Record<string, unknown>;
401
+ answer?: string;
391
402
  warning?: string;
392
403
  changeTracking?: Record<string, unknown>;
393
404
  branding?: BrandingProfile;
@@ -704,6 +715,9 @@ export interface BrowserCreateResponse {
704
715
 
705
716
  export interface BrowserExecuteResponse {
706
717
  success: boolean;
718
+ liveViewUrl?: string;
719
+ interactiveLiveViewUrl?: string;
720
+ output?: string;
707
721
  stdout?: string;
708
722
  result?: string;
709
723
  stderr?: string;
@@ -719,6 +733,17 @@ export interface BrowserDeleteResponse {
719
733
  error?: string;
720
734
  }
721
735
 
736
+ export interface ScrapeExecuteRequest {
737
+ code?: string;
738
+ prompt?: string;
739
+ language?: "python" | "node" | "bash";
740
+ timeout?: number;
741
+ origin?: string;
742
+ }
743
+
744
+ export type ScrapeExecuteResponse = BrowserExecuteResponse;
745
+ export type ScrapeBrowserDeleteResponse = BrowserDeleteResponse;
746
+
722
747
  export interface BrowserSession {
723
748
  id: string;
724
749
  status: string;