@upcrawl/sdk 1.3.0 → 1.4.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
@@ -148,6 +148,41 @@ const result = await Upcrawl.generatePdfFromUrl({
148
148
  console.log(result.url); // Download URL for the PDF
149
149
  ```
150
150
 
151
+ ### Execute Code
152
+
153
+ Run code in an isolated sandbox environment:
154
+
155
+ ```typescript
156
+ const result = await Upcrawl.executeCode({
157
+ code: 'print("Hello, World!")',
158
+ language: 'python'
159
+ });
160
+
161
+ console.log(result.stdout); // "Hello, World!\n"
162
+ console.log(result.exitCode); // 0
163
+ console.log(result.executionTimeMs); // 95.23
164
+ console.log(result.memoryUsageMb); // 8.45
165
+ ```
166
+
167
+ Each execution runs in its own isolated subprocess inside a Kata micro-VM with no network access. Code is cleaned up immediately after execution.
168
+
169
+ ```typescript
170
+ // Multi-line code with imports
171
+ const result = await Upcrawl.executeCode({
172
+ code: `
173
+ import json
174
+ data = {"name": "Upcrawl", "version": 1}
175
+ print(json.dumps(data, indent=2))
176
+ `
177
+ });
178
+
179
+ console.log(result.stdout);
180
+ // {
181
+ // "name": "Upcrawl",
182
+ // "version": 1
183
+ // }
184
+ ```
185
+
151
186
  ### Domain Filtering
152
187
 
153
188
  Filter search results by domain:
@@ -249,7 +284,9 @@ import Upcrawl, {
249
284
  BatchScrapeOptions,
250
285
  BatchScrapeResponse,
251
286
  GeneratePdfOptions,
252
- PdfResponse
287
+ PdfResponse,
288
+ ExecuteCodeOptions,
289
+ ExecuteCodeResponse
253
290
  } from '@upcrawl/sdk';
254
291
 
255
292
  const options: ScrapeOptions = {
@@ -275,6 +312,7 @@ const result: ScrapeResponse = await Upcrawl.scrape(options);
275
312
  | `Upcrawl.search(options)` | Search the web |
276
313
  | `Upcrawl.generatePdf(options)` | Generate PDF from HTML |
277
314
  | `Upcrawl.generatePdfFromUrl(options)` | Generate PDF from a URL |
315
+ | `Upcrawl.executeCode(options)` | Execute code in an isolated sandbox |
278
316
 
279
317
  ### Scrape Options
280
318
 
@@ -323,6 +361,25 @@ const result: ScrapeResponse = await Upcrawl.scrape(options);
323
361
  | `printBackground` | `boolean` | Print background graphics |
324
362
  | `timeoutMs` | `number` | Timeout (5000-120000) |
325
363
 
364
+ ### Execute Code Options
365
+
366
+ | Option | Type | Description |
367
+ |--------|------|-------------|
368
+ | `code` | `string` | Code to execute (required) |
369
+ | `language` | `'python'` | Language runtime (default: python) |
370
+
371
+ ### Execute Code Response
372
+
373
+ | Field | Type | Description |
374
+ |-------|------|-------------|
375
+ | `stdout` | `string` | Standard output |
376
+ | `stderr` | `string` | Standard error |
377
+ | `exitCode` | `number` | Exit code (0 = success, 124 = timeout) |
378
+ | `executionTimeMs` | `number` | Execution time in milliseconds |
379
+ | `timedOut` | `boolean` | Whether execution timed out |
380
+ | `memoryUsageMb` | `number` | Peak memory usage in MB |
381
+ | `cost` | `number` | Cost in USD |
382
+
326
383
  ## License
327
384
 
328
385
  MIT
package/dist/index.d.mts CHANGED
@@ -1,3 +1,5 @@
1
+ import { AxiosInstance } from 'axios';
2
+
1
3
  /**
2
4
  * Upcrawl SDK Types
3
5
  * Type definitions for all API requests and responses
@@ -231,6 +233,96 @@ declare class UpcrawlError extends Error {
231
233
  readonly code: string;
232
234
  constructor(message: string, status: number, code?: string);
233
235
  }
236
+ interface CreateBrowserSessionOptions {
237
+ /** Browser viewport width (800-3840). Defaults to 1280 */
238
+ width?: number;
239
+ /** Browser viewport height (600-2160). Defaults to 720 */
240
+ height?: number;
241
+ /** Run browser in headless mode. Defaults to true */
242
+ headless?: boolean;
243
+ }
244
+ interface BrowserSession {
245
+ /** Unique session identifier */
246
+ sessionId: string;
247
+ /** WebSocket URL for connecting with Playwright/Puppeteer */
248
+ wsEndpoint: string;
249
+ /** VNC URL for viewing the browser (if available) */
250
+ vncUrl: string | null;
251
+ /** Affinity cookie for sticky session routing (format: SCRAPER_AFFINITY=xxx) - extracted from response headers */
252
+ affinityCookie?: string;
253
+ /** Session creation timestamp */
254
+ createdAt: Date;
255
+ /** Browser viewport width */
256
+ width: number;
257
+ /** Browser viewport height */
258
+ height: number;
259
+ }
260
+
261
+ /**
262
+ * Upcrawl Browser Namespace
263
+ * Manage browser sessions for remote control with Playwright/Puppeteer
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * import Upcrawl from '@upcrawl/sdk';
268
+ * import playwright from 'playwright-core';
269
+ *
270
+ * const upcrawl = new Upcrawl('uc-your-api-key');
271
+ *
272
+ * // Create a browser session
273
+ * const session = await upcrawl.browser.create({
274
+ * width: 1280,
275
+ * height: 720,
276
+ * headless: true
277
+ * });
278
+ *
279
+ * // Connect with Playwright
280
+ * const browser = await playwright.connect(session.wsEndpoint);
281
+ * const page = await browser.newPage();
282
+ * await page.goto('https://example.com');
283
+ *
284
+ * // Close the session when done
285
+ * await upcrawl.browser.close(session.sessionId);
286
+ * ```
287
+ */
288
+
289
+ declare class Browser {
290
+ private createClient;
291
+ constructor(createClient: () => AxiosInstance);
292
+ /**
293
+ * Create a new browser session for remote control
294
+ * @param options - Session options including viewport size and headless mode
295
+ * @returns Promise with session details including WebSocket URL
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * const session = await upcrawl.browser.create({
300
+ * width: 1280,
301
+ * height: 720,
302
+ * headless: true
303
+ * });
304
+ *
305
+ * console.log(session.wsEndpoint); // WebSocket URL for Playwright
306
+ * console.log(session.vncUrl); // VNC URL for viewing (if available)
307
+ * ```
308
+ */
309
+ create(options?: CreateBrowserSessionOptions): Promise<BrowserSession>;
310
+ /**
311
+ * Close a browser session
312
+ * @param sessionId - The session ID to close
313
+ * @returns Promise that resolves when session is closed
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * await upcrawl.browser.close(session.sessionId);
318
+ * ```
319
+ */
320
+ close(sessionId: string): Promise<void>;
321
+ /**
322
+ * Handle API errors and convert to UpcrawlError
323
+ */
324
+ private handleError;
325
+ }
234
326
 
235
327
  /**
236
328
  * Upcrawl API Client
@@ -525,10 +617,27 @@ declare const Upcrawl: {
525
617
  * @returns Promise with execution response (stdout, stderr, exit code, memory usage)
526
618
  */
527
619
  readonly executeCode: typeof executeCode;
620
+ /**
621
+ * Browser session management
622
+ * Create and manage browser sessions for remote control with Playwright/Puppeteer
623
+ *
624
+ * @example
625
+ * ```typescript
626
+ * const session = await Upcrawl.browser.create({
627
+ * width: 1280,
628
+ * height: 720,
629
+ * headless: true
630
+ * });
631
+ *
632
+ * const browser = await playwright.connect(session.wsEndpoint);
633
+ * await upcrawl.browser.close(session.sessionId);
634
+ * ```
635
+ */
636
+ readonly browser: Browser;
528
637
  /**
529
638
  * Error class for Upcrawl API errors
530
639
  */
531
640
  readonly UpcrawlError: typeof UpcrawlError;
532
641
  };
533
642
 
534
- export { type BatchScrapeOptions, type BatchScrapeResponse, type ExecuteCodeOptions, type ExecuteCodeResponse, type GeneratePdfFromUrlOptions, type GeneratePdfOptions, type PdfMargin, type PdfResponse, type ScrapeMetadata, type ScrapeOptions, type ScrapeResponse, type SearchOptions, type SearchResponse, type SearchResultItem, type SearchResultWeb, type SummaryQuery, type UpcrawlConfig, UpcrawlError, type UpcrawlErrorResponse, batchScrape, configure, Upcrawl as default, executeCode, generatePdf, generatePdfFromUrl, getConfig, resetConfig, scrape, search, setApiKey, setBaseUrl, setTimeout };
643
+ export { type BatchScrapeOptions, type BatchScrapeResponse, Browser, type BrowserSession, type CreateBrowserSessionOptions, type ExecuteCodeOptions, type ExecuteCodeResponse, type GeneratePdfFromUrlOptions, type GeneratePdfOptions, type PdfMargin, type PdfResponse, type ScrapeMetadata, type ScrapeOptions, type ScrapeResponse, type SearchOptions, type SearchResponse, type SearchResultItem, type SearchResultWeb, type SummaryQuery, type UpcrawlConfig, UpcrawlError, type UpcrawlErrorResponse, batchScrape, configure, Upcrawl as default, executeCode, generatePdf, generatePdfFromUrl, getConfig, resetConfig, scrape, search, setApiKey, setBaseUrl, setTimeout };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { AxiosInstance } from 'axios';
2
+
1
3
  /**
2
4
  * Upcrawl SDK Types
3
5
  * Type definitions for all API requests and responses
@@ -231,6 +233,96 @@ declare class UpcrawlError extends Error {
231
233
  readonly code: string;
232
234
  constructor(message: string, status: number, code?: string);
233
235
  }
236
+ interface CreateBrowserSessionOptions {
237
+ /** Browser viewport width (800-3840). Defaults to 1280 */
238
+ width?: number;
239
+ /** Browser viewport height (600-2160). Defaults to 720 */
240
+ height?: number;
241
+ /** Run browser in headless mode. Defaults to true */
242
+ headless?: boolean;
243
+ }
244
+ interface BrowserSession {
245
+ /** Unique session identifier */
246
+ sessionId: string;
247
+ /** WebSocket URL for connecting with Playwright/Puppeteer */
248
+ wsEndpoint: string;
249
+ /** VNC URL for viewing the browser (if available) */
250
+ vncUrl: string | null;
251
+ /** Affinity cookie for sticky session routing (format: SCRAPER_AFFINITY=xxx) - extracted from response headers */
252
+ affinityCookie?: string;
253
+ /** Session creation timestamp */
254
+ createdAt: Date;
255
+ /** Browser viewport width */
256
+ width: number;
257
+ /** Browser viewport height */
258
+ height: number;
259
+ }
260
+
261
+ /**
262
+ * Upcrawl Browser Namespace
263
+ * Manage browser sessions for remote control with Playwright/Puppeteer
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * import Upcrawl from '@upcrawl/sdk';
268
+ * import playwright from 'playwright-core';
269
+ *
270
+ * const upcrawl = new Upcrawl('uc-your-api-key');
271
+ *
272
+ * // Create a browser session
273
+ * const session = await upcrawl.browser.create({
274
+ * width: 1280,
275
+ * height: 720,
276
+ * headless: true
277
+ * });
278
+ *
279
+ * // Connect with Playwright
280
+ * const browser = await playwright.connect(session.wsEndpoint);
281
+ * const page = await browser.newPage();
282
+ * await page.goto('https://example.com');
283
+ *
284
+ * // Close the session when done
285
+ * await upcrawl.browser.close(session.sessionId);
286
+ * ```
287
+ */
288
+
289
+ declare class Browser {
290
+ private createClient;
291
+ constructor(createClient: () => AxiosInstance);
292
+ /**
293
+ * Create a new browser session for remote control
294
+ * @param options - Session options including viewport size and headless mode
295
+ * @returns Promise with session details including WebSocket URL
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * const session = await upcrawl.browser.create({
300
+ * width: 1280,
301
+ * height: 720,
302
+ * headless: true
303
+ * });
304
+ *
305
+ * console.log(session.wsEndpoint); // WebSocket URL for Playwright
306
+ * console.log(session.vncUrl); // VNC URL for viewing (if available)
307
+ * ```
308
+ */
309
+ create(options?: CreateBrowserSessionOptions): Promise<BrowserSession>;
310
+ /**
311
+ * Close a browser session
312
+ * @param sessionId - The session ID to close
313
+ * @returns Promise that resolves when session is closed
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * await upcrawl.browser.close(session.sessionId);
318
+ * ```
319
+ */
320
+ close(sessionId: string): Promise<void>;
321
+ /**
322
+ * Handle API errors and convert to UpcrawlError
323
+ */
324
+ private handleError;
325
+ }
234
326
 
