@monostate/browsernative-client 1.2.0 → 2.0.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
@@ -1,461 +1,129 @@
1
1
  # @monostate/browsernative-client
2
2
 
3
- > **Official JavaScript/TypeScript client for Browser Native API**
3
+ > JavaScript/TypeScript client for the Browser Native web scraping API
4
4
 
5
- [![npm version](https://badge.fury.io/js/%40monostate%2Fbrowsernative-client.svg)](https://badge.fury.io/js/%40monostate%2Fbrowsernative-client)
5
+ [![npm](https://img.shields.io/npm/v/@monostate/browsernative-client.svg)](https://www.npmjs.com/package/@monostate/browsernative-client)
6
+ [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/monostate/browsernative-client/blob/main/LICENSE)
6
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
- [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
8
8
 
9
- A lightweight, fast, and reliable client for the Browser Native web scraping and content extraction API. Works in browsers, Node.js, Deno, and edge environments.
9
+ Zero-dependency client for scraping, screenshots, and AI analysis. Works in Node.js, browsers, and edge environments.
10
10
 
11
- ## 🚀 Quick Start
12
-
13
- ### Installation
11
+ ## Install
14
12
 
15
13
  ```bash
16
14
  npm install @monostate/browsernative-client
17
- # or
18
- yarn add @monostate/browsernative-client
19
- # or
20
- pnpm add @monostate/browsernative-client
21
15
  ```
22
16
 
23
- ### Get Your API Key
24
-
25
- 1. Sign up at [bnca.monostate.ai](https://bnca.monostate.ai)
26
- 2. Get your API key from the dashboard
27
- 3. Start scraping!
17
+ Get an API key at [bnca.monostate.ai](https://bnca.monostate.ai).
28
18
 
29
- ### Basic Usage
19
+ ## Usage
30
20
 
31
21
  ```javascript
32
22
  import { BrowserNativeClient } from '@monostate/browsernative-client';
33
23
 
34
24
  const client = new BrowserNativeClient('your-api-key');
35
25
 
36
- // Scrape any website
26
+ // Scrape
37
27
  const result = await client.scrape('https://example.com');
38
- console.log(result.data.title);
39
- console.log(result.data.content);
40
-
41
- // Quick screenshot capture (optimized for speed)
42
- const screenshot = await client.quickshot('https://example.com');
43
- console.log(screenshot.screenshot); // Base64 image
44
- ```
45
-
46
- ### Quick Functions
47
-
48
- ```javascript
49
- import { quickScrape, quickScreenshot, quickShot, quickAnalyze } from '@monostate/browsernative-client';
50
-
51
- // One-line scraping
52
- const content = await quickScrape('https://example.com', 'your-api-key');
53
-
54
- // Take a screenshot (with content extraction)
55
- const screenshot = await quickScreenshot('https://example.com', 'your-api-key');
56
-
57
- // Quick screenshot only (fastest option)
58
- const quickScreenshot = await quickShot('https://example.com', 'your-api-key');
59
-
60
- // AI-powered analysis
61
- const analysis = await quickAnalyze(
62
- 'https://news.ycombinator.com',
63
- 'What are the top 3 trending topics?',
64
- 'your-api-key'
65
- );
66
- ```
67
-
68
- ## 📋 API Reference
69
-
70
- ### Client Initialization
71
-
72
- ```javascript
73
- const client = new BrowserNativeClient(apiKey, options);
74
- ```
75
-
76
- **Options:**
77
- - `baseUrl` (string): API base URL (default: `https://bnca-api.fly.dev`)
78
- - `timeout` (number): Request timeout in ms (default: `30000`)
79
- - `retries` (number): Number of retry attempts (default: `2`)
80
- - `verbose` (boolean): Enable logging (default: `false`)
81
-
82
- ### Methods
83
-
84
- #### `client.scrape(url, options)`
85
-
86
- Extract structured content from any webpage.
87
-
88
- ```javascript
89
- const result = await client.scrape('https://example.com', {
90
- includeScreenshot: true,
91
- waitForSelector: '.main-content',
92
- extractMetadata: true,
93
- userAgent: 'Custom Bot 1.0'
94
- });
95
-
96
- console.log(result.data.title); // Page title
97
- console.log(result.data.content); // Main content
98
- console.log(result.data.metadata); // Meta tags, etc.
99
- console.log(result.screenshot); // Base64 image (if requested)
100
- console.log(result.method); // Scraping method used
101
- ```
102
-
103
- **Options:**
104
- - `includeScreenshot` (boolean): Include page screenshot
105
- - `waitForSelector` (string): CSS selector to wait for
106
- - `userAgent` (string): Custom user agent
107
- - `viewport` (object): `{ width: number, height: number }`
108
- - `extractMetadata` (boolean): Extract meta tags and structured data
109
-
110
- #### `client.screenshot(url, options)`
111
-
112
- Take high-quality screenshots of webpages with content extraction.
113
-
114
- ```javascript
115
- const result = await client.screenshot('https://example.com', {
116
- fullPage: true,
117
- format: 'png',
118
- viewport: { width: 1920, height: 1080 }
119
- });
120
-
121
- // Use the base64 image
122
- const img = `data:image/png;base64,${result.screenshot}`;
123
- ```
124
-
125
- **Options:**
126
- - `fullPage` (boolean): Capture full page scroll
127
- - `format` (string): `'png'`, `'jpeg'`, or `'webp'`
128
- - `quality` (number): JPEG quality (1-100)
129
- - All scrape options are also available
130
-
131
- #### `client.quickshot(url, options)`
132
-
133
- Optimized screenshot capture for maximum speed (no content extraction).
134
-
135
- ```javascript
136
- const result = await client.quickshot('https://example.com');
137
-
138
- // Returns screenshot immediately
139
- if (result.success && result.screenshot) {
140
- const img = result.screenshot; // Already includes data:image/png;base64,
141
- }
142
- ```
143
-
144
- **Benefits:**
145
- - 2-3x faster than regular screenshot
146
- - Optimized for visual capture only
147
- - Perfect for thumbnails and previews
148
-
149
- #### `client.analyze(url, question, options)`
150
-
151
- AI-powered content analysis and question answering.
152
-
153
- ```javascript
154
- const result = await client.analyze(
155
- 'https://techcrunch.com',
156
- 'What are the latest AI developments mentioned?',
157
- {
158
- language: 'en',
159
- style: 'detailed'
160
- }
161
- );
162
-
163
- console.log(result.analysis.answer); // AI response
164
- console.log(result.analysis.confidence); // Confidence score
165
- ```
166
-
167
- **Options:**
168
- - `language` (string): Response language (`'en'`, `'pt'`, `'es'`, `'fr'`, `'de'`, `'auto'`)
169
- - `style` (string): Response style (`'concise'`, `'detailed'`, `'technical'`)
170
- - All scrape options are also available
171
-
172
- #### `client.getUsage(days)`
173
-
174
- Get your account usage statistics.
175
-
176
- ```javascript
177
- const usage = await client.getUsage(30); // Last 30 days
178
-
179
- console.log(usage.data.monthlyTotal.totalRequests);
180
- console.log(usage.data.currentUsage);
181
- console.log(usage.data.usageLimit);
182
- ```
183
-
184
- #### `client.healthCheck()`
185
-
186
- Check API status and your account health.
187
-
188
- ```javascript
189
- const health = await client.healthCheck();
190
-
191
- console.log(health.data.status); // 'healthy', 'degraded', or 'unhealthy'
192
- console.log(health.data.services); // Service status breakdown
193
- ```
194
-
195
- ## 🌐 Framework Integration
196
-
197
- ### React Hook
198
-
199
- ```javascript
200
- // hooks/useBrowserNative.js
201
- import { useState } from 'react';
202
- import { BrowserNativeClient } from '@monostate/browsernative-client';
203
28
 
204
- export function useBrowserNative(apiKey) {
205
- const [loading, setLoading] = useState(false);
206
- const [data, setData] = useState(null);
207
- const [error, setError] = useState(null);
208
-
209
- const client = new BrowserNativeClient(apiKey);
210
-
211
- const scrape = async (url, options = {}) => {
212
- setLoading(true);
213
- setError(null);
214
-
215
- try {
216
- const result = await client.scrape(url, options);
217
- if (result.success) {
218
- setData(result.data);
219
- } else {
220
- setError(result.error);
221
- }
222
- } catch (err) {
223
- setError(err.message);
224
- } finally {
225
- setLoading(false);
226
- }
227
- };
228
-
229
- return { scrape, loading, data, error };
230
- }
231
- ```
29
+ // Force a specific scraping method
30
+ const result = await client.scrape('https://example.com', { method: 'lightpanda' });
232
31
 
233
- ### Vue Composable
32
+ // Screenshot
33
+ const screenshot = await client.screenshot('https://example.com');
234
34
 
235
- ```javascript
236
- // composables/useBrowserNative.js
237
- import { ref } from 'vue';
238
- import { BrowserNativeClient } from '@monostate/browsernative-client';
35
+ // Quick screenshot (faster, no content extraction)
36
+ const quick = await client.quickshot('https://example.com');
239
37
 
240
- export function useBrowserNative(apiKey) {
241
- const loading = ref(false);
242
- const data = ref(null);
243
- const error = ref(null);
244
-
245
- const client = new BrowserNativeClient(apiKey);
246
-
247
- const scrape = async (url, options = {}) => {
248
- loading.value = true;
249
- error.value = null;
250
-
251
- try {
252
- const result = await client.scrape(url, options);
253
- if (result.success) {
254
- data.value = result.data;
255
- } else {
256
- error.value = result.error;
257
- }
258
- } catch (err) {
259
- error.value = err.message;
260
- } finally {
261
- loading.value = false;
262
- }
263
- };
264
-
265
- return { scrape, loading, data, error };
266
- }
38
+ // AI Q&A
39
+ const analysis = await client.analyze('https://example.com', 'What is this site about?');
267
40
  ```
268
41
 
269
- ### Next.js API Route
42
+ ### Convenience functions
270
43
 
271
44
  ```javascript
272
- // pages/api/scrape.js
273
- import { BrowserNativeClient } from '@monostate/browsernative-client';
45
+ import { quickScrape, quickScreenshot, quickShot, quickAnalyze, bulkScrape } from '@monostate/browsernative-client';
274
46
 
275
- const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
276
-
277
- export default async function handler(req, res) {
278
- if (req.method !== 'POST') {
279
- return res.status(405).json({ error: 'Method not allowed' });
280
- }
281
-
282
- try {
283
- const { url, question } = req.body;
284
-
285
- let result;
286
- if (question) {
287
- result = await client.analyze(url, question);
288
- } else {
289
- result = await client.scrape(url);
290
- }
291
-
292
- res.status(200).json(result);
293
- } catch (error) {
294
- res.status(500).json({ error: error.message });
295
- }
296
- }
47
+ const content = await quickScrape('https://example.com', 'your-api-key');
48
+ const shot = await quickShot('https://example.com', 'your-api-key');
49
+ const answer = await quickAnalyze('https://example.com', 'What is this?', 'your-api-key');
297
50
  ```
298
51
 
299
- ### Express.js
52
+ ### Bulk scraping
300
53
 
301
54
  ```javascript
302
- import express from 'express';
303
- import { BrowserNativeClient } from '@monostate/browsernative-client';
55
+ const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
304
56
 
305
- const app = express();
306
- const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
307
-
308
- app.post('/scrape', async (req, res) => {
309
- try {
310
- const { url } = req.body;
311
- const result = await client.scrape(url);
312
- res.json(result);
313
- } catch (error) {
314
- res.status(500).json({ error: error.message });
315
- }
57
+ const { results, stats } = await client.bulkScrape(urls, {
58
+ concurrency: 5,
59
+ continueOnError: true,
60
+ progressCallback: (p) => console.log(`${p.percentage.toFixed(1)}%`),
316
61
  });
317
- ```
318
62
 
319
- ## 🔒 Environment Variables
320
-
321
- Create a `.env` file:
322
-
323
- ```bash
324
- BROWSER_NATIVE_API_KEY=your_api_key_here
63
+ console.log(`${stats.successful}/${stats.total} succeeded in ${stats.totalTime}ms`);
325
64
  ```
326
65
 
327
- Then use in your code:
66
+ ## API Reference
328
67
 
329
- ```javascript
330
- const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
331
- ```
332
-
333
- ## 📱 Browser Usage
334
-
335
- You can use this client directly in browsers, but be careful with API keys:
336
-
337
- ```html
338
- <!DOCTYPE html>
339
- <html>
340
- <head>
341
- <title>Browser Native Demo</title>
342
- </head>
343
- <body>
344
- <script type="module">
345
- import { BrowserNativeClient } from 'https://cdn.skypack.dev/@monostate/browsernative-client';
346
-
347
- // ⚠️ Never expose your API key in client-side code!
348
- // Use a proxy server or environment variables
349
- const client = new BrowserNativeClient(await getApiKeyFromServer());
350
-
351
- const result = await client.scrape('https://example.com');
352
- console.log(result);
353
- </script>
354
- </body>
355
- </html>
356
- ```
357
-
358
- **Security Note**: Never expose your API key in client-side code. Use a backend proxy or server-side rendering.
359
-
360
- ## ⚡ Performance Tips
361
-
362
- 1. **Reuse Client Instances**: Create one client instance and reuse it
363
- 2. **Enable Retries**: The client automatically retries failed requests
364
- 3. **Use Appropriate Timeouts**: Adjust timeout based on your use case
365
- 4. **Batch Requests**: Process multiple URLs concurrently
68
+ ### Client options
366
69
 
367
70
  ```javascript
368
71
  const client = new BrowserNativeClient(apiKey, {
369
- timeout: 45000, // Longer timeout for complex sites
370
- retries: 3, // More retries for reliability
371
- verbose: true // Enable logging for debugging
72
+ baseUrl: 'https://bnca-api.fly.dev', // API endpoint
73
+ timeout: 30000, // Request timeout (ms)
74
+ retries: 2, // Retry attempts
75
+ verbose: false, // Debug logging
372
76
  });
77
+ ```
373
78
 
374
- // Concurrent scraping
375
- const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
376
- const results = await Promise.all(
377
- urls.map(url => client.scrape(url))
378
- );
79
+ ### Methods
80
+
81
+ | Method | Description |
82
+ |--------|-------------|
83
+ | `scrape(url, opts?)` | Extract structured content |
84
+ | `screenshot(url, opts?)` | Screenshot with content extraction |
85
+ | `quickshot(url, opts?)` | Fast screenshot only |
86
+ | `analyze(url, question, opts?)` | AI-powered Q&A |
87
+ | `bulkScrape(urls, opts?)` | Scrape multiple URLs concurrently |
88
+ | `getUsage(days?)` | Account usage statistics |
89
+ | `healthCheck()` | API health status |
90
+
91
+ ### Scrape options
92
+
93
+ ```javascript
94
+ {
95
+ method: 'auto', // 'auto' | 'direct' | 'lightpanda' | 'puppeteer'
96
+ includeScreenshot: false,
97
+ waitForSelector: '.content',
98
+ userAgent: 'Custom Bot',
99
+ viewport: { width: 1920, height: 1080 },
100
+ extractMetadata: true,
101
+ }
379
102
  ```
380
103
 
381
- ## 🔧 Error Handling
104
+ ### Response shape
382
105
 
383
106
  ```javascript
384
- try {
385
- const result = await client.scrape(url);
386
-
387
- if (result.success) {
388
- console.log('Success:', result.data);
389
- } else {
390
- console.error('Scraping failed:', result.error);
391
- }
392
- } catch (error) {
393
- console.error('Request failed:', error.message);
107
+ {
108
+ success: true,
109
+ data: { title, content, metadata, ... },
110
+ responseTime: 1234,
111
+ attempt: 1,
394
112
  }
395
113
  ```
396
114
 
397
- Common error scenarios:
398
- - **Invalid API Key**: Check your API key and account status
399
- - **Rate Limited**: Upgrade your plan or reduce request frequency
400
- - **Timeout**: Increase timeout or try a simpler extraction method
401
- - **Invalid URL**: Ensure the URL is accessible and properly formatted
402
-
403
- ## 🚀 TypeScript Support
115
+ ## TypeScript
404
116
 
405
- Full TypeScript support with comprehensive type definitions:
117
+ Full type definitions included.
406
118
 
407
119
  ```typescript
408
- import { BrowserNativeClient, ScrapeResult, AnalyzeResult } from '@monostate/browsernative-client';
409
-
410
- const client: BrowserNativeClient = new BrowserNativeClient('your-api-key');
411
-
412
- const result: ScrapeResult = await client.scrape('https://example.com');
413
- const analysis: AnalyzeResult = await client.analyze(url, question);
120
+ import { BrowserNativeClient, ScrapeResult, BulkScrapeResult } from '@monostate/browsernative-client';
414
121
  ```
415
122
 
416
- ## 📊 Rate Limits
417
-
418
- | Plan | Requests/Month | Rate Limit |
419
- |------|----------------|------------|
420
- | **Free** | 1,000 | 10/minute |
421
- | **Starter** | 10,000 | 60/minute |
422
- | **Pro** | 100,000 | 300/minute |
423
- | **Enterprise** | Unlimited | Custom |
424
-
425
- ## 📋 Changelog
426
-
427
- ### v1.2.0 (Latest)
428
- - 🔧 **Timeout Improvements**: Enhanced timeout handling and request reliability
429
- - 📝 **Documentation Updates**: Comprehensive API documentation and examples
430
- - 🏷️ **Package Naming**: Proper package name consistency across all imports
431
- - ⚡ **Performance Optimizations**: Better error handling and response processing
432
- - 🌐 **Framework Integration**: Improved React, Vue, and Next.js examples
433
-
434
- ### v1.1.2
435
- - Bug fixes and stability improvements
436
- - Enhanced error handling
437
-
438
- ### v1.1.1
439
- - Initial TypeScript support
440
- - Basic API client functionality
441
-
442
- ## 🤝 Support
443
-
444
- - 📧 **Email**: [support@bnca.monostate.ai](mailto:support@bnca.monostate.ai)
445
- - 📖 **Documentation**: [bnca.monostate.ai/docs](https://bnca.monostate.ai/docs)
446
- - 🐛 **Issues**: [GitHub Issues](https://github.com/browsernative/client-sdk/issues)
447
- - 💬 **Discord**: [Join our community](https://discord.gg/browsernative)
448
-
449
- ## 📄 License
450
-
451
- MIT License - see [LICENSE](../../LICENSE) file for details.
452
-
453
- ---
454
-
455
- <div align="center">
123
+ ## Changelog
456
124
 
457
- **Built with ❤️ for developers who value speed and reliability**
125
+ See [CHANGELOG.md](./CHANGELOG.md).
458
126
 
459
- [🌐 Website](https://bnca.monostate.ai) | [📖 Docs](https://bnca.monostate.ai/docs) | [🚀 Get API Key](https://bnca.monostate.ai/signup)
127
+ ## License
460
128
 
461
- </div>
129
+ MIT
package/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  export interface ClientOptions {
6
- /** Base URL for the API (default: https://browsernative.monostate.ai) */
6
+ /** Base URL for the API (default: https://bnca-api.fly.dev) */
7
7
  baseUrl?: string;
8
8
  /** Request timeout in milliseconds (default: 30000) */
9
9
  timeout?: number;
@@ -14,6 +14,8 @@ export interface ClientOptions {
14
14
  }
15
15
 
16
16
  export interface ScrapeOptions {
17
+ /** Force a specific scraping method */
18
+ method?: 'auto' | 'direct' | 'lightpanda' | 'puppeteer';
17
19
  /** Include screenshot in the response */
18
20
  includeScreenshot?: boolean;
19
21
  /** Wait for specific selector before extracting content */
@@ -29,6 +31,26 @@ export interface ScrapeOptions {
29
31
  extractMetadata?: boolean;
30
32
  }
31
33
 
34
+ export interface BulkScrapeOptions extends ScrapeOptions {
35
+ /** Number of concurrent requests (default: 5) */
36
+ concurrency?: number;
37
+ /** Continue on error (default: true) */
38
+ continueOnError?: boolean;
39
+ /** Progress callback */
40
+ progressCallback?: (progress: { processed: number; total: number; percentage: number }) => void;
41
+ }
42
+
43
+ export interface BulkScrapeResult {
44
+ results: Array<ScrapeResult & { url: string }>;
45
+ stats: {
46
+ total: number;
47
+ successful: number;
48
+ failed: number;
49
+ totalTime: number;
50
+ averageTime: number;
51
+ };
52
+ }
53
+
32
54
  export interface ScreenshotOptions extends ScrapeOptions {
33
55
  /** Force full page screenshot */
34
56
  fullPage?: boolean;
@@ -74,14 +96,33 @@ export interface ScrapeResult {
74
96
  attempt?: number;
75
97
  }
76
98
 
77
- export interface AnalyzeResult extends ScrapeResult {
78
- /** AI analysis response */
79
- analysis?: {
80
- answer: string;
81
- confidence: number;
82
- processingTime: number;
83
- language: string;
99
+ export interface AnalyzeResult {
100
+ /** Whether the request was successful */
101
+ success: boolean;
102
+ /** API response data */
103
+ data?: {
104
+ /** Whether the inner request was successful */
105
+ success?: boolean;
106
+ /** The answer from AI analysis */
107
+ answer?: string;
108
+ /** Metadata about the request */
109
+ metadata?: {
110
+ url: string;
111
+ question: string;
112
+ method: string;
113
+ timestamp: string;
114
+ performance: {
115
+ totalTime: number;
116
+ };
117
+ screenshot?: string | null;
118
+ };
84
119
  };
120
+ /** Error message (if failed) */
121
+ error?: string;
122
+ /** Response time in milliseconds */
123
+ responseTime: number;
124
+ /** Attempt number that succeeded */
125
+ attempt?: number;
85
126
  }
86
127
 
87
128
  export interface UsageResult {
@@ -153,6 +194,11 @@ export declare class BrowserNativeClient {
153
194
  */
154
195
  analyze(url: string, question: string, options?: AnalyzeOptions): Promise<AnalyzeResult>;
155
196
 
197
+ /**
198
+ * Scrape multiple URLs with concurrency control
199
+ */
200
+ bulkScrape(urls: string[], options?: BulkScrapeOptions): Promise<BulkScrapeResult>;
201
+
156
202
  /**
157
203
  * Get account usage statistics
158
204
  */
@@ -201,4 +247,13 @@ export declare function quickShot(
201
247
  options?: ScreenshotOptions
202
248
  ): Promise<ScrapeResult>;
203
249
 
250
+ /**
251
+ * Convenience function for bulk scraping multiple URLs
252
+ */
253
+ export declare function bulkScrape(
254
+ urls: string[],
255
+ apiKey: string,
256
+ options?: BulkScrapeOptions
257
+ ): Promise<BulkScrapeResult>;
258
+
204
259
  export default BrowserNativeClient;
package/index.js CHANGED
@@ -83,6 +83,57 @@ export class BrowserNativeClient {
83
83
  return this._makeRequest('/aireply', payload);
84
84
  }
85
85
 
86
+ /**
87
+ * Scrape multiple URLs with concurrency control
88
+ * @param {string[]} urls - URLs to scrape
89
+ * @param {object} options - Bulk scraping options
90
+ * @returns {Promise<object>} Aggregated results
91
+ */
92
+ async bulkScrape(urls, options = {}) {
93
+ const concurrency = options.concurrency || 5;
94
+ const continueOnError = options.continueOnError !== false;
95
+ const results = [];
96
+ const startTime = Date.now();
97
+ let processed = 0;
98
+
99
+ const queue = [...urls];
100
+ const workers = Array.from({ length: Math.min(concurrency, urls.length) }, async () => {
101
+ while (queue.length > 0) {
102
+ const url = queue.shift();
103
+ if (!url) break;
104
+ try {
105
+ const result = await this.scrape(url, options);
106
+ results.push({ url, ...result });
107
+ } catch (error) {
108
+ results.push({ url, success: false, error: error.message });
109
+ if (!continueOnError) throw error;
110
+ }
111
+ processed++;
112
+ if (options.progressCallback) {
113
+ options.progressCallback({
114
+ processed,
115
+ total: urls.length,
116
+ percentage: (processed / urls.length) * 100,
117
+ });
118
+ }
119
+ }
120
+ });
121
+
122
+ await Promise.all(workers);
123
+
124
+ const successful = results.filter(r => r.success).length;
125
+ return {
126
+ results,
127
+ stats: {
128
+ total: urls.length,
129
+ successful,
130
+ failed: urls.length - successful,
131
+ totalTime: Date.now() - startTime,
132
+ averageTime: Math.round((Date.now() - startTime) / urls.length),
133
+ },
134
+ };
135
+ }
136
+
86
137
  /**
87
138
  * Get account usage statistics
88
139
  * @param {number} days - Number of days to fetch (max 30)
@@ -121,7 +172,7 @@ export class BrowserNativeClient {
121
172
  headers: {
122
173
  'x-api-key': this.apiKey,
123
174
  'Content-Type': 'application/json',
124
- 'User-Agent': 'Browser Native Client SDK/1.0.3'
175
+ 'User-Agent': 'Browser Native Client SDK/2.0.0'
125
176
  }
126
177
  };
127
178
 
@@ -231,5 +282,17 @@ export async function quickShot(url, apiKey, options = {}) {
231
282
  return client.quickshot(url, options);
232
283
  }
233
284
 
285
+ /**
286
+ * Convenience function for bulk scraping multiple URLs
287
+ * @param {string[]} urls - URLs to scrape
288
+ * @param {string} apiKey - Your API key
289
+ * @param {object} options - Bulk options (concurrency, continueOnError, progressCallback)
290
+ * @returns {Promise<object>} Aggregated results
291
+ */
292
+ export async function bulkScrape(urls, apiKey, options = {}) {
293
+ const client = new BrowserNativeClient(apiKey, options);
294
+ return client.bulkScrape(urls, options);
295
+ }
296
+
234
297
  // Default export for CommonJS compatibility
235
298
  export default BrowserNativeClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monostate/browsernative-client",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "Browser Native client SDK for web scraping and content extraction API",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -33,7 +33,7 @@
33
33
  "license": "MIT",
34
34
  "dependencies": {},
35
35
  "engines": {
36
- "node": ">=16.0.0"
36
+ "node": ">=18.0.0"
37
37
  },
38
38
  "repository": {
39
39
  "type": "git",
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 BNCA Team
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.