@mendable/firecrawl-js 4.16.0 → 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 +22 -0
- package/dist/{chunk-OM7BT4QE.js → chunk-2UJCMTR4.js} +2 -2
- package/dist/index.cjs +78 -2
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +78 -2
- package/dist/{package-KOMYCNXX.js → package-UDBWBSIB.js} +1 -1
- package/package.json +2 -2
- package/src/__tests__/unit/v2/scrape-browser.unit.test.ts +104 -0
- package/src/v2/client.ts +48 -1
- package/src/v2/methods/scrape.ts +86 -1
- package/src/v2/types.ts +18 -0
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
@@ -119,6 +119,10 @@ interface ScrapeOptions {
|
|
|
119
119
|
maxAge?: number;
|
|
120
120
|
minAge?: number;
|
|
121
121
|
storeInCache?: boolean;
|
|
122
|
+
profile?: {
|
|
123
|
+
name: string;
|
|
124
|
+
saveChanges?: boolean;
|
|
125
|
+
};
|
|
122
126
|
integration?: string;
|
|
123
127
|
origin?: string;
|
|
124
128
|
}
|
|
@@ -578,6 +582,9 @@ interface BrowserCreateResponse {
|
|
|
578
582
|
}
|
|
579
583
|
interface BrowserExecuteResponse {
|
|
580
584
|
success: boolean;
|
|
585
|
+
liveViewUrl?: string;
|
|
586
|
+
interactiveLiveViewUrl?: string;
|
|
587
|
+
output?: string;
|
|
581
588
|
stdout?: string;
|
|
582
589
|
result?: string;
|
|
583
590
|
stderr?: string;
|
|
@@ -591,6 +598,15 @@ interface BrowserDeleteResponse {
|
|
|
591
598
|
creditsBilled?: number;
|
|
592
599
|
error?: string;
|
|
593
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;
|
|
594
610
|
interface BrowserSession {
|
|
595
611
|
id: string;
|
|
596
612
|
status: string;
|
|
@@ -753,6 +769,30 @@ declare class FirecrawlClient {
|
|
|
753
769
|
json?: InferredJsonFromOptions<Opts>;
|
|
754
770
|
}>;
|
|
755
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>;
|
|
756
796
|
/**
|
|
757
797
|
* Search the web and optionally scrape each result.
|
|
758
798
|
* @param query Search query string.
|
|
@@ -1849,4 +1889,4 @@ declare class Firecrawl extends FirecrawlClient {
|
|
|
1849
1889
|
get v1(): FirecrawlApp;
|
|
1850
1890
|
}
|
|
1851
1891
|
|
|
1852
|
-
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 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
|
@@ -119,6 +119,10 @@ interface ScrapeOptions {
|
|
|
119
119
|
maxAge?: number;
|
|
120
120
|
minAge?: number;
|
|
121
121
|
storeInCache?: boolean;
|
|
122
|
+
profile?: {
|
|
123
|
+
name: string;
|
|
124
|
+
saveChanges?: boolean;
|
|
125
|
+
};
|
|
122
126
|
integration?: string;
|
|
123
127
|
origin?: string;
|
|
124
128
|
}
|
|
@@ -578,6 +582,9 @@ interface BrowserCreateResponse {
|
|
|
578
582
|
}
|
|
579
583
|
interface BrowserExecuteResponse {
|
|
580
584
|
success: boolean;
|
|
585
|
+
liveViewUrl?: string;
|
|
586
|
+
interactiveLiveViewUrl?: string;
|
|
587
|
+
output?: string;
|
|
581
588
|
stdout?: string;
|
|
582
589
|
result?: string;
|
|
583
590
|
stderr?: string;
|
|
@@ -591,6 +598,15 @@ interface BrowserDeleteResponse {
|
|
|
591
598
|
creditsBilled?: number;
|
|
592
599
|
error?: string;
|
|
593
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;
|
|
594
610
|
interface BrowserSession {
|
|
595
611
|
id: string;
|
|
596
612
|
status: string;
|
|
@@ -753,6 +769,30 @@ declare class FirecrawlClient {
|
|
|
753
769
|
json?: InferredJsonFromOptions<Opts>;
|
|
754
770
|
}>;
|
|
755
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>;
|
|
756
796
|
/**
|
|
757
797
|
* Search the web and optionally scrape each result.
|
|
758
798
|
* @param query Search query string.
|
|
@@ -1849,4 +1889,4 @@ declare class Firecrawl extends FirecrawlClient {
|
|
|
1849
1889
|
get v1(): FirecrawlApp;
|
|
1850
1890
|
}
|
|
1851
1891
|
|
|
1852
|
-
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 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-
|
|
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-
|
|
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);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mendable/firecrawl-js",
|
|
3
|
-
"version": "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.
|
|
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 {
|
|
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
|
/**
|
package/src/v2/methods/scrape.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
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
|
@@ -163,6 +163,10 @@ export interface ScrapeOptions {
|
|
|
163
163
|
maxAge?: number;
|
|
164
164
|
minAge?: number;
|
|
165
165
|
storeInCache?: boolean;
|
|
166
|
+
profile?: {
|
|
167
|
+
name: string;
|
|
168
|
+
saveChanges?: boolean;
|
|
169
|
+
};
|
|
166
170
|
integration?: string;
|
|
167
171
|
origin?: string;
|
|
168
172
|
}
|
|
@@ -711,6 +715,9 @@ export interface BrowserCreateResponse {
|
|
|
711
715
|
|
|
712
716
|
export interface BrowserExecuteResponse {
|
|
713
717
|
success: boolean;
|
|
718
|
+
liveViewUrl?: string;
|
|
719
|
+
interactiveLiveViewUrl?: string;
|
|
720
|
+
output?: string;
|
|
714
721
|
stdout?: string;
|
|
715
722
|
result?: string;
|
|
716
723
|
stderr?: string;
|
|
@@ -726,6 +733,17 @@ export interface BrowserDeleteResponse {
|
|
|
726
733
|
error?: string;
|
|
727
734
|
}
|
|
728
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
|
+
|
|
729
747
|
export interface BrowserSession {
|
|
730
748
|
id: string;
|
|
731
749
|
status: string;
|