235
327
  /**
236
328
  * Upcrawl API Client
@@ -525,10 +617,27 @@ declare const Upcrawl: {
525
617
  * @returns Promise with execution response (stdout, stderr, exit code, memory usage)
526
618
  */
527
619
  readonly executeCode: typeof executeCode;
620
+ /**
621
+ * Browser session management
622
+ * Create and manage browser sessions for remote control with Playwright/Puppeteer
623
+ *
624
+ * @example
625
+ * ```typescript
626
+ * const session = await Upcrawl.browser.create({
627
+ * width: 1280,
628
+ * height: 720,
629
+ * headless: true
630
+ * });
631
+ *
632
+ * const browser = await playwright.connect(session.wsEndpoint);
633
+ * await upcrawl.browser.close(session.sessionId);
634
+ * ```
635
+ */
636
+ readonly browser: Browser;
528
637
  /**
529
638
  * Error class for Upcrawl API errors
530
639
  */
531
640
  readonly UpcrawlError: typeof UpcrawlError;
532
641
  };
533
642
 
534
- export { type BatchScrapeOptions, type BatchScrapeResponse, type ExecuteCodeOptions, type ExecuteCodeResponse, type GeneratePdfFromUrlOptions, type GeneratePdfOptions, type PdfMargin, type PdfResponse, type ScrapeMetadata, type ScrapeOptions, type ScrapeResponse, type SearchOptions, type SearchResponse, type SearchResultItem, type SearchResultWeb, type SummaryQuery, type UpcrawlConfig, UpcrawlError, type UpcrawlErrorResponse, batchScrape, configure, Upcrawl as default, executeCode, generatePdf, generatePdfFromUrl, getConfig, resetConfig, scrape, search, setApiKey, setBaseUrl, setTimeout };
643
+ export { type BatchScrapeOptions, type BatchScrapeResponse, Browser, type BrowserSession, type CreateBrowserSessionOptions, type ExecuteCodeOptions, type ExecuteCodeResponse, type GeneratePdfFromUrlOptions, type GeneratePdfOptions, type PdfMargin, type PdfResponse, type ScrapeMetadata, type ScrapeOptions, type ScrapeResponse, type SearchOptions, type SearchResponse, type SearchResultItem, type SearchResultWeb, type SummaryQuery, type UpcrawlConfig, UpcrawlError, type UpcrawlErrorResponse, batchScrape, configure, Upcrawl as default, executeCode, generatePdf, generatePdfFromUrl, getConfig, resetConfig, scrape, search, setApiKey, setBaseUrl, setTimeout };
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ Browser: () => Browser,
33
34
  UpcrawlError: () => UpcrawlError,
