@monostate/browsernative-client 1.0.1
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 +419 -0
- package/index.d.ts +190 -0
- package/index.js +208 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# @browsernative/client
|
|
2
|
+
|
|
3
|
+
> **Official JavaScript/TypeScript client for Browser Native API**
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/js/%40browsernative%2Fclient)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](../../LICENSE)
|
|
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.
|
|
10
|
+
|
|
11
|
+
## 🚀 Quick Start
|
|
12
|
+
|
|
13
|
+
### Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @browsernative/client
|
|
17
|
+
# or
|
|
18
|
+
yarn add @browsernative/client
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @browsernative/client
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Get Your API Key
|
|
24
|
+
|
|
25
|
+
1. Sign up at [browsernative.monostate.ai](https://browsernative.monostate.ai)
|
|
26
|
+
2. Get your API key from the dashboard
|
|
27
|
+
3. Start scraping!
|
|
28
|
+
|
|
29
|
+
### Basic Usage
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { BrowserNativeClient } from '@browsernative/client';
|
|
33
|
+
|
|
34
|
+
const client = new BrowserNativeClient('your-api-key');
|
|
35
|
+
|
|
36
|
+
// Scrape any website
|
|
37
|
+
const result = await client.scrape('https://example.com');
|
|
38
|
+
console.log(result.data.title);
|
|
39
|
+
console.log(result.data.content);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Quick Functions
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { quickScrape, quickScreenshot, quickAnalyze } from '@browsernative/client';
|
|
46
|
+
|
|
47
|
+
// One-line scraping
|
|
48
|
+
const content = await quickScrape('https://example.com', 'your-api-key');
|
|
49
|
+
|
|
50
|
+
// Take a screenshot
|
|
51
|
+
const screenshot = await quickScreenshot('https://example.com', 'your-api-key');
|
|
52
|
+
|
|
53
|
+
// AI-powered analysis
|
|
54
|
+
const analysis = await quickAnalyze(
|
|
55
|
+
'https://news.ycombinator.com',
|
|
56
|
+
'What are the top 3 trending topics?',
|
|
57
|
+
'your-api-key'
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 📋 API Reference
|
|
62
|
+
|
|
63
|
+
### Client Initialization
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
const client = new BrowserNativeClient(apiKey, options);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Options:**
|
|
70
|
+
- `baseUrl` (string): API base URL (default: `https://browsernative.monostate.ai`)
|
|
71
|
+
- `timeout` (number): Request timeout in ms (default: `30000`)
|
|
72
|
+
- `retries` (number): Number of retry attempts (default: `2`)
|
|
73
|
+
- `verbose` (boolean): Enable logging (default: `false`)
|
|
74
|
+
|
|
75
|
+
### Methods
|
|
76
|
+
|
|
77
|
+
#### `client.scrape(url, options)`
|
|
78
|
+
|
|
79
|
+
Extract structured content from any webpage.
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const result = await client.scrape('https://example.com', {
|
|
83
|
+
includeScreenshot: true,
|
|
84
|
+
waitForSelector: '.main-content',
|
|
85
|
+
extractMetadata: true,
|
|
86
|
+
userAgent: 'Custom Bot 1.0'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log(result.data.title); // Page title
|
|
90
|
+
console.log(result.data.content); // Main content
|
|
91
|
+
console.log(result.data.metadata); // Meta tags, etc.
|
|
92
|
+
console.log(result.screenshot); // Base64 image (if requested)
|
|
93
|
+
console.log(result.method); // Scraping method used
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Options:**
|
|
97
|
+
- `includeScreenshot` (boolean): Include page screenshot
|
|
98
|
+
- `waitForSelector` (string): CSS selector to wait for
|
|
99
|
+
- `userAgent` (string): Custom user agent
|
|
100
|
+
- `viewport` (object): `{ width: number, height: number }`
|
|
101
|
+
- `extractMetadata` (boolean): Extract meta tags and structured data
|
|
102
|
+
|
|
103
|
+
#### `client.screenshot(url, options)`
|
|
104
|
+
|
|
105
|
+
Take high-quality screenshots of webpages.
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
const result = await client.screenshot('https://example.com', {
|
|
109
|
+
fullPage: true,
|
|
110
|
+
format: 'png',
|
|
111
|
+
viewport: { width: 1920, height: 1080 }
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Use the base64 image
|
|
115
|
+
const img = `data:image/png;base64,${result.screenshot}`;
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Options:**
|
|
119
|
+
- `fullPage` (boolean): Capture full page scroll
|
|
120
|
+
- `format` (string): `'png'`, `'jpeg'`, or `'webp'`
|
|
121
|
+
- `quality` (number): JPEG quality (1-100)
|
|
122
|
+
- All scrape options are also available
|
|
123
|
+
|
|
124
|
+
#### `client.analyze(url, question, options)`
|
|
125
|
+
|
|
126
|
+
AI-powered content analysis and question answering.
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
const result = await client.analyze(
|
|
130
|
+
'https://techcrunch.com',
|
|
131
|
+
'What are the latest AI developments mentioned?',
|
|
132
|
+
{
|
|
133
|
+
language: 'en',
|
|
134
|
+
style: 'detailed'
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
console.log(result.analysis.answer); // AI response
|
|
139
|
+
console.log(result.analysis.confidence); // Confidence score
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Options:**
|
|
143
|
+
- `language` (string): Response language (`'en'`, `'pt'`, `'es'`, `'fr'`, `'de'`, `'auto'`)
|
|
144
|
+
- `style` (string): Response style (`'concise'`, `'detailed'`, `'technical'`)
|
|
145
|
+
- All scrape options are also available
|
|
146
|
+
|
|
147
|
+
#### `client.getUsage(days)`
|
|
148
|
+
|
|
149
|
+
Get your account usage statistics.
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
const usage = await client.getUsage(30); // Last 30 days
|
|
153
|
+
|
|
154
|
+
console.log(usage.data.monthlyTotal.totalRequests);
|
|
155
|
+
console.log(usage.data.currentUsage);
|
|
156
|
+
console.log(usage.data.usageLimit);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `client.healthCheck()`
|
|
160
|
+
|
|
161
|
+
Check API status and your account health.
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const health = await client.healthCheck();
|
|
165
|
+
|
|
166
|
+
console.log(health.data.status); // 'healthy', 'degraded', or 'unhealthy'
|
|
167
|
+
console.log(health.data.services); // Service status breakdown
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 🌐 Framework Integration
|
|
171
|
+
|
|
172
|
+
### React Hook
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// hooks/useBrowserNative.js
|
|
176
|
+
import { useState } from 'react';
|
|
177
|
+
import { BrowserNativeClient } from '@browsernative/client';
|
|
178
|
+
|
|
179
|
+
export function useBrowserNative(apiKey) {
|
|
180
|
+
const [loading, setLoading] = useState(false);
|
|
181
|
+
const [data, setData] = useState(null);
|
|
182
|
+
const [error, setError] = useState(null);
|
|
183
|
+
|
|
184
|
+
const client = new BrowserNativeClient(apiKey);
|
|
185
|
+
|
|
186
|
+
const scrape = async (url, options = {}) => {
|
|
187
|
+
setLoading(true);
|
|
188
|
+
setError(null);
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const result = await client.scrape(url, options);
|
|
192
|
+
if (result.success) {
|
|
193
|
+
setData(result.data);
|
|
194
|
+
} else {
|
|
195
|
+
setError(result.error);
|
|
196
|
+
}
|
|
197
|
+
} catch (err) {
|
|
198
|
+
setError(err.message);
|
|
199
|
+
} finally {
|
|
200
|
+
setLoading(false);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
return { scrape, loading, data, error };
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Vue Composable
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
// composables/useBrowserNative.js
|
|
212
|
+
import { ref } from 'vue';
|
|
213
|
+
import { BrowserNativeClient } from '@browsernative/client';
|
|
214
|
+
|
|
215
|
+
export function useBrowserNative(apiKey) {
|
|
216
|
+
const loading = ref(false);
|
|
217
|
+
const data = ref(null);
|
|
218
|
+
const error = ref(null);
|
|
219
|
+
|
|
220
|
+
const client = new BrowserNativeClient(apiKey);
|
|
221
|
+
|
|
222
|
+
const scrape = async (url, options = {}) => {
|
|
223
|
+
loading.value = true;
|
|
224
|
+
error.value = null;
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const result = await client.scrape(url, options);
|
|
228
|
+
if (result.success) {
|
|
229
|
+
data.value = result.data;
|
|
230
|
+
} else {
|
|
231
|
+
error.value = result.error;
|
|
232
|
+
}
|
|
233
|
+
} catch (err) {
|
|
234
|
+
error.value = err.message;
|
|
235
|
+
} finally {
|
|
236
|
+
loading.value = false;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return { scrape, loading, data, error };
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Next.js API Route
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
// pages/api/scrape.js
|
|
248
|
+
import { BrowserNativeClient } from '@browsernative/client';
|
|
249
|
+
|
|
250
|
+
const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
|
|
251
|
+
|
|
252
|
+
export default async function handler(req, res) {
|
|
253
|
+
if (req.method !== 'POST') {
|
|
254
|
+
return res.status(405).json({ error: 'Method not allowed' });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
const { url, question } = req.body;
|
|
259
|
+
|
|
260
|
+
let result;
|
|
261
|
+
if (question) {
|
|
262
|
+
result = await client.analyze(url, question);
|
|
263
|
+
} else {
|
|
264
|
+
result = await client.scrape(url);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
res.status(200).json(result);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
res.status(500).json({ error: error.message });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Express.js
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
import express from 'express';
|
|
278
|
+
import { BrowserNativeClient } from '@browsernative/client';
|
|
279
|
+
|
|
280
|
+
const app = express();
|
|
281
|
+
const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
|
|
282
|
+
|
|
283
|
+
app.post('/scrape', async (req, res) => {
|
|
284
|
+
try {
|
|
285
|
+
const { url } = req.body;
|
|
286
|
+
const result = await client.scrape(url);
|
|
287
|
+
res.json(result);
|
|
288
|
+
} catch (error) {
|
|
289
|
+
res.status(500).json({ error: error.message });
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 🔒 Environment Variables
|
|
295
|
+
|
|
296
|
+
Create a `.env` file:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
BROWSER_NATIVE_API_KEY=your_api_key_here
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Then use in your code:
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
const client = new BrowserNativeClient(process.env.BROWSER_NATIVE_API_KEY);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## 📱 Browser Usage
|
|
309
|
+
|
|
310
|
+
You can use this client directly in browsers, but be careful with API keys:
|
|
311
|
+
|
|
312
|
+
```html
|
|
313
|
+
<!DOCTYPE html>
|
|
314
|
+
<html>
|
|
315
|
+
<head>
|
|
316
|
+
<title>Browser Native Demo</title>
|
|
317
|
+
</head>
|
|
318
|
+
<body>
|
|
319
|
+
<script type="module">
|
|
320
|
+
import { BrowserNativeClient } from 'https://cdn.skypack.dev/@browsernative/client';
|
|
321
|
+
|
|
322
|
+
// ⚠️ Never expose your API key in client-side code!
|
|
323
|
+
// Use a proxy server or environment variables
|
|
324
|
+
const client = new BrowserNativeClient(await getApiKeyFromServer());
|
|
325
|
+
|
|
326
|
+
const result = await client.scrape('https://example.com');
|
|
327
|
+
console.log(result);
|
|
328
|
+
</script>
|
|
329
|
+
</body>
|
|
330
|
+
</html>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Security Note**: Never expose your API key in client-side code. Use a backend proxy or server-side rendering.
|
|
334
|
+
|
|
335
|
+
## ⚡ Performance Tips
|
|
336
|
+
|
|
337
|
+
1. **Reuse Client Instances**: Create one client instance and reuse it
|
|
338
|
+
2. **Enable Retries**: The client automatically retries failed requests
|
|
339
|
+
3. **Use Appropriate Timeouts**: Adjust timeout based on your use case
|
|
340
|
+
4. **Batch Requests**: Process multiple URLs concurrently
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
const client = new BrowserNativeClient(apiKey, {
|
|
344
|
+
timeout: 45000, // Longer timeout for complex sites
|
|
345
|
+
retries: 3, // More retries for reliability
|
|
346
|
+
verbose: true // Enable logging for debugging
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Concurrent scraping
|
|
350
|
+
const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
|
|
351
|
+
const results = await Promise.all(
|
|
352
|
+
urls.map(url => client.scrape(url))
|
|
353
|
+
);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## 🔧 Error Handling
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
try {
|
|
360
|
+
const result = await client.scrape(url);
|
|
361
|
+
|
|
362
|
+
if (result.success) {
|
|
363
|
+
console.log('Success:', result.data);
|
|
364
|
+
} else {
|
|
365
|
+
console.error('Scraping failed:', result.error);
|
|
366
|
+
}
|
|
367
|
+
} catch (error) {
|
|
368
|
+
console.error('Request failed:', error.message);
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Common error scenarios:
|
|
373
|
+
- **Invalid API Key**: Check your API key and account status
|
|
374
|
+
- **Rate Limited**: Upgrade your plan or reduce request frequency
|
|
375
|
+
- **Timeout**: Increase timeout or try a simpler extraction method
|
|
376
|
+
- **Invalid URL**: Ensure the URL is accessible and properly formatted
|
|
377
|
+
|
|
378
|
+
## 🚀 TypeScript Support
|
|
379
|
+
|
|
380
|
+
Full TypeScript support with comprehensive type definitions:
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
import { BrowserNativeClient, ScrapeResult, AnalyzeResult } from '@browsernative/client';
|
|
384
|
+
|
|
385
|
+
const client: BrowserNativeClient = new BrowserNativeClient('your-api-key');
|
|
386
|
+
|
|
387
|
+
const result: ScrapeResult = await client.scrape('https://example.com');
|
|
388
|
+
const analysis: AnalyzeResult = await client.analyze(url, question);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## 📊 Rate Limits
|
|
392
|
+
|
|
393
|
+
| Plan | Requests/Month | Rate Limit |
|
|
394
|
+
|------|----------------|------------|
|
|
395
|
+
| **Free** | 1,000 | 10/minute |
|
|
396
|
+
| **Starter** | 10,000 | 60/minute |
|
|
397
|
+
| **Pro** | 100,000 | 300/minute |
|
|
398
|
+
| **Enterprise** | Unlimited | Custom |
|
|
399
|
+
|
|
400
|
+
## 🤝 Support
|
|
401
|
+
|
|
402
|
+
- 📧 **Email**: [support@browsernative.monostate.ai](mailto:support@browsernative.monostate.ai)
|
|
403
|
+
- 📖 **Documentation**: [browsernative.monostate.ai/docs](https://browsernative.monostate.ai/docs)
|
|
404
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/browsernative/client-sdk/issues)
|
|
405
|
+
- 💬 **Discord**: [Join our community](https://discord.gg/browsernative)
|
|
406
|
+
|
|
407
|
+
## 📄 License
|
|
408
|
+
|
|
409
|
+
MIT License - see [LICENSE](../../LICENSE) file for details.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
<div align="center">
|
|
414
|
+
|
|
415
|
+
**Built with ❤️ for developers who value speed and reliability**
|
|
416
|
+
|
|
417
|
+
[🌐 Website](https://browsernative.monostate.ai) | [📖 Docs](https://browsernative.monostate.ai/docs) | [🚀 Get API Key](https://browsernative.monostate.ai/signup)
|
|
418
|
+
|
|
419
|
+
</div>
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Native Client SDK TypeScript Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ClientOptions {
|
|
6
|
+
/** Base URL for the API (default: https://browsernative.monostate.ai) */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
9
|
+
timeout?: number;
|
|
10
|
+
/** Number of retry attempts (default: 2) */
|
|
11
|
+
retries?: number;
|
|
12
|
+
/** Enable verbose logging (default: false) */
|
|
13
|
+
verbose?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ScrapeOptions {
|
|
17
|
+
/** Include screenshot in the response */
|
|
18
|
+
includeScreenshot?: boolean;
|
|
19
|
+
/** Wait for specific selector before extracting content */
|
|
20
|
+
waitForSelector?: string;
|
|
21
|
+
/** Custom user agent string */
|
|
22
|
+
userAgent?: string;
|
|
23
|
+
/** Viewport size for rendering */
|
|
24
|
+
viewport?: {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
/** Additional metadata to extract */
|
|
29
|
+
extractMetadata?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ScreenshotOptions extends ScrapeOptions {
|
|
33
|
+
/** Force full page screenshot */
|
|
34
|
+
fullPage?: boolean;
|
|
35
|
+
/** Image format (default: png) */
|
|
36
|
+
format?: 'png' | 'jpeg' | 'webp';
|
|
37
|
+
/** Image quality for JPEG (1-100) */
|
|
38
|
+
quality?: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AnalyzeOptions extends ScrapeOptions {
|
|
42
|
+
/** Language for the AI response */
|
|
43
|
+
language?: 'en' | 'pt' | 'es' | 'fr' | 'de' | 'auto';
|
|
44
|
+
/** Response style */
|
|
45
|
+
style?: 'concise' | 'detailed' | 'technical';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ScrapeResult {
|
|
49
|
+
/** Whether the request was successful */
|
|
50
|
+
success: boolean;
|
|
51
|
+
/** Extracted content data */
|
|
52
|
+
data?: {
|
|
53
|
+
title?: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
content?: string;
|
|
56
|
+
metadata?: Record<string, any>;
|
|
57
|
+
links?: string[];
|
|
58
|
+
images?: string[];
|
|
59
|
+
};
|
|
60
|
+
/** Scraping method used */
|
|
61
|
+
method?: 'direct' | 'lightpanda' | 'puppeteer';
|
|
62
|
+
/** Performance information */
|
|
63
|
+
performance?: {
|
|
64
|
+
totalTime: number;
|
|
65
|
+
method: string;
|
|
66
|
+
};
|
|
67
|
+
/** Base64 encoded screenshot (if requested) */
|
|
68
|
+
screenshot?: string;
|
|
69
|
+
/** Error message (if failed) */
|
|
70
|
+
error?: string;
|
|
71
|
+
/** Response time in milliseconds */
|
|
72
|
+
responseTime: number;
|
|
73
|
+
/** Attempt number that succeeded */
|
|
74
|
+
attempt?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface AnalyzeResult extends ScrapeResult {
|
|
78
|
+
/** AI analysis response */
|
|
79
|
+
analysis?: {
|
|
80
|
+
answer: string;
|
|
81
|
+
confidence: number;
|
|
82
|
+
processingTime: number;
|
|
83
|
+
language: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface UsageResult {
|
|
88
|
+
success: boolean;
|
|
89
|
+
data?: {
|
|
90
|
+
/** Daily usage breakdown */
|
|
91
|
+
dailyUsage: Array<{
|
|
92
|
+
date: string;
|
|
93
|
+
requests: number;
|
|
94
|
+
scrapeRequests: number;
|
|
95
|
+
analyzeRequests: number;
|
|
96
|
+
}>;
|
|
97
|
+
/** Monthly totals */
|
|
98
|
+
monthlyTotal: {
|
|
99
|
+
totalRequests: number;
|
|
100
|
+
scrapeTotal: number;
|
|
101
|
+
analyzeTotal: number;
|
|
102
|
+
};
|
|
103
|
+
/** Current plan information */
|
|
104
|
+
currentUsage: number;
|
|
105
|
+
usageLimit: number;
|
|
106
|
+
planType: string;
|
|
107
|
+
subscriptionStatus: string;
|
|
108
|
+
currentPeriodEnd: string;
|
|
109
|
+
};
|
|
110
|
+
error?: string;
|
|
111
|
+
responseTime: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface HealthResult {
|
|
115
|
+
success: boolean;
|
|
116
|
+
data?: {
|
|
117
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
118
|
+
version: string;
|
|
119
|
+
uptime: number;
|
|
120
|
+
services: {
|
|
121
|
+
scraping: boolean;
|
|
122
|
+
ai: boolean;
|
|
123
|
+
database: boolean;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
error?: string;
|
|
127
|
+
responseTime: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Browser Native API Client
|
|
132
|
+
*/
|
|
133
|
+
export declare class BrowserNativeClient {
|
|
134
|
+
constructor(apiKey: string, options?: ClientOptions);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Scrape a webpage and extract structured content
|
|
138
|
+
*/
|
|
139
|
+
scrape(url: string, options?: ScrapeOptions): Promise<ScrapeResult>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Scrape a webpage and take a screenshot
|
|
143
|
+
*/
|
|
144
|
+
screenshot(url: string, options?: ScreenshotOptions): Promise<ScrapeResult>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Extract content and answer questions using AI
|
|
148
|
+
*/
|
|
149
|
+
analyze(url: string, question: string, options?: AnalyzeOptions): Promise<AnalyzeResult>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get account usage statistics
|
|
153
|
+
*/
|
|
154
|
+
getUsage(days?: number): Promise<UsageResult>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check API health and your account status
|
|
158
|
+
*/
|
|
159
|
+
healthCheck(): Promise<HealthResult>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Convenience function for quick scraping without instantiating a client
|
|
164
|
+
*/
|
|
165
|
+
export declare function quickScrape(
|
|
166
|
+
url: string,
|
|
167
|
+
apiKey: string,
|
|
168
|
+
options?: ScrapeOptions
|
|
169
|
+
): Promise<ScrapeResult>;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Convenience function for taking screenshots
|
|
173
|
+
*/
|
|
174
|
+
export declare function quickScreenshot(
|
|
175
|
+
url: string,
|
|
176
|
+
apiKey: string,
|
|
177
|
+
options?: ScreenshotOptions
|
|
178
|
+
): Promise<ScrapeResult>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Convenience function for AI analysis
|
|
182
|
+
*/
|
|
183
|
+
export declare function quickAnalyze(
|
|
184
|
+
url: string,
|
|
185
|
+
question: string,
|
|
186
|
+
apiKey: string,
|
|
187
|
+
options?: AnalyzeOptions
|
|
188
|
+
): Promise<AnalyzeResult>;
|
|
189
|
+
|
|
190
|
+
export default BrowserNativeClient;
|
package/index.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Native Client SDK
|
|
3
|
+
*
|
|
4
|
+
* A lightweight JavaScript client for the Browser Native web scraping API.
|
|
5
|
+
* Works in browsers, Node.js, and edge environments.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class BrowserNativeClient {
|
|
9
|
+
constructor(apiKey, options = {}) {
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
throw new Error('API key is required. Get one at https://browsernative.monostate.ai');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.baseUrl = options.baseUrl || 'https://bnca-api.fly.dev';
|
|
16
|
+
this.timeout = options.timeout || 30000;
|
|
17
|
+
this.retries = options.retries || 2;
|
|
18
|
+
this.verbose = options.verbose || false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Scrape a webpage and extract structured content
|
|
23
|
+
* @param {string} url - The URL to scrape
|
|
24
|
+
* @param {object} options - Scraping options
|
|
25
|
+
* @returns {Promise<object>} Scraping result
|
|
26
|
+
*/
|
|
27
|
+
async scrape(url, options = {}) {
|
|
28
|
+
const payload = {
|
|
29
|
+
url,
|
|
30
|
+
screenshot: options.includeScreenshot || false,
|
|
31
|
+
...options
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return this._makeRequest('/scrapeurl', payload);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Scrape a webpage and take a screenshot
|
|
39
|
+
* @param {string} url - The URL to scrape
|
|
40
|
+
* @param {object} options - Screenshot options
|
|
41
|
+
* @returns {Promise<object>} Screenshot result with base64 image
|
|
42
|
+
*/
|
|
43
|
+
async screenshot(url, options = {}) {
|
|
44
|
+
const payload = {
|
|
45
|
+
url,
|
|
46
|
+
screenshot: true,
|
|
47
|
+
...options
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return this._makeRequest('/scrapeurl', payload);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract content and answer questions using AI
|
|
55
|
+
* @param {string} url - The URL to analyze
|
|
56
|
+
* @param {string} question - The question to answer
|
|
57
|
+
* @param {object} options - Analysis options
|
|
58
|
+
* @returns {Promise<object>} AI analysis result
|
|
59
|
+
*/
|
|
60
|
+
async analyze(url, question, options = {}) {
|
|
61
|
+
const payload = {
|
|
62
|
+
url,
|
|
63
|
+
question,
|
|
64
|
+
screenshot: options.includeScreenshot || false,
|
|
65
|
+
...options
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return this._makeRequest('/aireply', payload);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get account usage statistics
|
|
73
|
+
* @param {number} days - Number of days to fetch (max 30)
|
|
74
|
+
* @returns {Promise<object>} Usage statistics
|
|
75
|
+
*/
|
|
76
|
+
async getUsage(days = 30) {
|
|
77
|
+
return this._makeRequest('/stats', {}, 'GET');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check API health and your account status
|
|
82
|
+
* @returns {Promise<object>} Health check result
|
|
83
|
+
*/
|
|
84
|
+
async healthCheck() {
|
|
85
|
+
return this._makeRequest('/health', {}, 'GET');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Make an authenticated request to the API
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
async _makeRequest(endpoint, payload = {}, method = 'POST', queryParams = '') {
|
|
93
|
+
const url = `${this.baseUrl}${endpoint}${queryParams}`;
|
|
94
|
+
const startTime = Date.now();
|
|
95
|
+
|
|
96
|
+
let lastError;
|
|
97
|
+
|
|
98
|
+
for (let attempt = 1; attempt <= this.retries + 1; attempt++) {
|
|
99
|
+
try {
|
|
100
|
+
if (this.verbose) {
|
|
101
|
+
console.log(`Browser Native: ${method} ${url} (attempt ${attempt})`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const options = {
|
|
105
|
+
method,
|
|
106
|
+
headers: {
|
|
107
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
108
|
+
'Content-Type': 'application/json',
|
|
109
|
+
'User-Agent': 'Browser Native Client SDK/1.0.0'
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (method !== 'GET') {
|
|
114
|
+
options.body = JSON.stringify(payload);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Set up timeout
|
|
118
|
+
const controller = new AbortController();
|
|
119
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
120
|
+
options.signal = controller.signal;
|
|
121
|
+
|
|
122
|
+
const response = await fetch(url, options);
|
|
123
|
+
clearTimeout(timeoutId);
|
|
124
|
+
|
|
125
|
+
const responseTime = Date.now() - startTime;
|
|
126
|
+
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
129
|
+
throw new Error(`API Error (${response.status}): ${errorData.error || response.statusText}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const data = await response.json();
|
|
133
|
+
|
|
134
|
+
if (this.verbose) {
|
|
135
|
+
console.log(`Browser Native: Request completed in ${responseTime}ms`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
data,
|
|
141
|
+
responseTime,
|
|
142
|
+
attempt
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
lastError = error;
|
|
147
|
+
|
|
148
|
+
if (attempt <= this.retries && !error.name === 'AbortError') {
|
|
149
|
+
const delay = Math.pow(2, attempt - 1) * 1000; // Exponential backoff
|
|
150
|
+
if (this.verbose) {
|
|
151
|
+
console.log(`Browser Native: Attempt ${attempt} failed, retrying in ${delay}ms...`);
|
|
152
|
+
}
|
|
153
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// All retries failed
|
|
162
|
+
return {
|
|
163
|
+
success: false,
|
|
164
|
+
error: lastError.message || 'Request failed',
|
|
165
|
+
responseTime: Date.now() - startTime
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Convenience function for quick scraping without instantiating a client
|
|
172
|
+
* @param {string} url - The URL to scrape
|
|
173
|
+
* @param {string} apiKey - Your API key
|
|
174
|
+
* @param {object} options - Additional options
|
|
175
|
+
* @returns {Promise<object>} Scraping result
|
|
176
|
+
*/
|
|
177
|
+
export async function quickScrape(url, apiKey, options = {}) {
|
|
178
|
+
const client = new BrowserNativeClient(apiKey, options);
|
|
179
|
+
return client.scrape(url, options);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Convenience function for taking screenshots
|
|
184
|
+
* @param {string} url - The URL to capture
|
|
185
|
+
* @param {string} apiKey - Your API key
|
|
186
|
+
* @param {object} options - Additional options
|
|
187
|
+
* @returns {Promise<object>} Screenshot result
|
|
188
|
+
*/
|
|
189
|
+
export async function quickScreenshot(url, apiKey, options = {}) {
|
|
190
|
+
const client = new BrowserNativeClient(apiKey, options);
|
|
191
|
+
return client.screenshot(url, options);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Convenience function for AI analysis
|
|
196
|
+
* @param {string} url - The URL to analyze
|
|
197
|
+
* @param {string} question - The question to answer
|
|
198
|
+
* @param {string} apiKey - Your API key
|
|
199
|
+
* @param {object} options - Additional options
|
|
200
|
+
* @returns {Promise<object>} Analysis result
|
|
201
|
+
*/
|
|
202
|
+
export async function quickAnalyze(url, question, apiKey, options = {}) {
|
|
203
|
+
const client = new BrowserNativeClient(apiKey, options);
|
|
204
|
+
return client.analyze(url, question, options);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Default export for CommonJS compatibility
|
|
208
|
+
export default BrowserNativeClient;
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@monostate/browsernative-client",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Browser Native client SDK for web scraping and content extraction API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./index.js",
|
|
11
|
+
"types": "./index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"index.js",
|
|
16
|
+
"index.d.ts",
|
|
17
|
+
"README.md",
|
|
18
|
+
"package.json"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"web-scraping",
|
|
22
|
+
"api-client",
|
|
23
|
+
"browser-native",
|
|
24
|
+
"content-extraction",
|
|
25
|
+
"web-automation",
|
|
26
|
+
"data-extraction",
|
|
27
|
+
"javascript",
|
|
28
|
+
"typescript",
|
|
29
|
+
"browser",
|
|
30
|
+
"client-sdk"
|
|
31
|
+
],
|
|
32
|
+
"author": "Browser Native Team",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=16.0.0"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/browsernative/client-sdk.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/browsernative/client-sdk/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://browsernative.monostate.ai",
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|