@monostate/browsernative-client 1.2.1 → 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 +71 -403
- package/index.d.ts +62 -7
- package/index.js +64 -1
- package/package.json +2 -2
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -1,461 +1,129 @@
|
|
|
1
1
|
# @monostate/browsernative-client
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> JavaScript/TypeScript client for the Browser Native web scraping API
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@monostate/browsernative-client)
|
|
6
|
+
[](https://github.com/monostate/browsernative-client/blob/main/LICENSE)
|
|
6
7
|
[](https://www.typescriptlang.org/)
|
|
7
|
-
[](../../LICENSE)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Zero-dependency client for scraping, screenshots, and AI analysis. Works in Node.js, browsers, and edge environments.
|
|
10
10
|
|
|
11
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
205
|
-
|
|
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
|
-
|
|
32
|
+
// Screenshot
|
|
33
|
+
const screenshot = await client.screenshot('https://example.com');
|
|
234
34
|
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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
|
-
###
|
|
42
|
+
### Convenience functions
|
|
270
43
|
|
|
271
44
|
```javascript
|
|
272
|
-
|
|
273
|
-
import { BrowserNativeClient } from '@monostate/browsernative-client';
|
|
45
|
+
import { quickScrape, quickScreenshot, quickShot, quickAnalyze, bulkScrape } from '@monostate/browsernative-client';
|
|
274
46
|
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
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
|
-
###
|
|
52
|
+
### Bulk scraping
|
|
300
53
|
|
|
301
54
|
```javascript
|
|
302
|
-
|
|
303
|
-
import { BrowserNativeClient } from '@monostate/browsernative-client';
|
|
55
|
+
const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
|
|
304
56
|
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
+
## API Reference
|
|
328
67
|
|
|
329
|
-
|
|
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
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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
|
-
|
|
104
|
+
### Response shape
|
|
382
105
|
|
|
383
106
|
```javascript
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
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
|
|
117
|
+
Full type definitions included.
|
|
406
118
|
|
|
407
119
|
```typescript
|
|
408
|
-
import { BrowserNativeClient, ScrapeResult,
|
|
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
|
-
##
|
|
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
|
-
|
|
125
|
+
See [CHANGELOG.md](./CHANGELOG.md).
|
|
458
126
|
|
|
459
|
-
|
|
127
|
+
## License
|
|
460
128
|
|
|
461
|
-
|
|
129
|
+
MIT
|
package/index.d.ts
CHANGED
|
@@ -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
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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/
|
|
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": "
|
|
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": ">=
|
|
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.
|