34
35
  batchScrape: () => batchScrape,
35
36
  configure: () => configure,
@@ -57,6 +58,104 @@ var UpcrawlError = class extends Error {
57
58
  }
58
59
  };
59
60
 
61
+ // src/browser.ts
62
+ var Browser = class {
63
+ constructor(createClient2) {
64
+ this.createClient = createClient2;
65
+ }
66
+ /**
67
+ * Create a new browser session for remote control
68
+ * @param options - Session options including viewport size and headless mode
69
+ * @returns Promise with session details including WebSocket URL
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const session = await upcrawl.browser.create({
74
+ * width: 1280,
75
+ * height: 720,
76
+ * headless: true
77
+ * });
78
+ *
79
+ * console.log(session.wsEndpoint); // WebSocket URL for Playwright
80
+ * console.log(session.vncUrl); // VNC URL for viewing (if available)
81
+ * ```
82
+ */
83
+ async create(options) {
84
+ try {
85
+ const client = this.createClient();
86
+ const response = await client.post("/browser/session", {
87
+ width: options?.width ?? 1280,
88
+ height: options?.height ?? 720,
89
+ headless: options?.headless ?? true
90
+ });
91
+ const setCookieHeaders = response.headers["set-cookie"] || [];
92
+ const affinityCookie = setCookieHeaders.map((c) => c.split(";")[0]).find((c) => c.startsWith("SCRAPER_AFFINITY="));
93
+ return {
94
+ sessionId: response.data.sessionId,
95
+ wsEndpoint: response.data.wsUrl,
96
+ vncUrl: response.data.vncUrl,
97
+ affinityCookie: affinityCookie || void 0,
98
+ createdAt: new Date(response.data.createdAt),
99
+ width: response.data.width,
100
+ height: response.data.height
101
+ };
102
+ } catch (error) {
103
+ this.handleError(error);
104
+ }
105
+ }
106
+ /**
107
+ * Close a browser session
108
+ * @param sessionId - The session ID to close
109
+ * @returns Promise that resolves when session is closed
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * await upcrawl.browser.close(session.sessionId);
114
+ * ```
115
+ */
116
+ async close(sessionId) {
117
+ try {
118
+ const client = this.createClient();
119
+ await client.delete(`/browser/session/${sessionId}`);
120
+ } catch (error) {
121
+ this.handleError(error);
122
+ }
123
+ }
124
+ /**
125
+ * Handle API errors and convert to UpcrawlError
126
+ */
127
+ handleError(error) {
128
+ if (error && typeof error === "object" && "response" in error) {
129
+ const axiosError = error;
130
+ const status = axiosError.response?.status || 500;
131
+ const data = axiosError.response?.data;
132
+ if (data?.error) {
133
+ throw new UpcrawlError(data.error.message || "Unknown error", status, data.error.code || "UNKNOWN_ERROR");
134
+ }
135
+ switch (status) {
136
+ case 401:
137
+ throw new UpcrawlError("Invalid or missing API key", 401, "UNAUTHORIZED");
138
+ case 404:
139
+ throw new UpcrawlError("Session not found", 404, "NOT_FOUND");
140
+ case 429:
141
+ throw new UpcrawlError("Rate limit exceeded", 429, "RATE_LIMIT_EXCEEDED");
142
+ case 503:
143
+ throw new UpcrawlError("No browser slots available", 503, "SERVICE_UNAVAILABLE");
144
+ default:
145
+ throw new UpcrawlError(axiosError.message || "An unknown error occurred", status, "UNKNOWN_ERROR");
146
+ }
147
+ }
148
+ if (error instanceof UpcrawlError) {
149
+ throw error;
150
+ }
151
+ throw new UpcrawlError(
152
+ error instanceof Error ? error.message : "An unknown error occurred",
153
+ 500,
154
+ "UNKNOWN_ERROR"
155
+ );
156
+ }
157
+ };
158
+
60
159
  // src/client.ts
61
160
  var import_axios = __toESM(require("axios"));
62
161
  var DEFAULT_BASE_URL = "https://api.upcrawl.dev/api/v1";
@@ -279,6 +378,23 @@ var Upcrawl = {
279
378
  * @returns Promise with execution response (stdout, stderr, exit code, memory usage)
280
379
  */
281
380
  executeCode,
381
+ /**
382
+ * Browser session management
383
+ * Create and manage browser sessions for remote control with Playwright/Puppeteer
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * const session = await Upcrawl.browser.create({
388
+ * width: 1280,
389
+ * height: 720,
390
+ * headless: true
391
+ * });
392
+ *
393
+ * const browser = await playwright.connect(session.wsEndpoint);
394
+ * await upcrawl.browser.close(session.sessionId);
395
+ * ```
396
+ */
397
+ browser: new Browser(createClient),
282
398
  /**
283
399
  * Error class for Upcrawl API errors
284
400
  */
@@ -287,6 +403,7 @@ var Upcrawl = {
287
403
  var index_default = Upcrawl;
288
404
  // Annotate the CommonJS export names for ESM import in node:
289
405
  0 && (module.exports = {
406
+ Browser,
290
407
  UpcrawlError,
291
408
  batchScrape,
292
409
  configure,
package/dist/index.mjs CHANGED
@@ -8,6 +8,104 @@ var UpcrawlError = class extends Error {
8
8
  }
9
9
  };
10
10
 
11
+ // src/browser.ts
12
+ var Browser = class {
13
+ constructor(createClient2) {
14
+ this.createClient = createClient2;
15
+ }
16
+ /**
17
+ * Create a new browser session for remote control
18
+ * @param options - Session options including viewport size and headless mode
19
+ * @returns Promise with session details including WebSocket URL
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const session = await upcrawl.browser.create({
24
+ * width: 1280,
25
+ * height: 720,
26
+ * headless: true
27
+ * });
28
+ *
29
+ * console.log(session.wsEndpoint); // WebSocket URL for Playwright
30
+ * console.log(session.vncUrl); // VNC URL for viewing (if available)
31
+ * ```
32
+ */
33
+ async create(options) {
34
+ try {
35
+ const client = this.createClient();
36
+ const response = await client.post("/browser/session", {
37
+ width: options?.width ?? 1280,
38
+ height: options?.height ?? 720,
39
+ headless: options?.headless ?? true
40
+ });
41
+ const setCookieHeaders = response.headers["set-cookie"] || [];
42
+ const affinityCookie = setCookieHeaders.map((c) => c.split(";")[0]).find((c) => c.startsWith("SCRAPER_AFFINITY="));
43
+ return {
44
+ sessionId: response.data.sessionId,
45
+ wsEndpoint: response.data.wsUrl,
46
+ vncUrl: response.data.vncUrl,
47
+ affinityCookie: affinityCookie || void 0,
48
+ createdAt: new Date(response.data.createdAt),
49
+ width: response.data.width,
50
+ height: response.data.height
51
+ };
52
+ } catch (error) {
53
+ this.handleError(error);
54
+ }
55
+ }
56
+ /**
57
+ * Close a browser session
58
+ * @param sessionId - The session ID to close
59
+ * @returns Promise that resolves when session is closed
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * await upcrawl.browser.close(session.sessionId);
64
+ * ```
65
+ */
66
+ async close(sessionId) {
67
+ try {
68
+ const client = this.createClient();
69
+ await client.delete(`/browser/session/${sessionId}`);
70
+ } catch (error) {
71
+ this.handleError(error);
72
+ }
73
+ }
74
+ /**
75
+ * Handle API errors and convert to UpcrawlError
76
+ */
77
+ handleError(error) {
78
+ if (error && typeof error === "object" && "response" in error) {
79
+ const axiosError = error;
80
+ const status = axiosError.response?.status || 500;
81
+ const data = axiosError.response?.data;
82
+ if (data?.error) {
83
+ throw new UpcrawlError(data.error.message || "Unknown error", status, data.error.code || "UNKNOWN_ERROR");
84
+ }
85
+ switch (status) {
86
+ case 401:
87
+ throw new UpcrawlError("Invalid or missing API key", 401, "UNAUTHORIZED");
88
+ case 404:
89
+ throw new UpcrawlError("Session not found", 404, "NOT_FOUND");
90
+ case 429:
91
+ throw new UpcrawlError("Rate limit exceeded", 429, "RATE_LIMIT_EXCEEDED");
92
+ case 503:
93
+ throw new UpcrawlError("No browser slots available", 503, "SERVICE_UNAVAILABLE");
94
+ default:
95
+ throw new UpcrawlError(axiosError.message || "An unknown error occurred", status, "UNKNOWN_ERROR");
96
+ }
97
+ }
98
+ if (error instanceof UpcrawlError) {
99
+ throw error;
100
+ }
101
+ throw new UpcrawlError(
102
+ error instanceof Error ? error.message : "An unknown error occurred",
103
+ 500,
104
+ "UNKNOWN_ERROR"
105
+ );
106
+ }
107
+ };
108
+
11
109
  // src/client.ts
12
110
  import axios from "axios";
13
111
  var DEFAULT_BASE_URL = "https://api.upcrawl.dev/api/v1";
@@ -230,6 +328,23 @@ var Upcrawl = {
230
328
  * @returns Promise with execution response (stdout, stderr, exit code, memory usage)
231
329
  */
232
330
  executeCode,
331
+ /**
332
+ * Browser session management
333
+ * Create and manage browser sessions for remote control with Playwright/Puppeteer
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * const session = await Upcrawl.browser.create({
338
+ * width: 1280,
339
+ * height: 720,
340
+ * headless: true
341
+ * });
342
+ *
343
+ * const browser = await playwright.connect(session.wsEndpoint);
344
+ * await upcrawl.browser.close(session.sessionId);
345
+ * ```
346
+ */
347
+ browser: new Browser(createClient),
233
348
  /**
234
349
  * Error class for Upcrawl API errors
235
350
  */
@@ -237,6 +352,7 @@ var Upcrawl = {
237
352
  };
238
353
  var index_default = Upcrawl;
239
354
  export {
355
+ Browser,
240
356
  UpcrawlError,
241
357
  batchScrape,
242
358
  configure,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upcrawl/sdk",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -43,7 +43,8 @@
43
43
  "url": "https://github.com/upcrawl/upcrawl-js/issues"
44
44
  },
45
45
  "dependencies": {
46
- "axios": "^1.6.0"
46
+ "axios": "^1.6.0",
47
+ "react-vnc": "^3.2.0"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@types/node": "^20.10.0",