browser7
v1.0.0
Published
Official Node.js SDK for Browser7 - Geo-targeted web scraping with automatic CAPTCHA solving and wait actions
Maintainers
Readme
Browser7 Node.js SDK
Official Node.js client for the Browser7 web scraping and rendering API.
Browser7 provides geo-targeted web scraping with automatic proxy management, CAPTCHA solving, and powerful wait actions for dynamic content.
Features
- 🌍 Geo-Targeting - Render pages from specific countries and cities using residential proxies
- 🤖 CAPTCHA Solving - Automatic detection and solving of reCAPTCHA and Cloudflare Turnstile
- 📸 Screenshots - Capture viewport or full-page screenshots in PNG or JPEG
- 🌐 In-Browser Fetch - Fetch additional URLs through the rendered page's browser context
- ⏱️ Wait Actions - Click elements, wait for selectors, text content, or delays
- 🚀 Performance - Block images, track bandwidth, view timing breakdowns
- 🔄 Automatic Polling - Built-in polling with progress callbacks
- 📦 Dual Package - Works with both ESM (
import) and CommonJS (require)
Installation
npm install browser7Requirements: Node.js 18+ (uses native fetch API)
Quick Start
// ESM
import Browser7 from 'browser7';
// Or CommonJS
const Browser7 = require('browser7');
// Create client
const client = new Browser7({ apiKey: 'your-api-key' });
// Simple render
const result = await client.render('https://example.com');
console.log(result.html);Authentication
Get your API key from the Browser7 Dashboard.
const client = new Browser7({ apiKey: 'b7_your_api_key_here' });Usage Examples
Basic Rendering
const result = await client.render('https://example.com', {
countryCode: 'US'
});
console.log(result.html); // Rendered HTML
console.log(result.selectedCity); // City used for renderingWith Wait Actions
Use helper methods to create wait actions:
const result = await client.render('https://example.com', {
countryCode: 'GB',
city: 'london',
waitFor: [
Browser7.waitForClick('.cookie-accept'), // Click element
Browser7.waitForSelector('.main-content', 'visible'), // Wait for element
Browser7.waitForText('Subscribe', '.footer'), // Wait for text
Browser7.waitForDelay(2000) // Wait 2 seconds
]
});With CAPTCHA Solving
const result = await client.render('https://protected-site.com', {
countryCode: 'US',
captcha: 'auto' // Auto-detect and solve CAPTCHAs
});
console.log(result.captcha); // CAPTCHA detection infoWith Screenshots
const result = await client.render('https://example.com', {
countryCode: 'US',
includeScreenshot: true, // Enable screenshot
screenshotFormat: 'jpeg', // 'jpeg' or 'png'
screenshotQuality: 80, // 1-100 (JPEG only)
screenshotFullPage: false // false = viewport only, true = full page
});
// Save screenshot to file
const fs = require('fs');
const screenshotBuffer = Buffer.from(result.screenshot, 'base64');
fs.writeFileSync('screenshot.jpg', screenshotBuffer);With Progress Tracking
const result = await client.render(
'https://example.com',
{ countryCode: 'US' },
(progress) => {
console.log(`${progress.type}: ${progress.status}`);
// Output: started: N/A
// Output: polling: processing
// Output: completed: completed
}
);Performance Options
const result = await client.render('https://example.com', {
blockImages: true, // Block images (default: true)
captcha: 'disabled' // Skip CAPTCHA detection (default: disabled)
});
console.log(result.bandwidthMetrics); // Network stats
console.log(result.timingBreakdown); // Performance metricsFetch Additional URLs
const result = await client.render('https://example.com', {
fetchUrls: [
'https://example.com/api/data',
'https://example.com/api/user'
]
});
console.log(result.fetchResponses); // Array of fetch responsesCheck Account Balance
const balance = await client.getAccountBalance();
console.log(`Total: ${balance.totalBalanceFormatted}`);
console.log(`Renders remaining: ${balance.totalBalanceCents}`);
console.log(`\nBreakdown:`);
console.log(` Paid: ${balance.breakdown.paid.formatted} (${balance.breakdown.paid.cents} renders)`);
console.log(` Free: ${balance.breakdown.free.formatted} (${balance.breakdown.free.cents} renders)`);
console.log(` Bonus: ${balance.breakdown.bonus.formatted} (${balance.breakdown.bonus.cents} renders)`);API Reference
new Browser7(options)
Create a new Browser7 client.
Parameters:
options(object): Configuration optionsapiKey(string, required): Your Browser7 API keybaseUrl(string, optional): Full API base URL including version path (e.g.,'https://api.browser7.com/v1'). Defaults to production API.
Example:
// Production (default)
const client = new Browser7({ apiKey: 'your-api-key' });
// Canadian endpoint
const client = new Browser7({
apiKey: 'your-api-key',
baseUrl: 'https://ca-api.browser7.com/v1'
});client.render(url, options, onProgress)
Render a URL and poll for the result (recommended).
Parameters:
url(string): The URL to renderoptions(object, optional): Render optionsonProgress(function, optional): Progress callback
Returns: Promise
Options:
| Option | Type | Description | Default |
|--------|------|-------------|---------|
| countryCode | string | Country code (e.g., 'US', 'GB', 'DE') | Auto-select |
| city | string | City name (e.g., 'new.york', 'london') | Auto-select |
| waitFor | WaitAction[] | Array of wait actions (max 10) | - |
| captcha | string | CAPTCHA mode: 'disabled', 'auto', 'recaptcha_v2', 'recaptcha_v3', 'turnstile' | 'disabled' |
| blockImages | boolean | Block images for faster rendering | true |
| fetchUrls | string[] | Additional URLs to fetch (max 10) | - |
| includeScreenshot | boolean | Enable screenshot capture | false |
| screenshotFormat | string | Screenshot format: 'jpeg' or 'png' | 'jpeg' |
| screenshotQuality | number | JPEG quality (1-100, only for JPEG) | 80 |
| screenshotFullPage | boolean | Capture full page or viewport only | false |
Wait Action Types:
Use helper methods to create wait actions:
// Wait for a delay
Browser7.waitForDelay(duration)
// Wait for an element
Browser7.waitForSelector(selector, state, timeout)
// state: 'visible' | 'hidden' | 'attached' (default: 'visible')
// Wait for text to appear
Browser7.waitForText(text, selector, timeout)
// selector is optional - limits search scope
// Click an element
Browser7.waitForClick(selector, timeout)Or create manually:
{
waitFor: [
{ type: 'delay', duration: 3000 },
{ type: 'selector', selector: '.content', state: 'visible', timeout: 30000 },
{ type: 'text', text: 'Hello', selector: '.greeting', timeout: 30000 },
{ type: 'click', selector: '.button', timeout: 30000 }
]
}RenderResult:
{
status: 'completed',
html: '<!DOCTYPE html>...', // Decompressed HTML
screenshot: 'iVBORw0KGgoAAAANS...', // Base64-encoded image (if requested)
loadStrategy: 'default', // 'default' or 'custom'
selectedCity: {
name: 'new.york',
displayName: 'New York',
latitude: 40.7128,
longitude: -74.0060,
timezoneId: 'America/New_York'
},
bandwidthMetrics: {
networkBytes: 524288,
cachedBytes: 102400,
cacheHitRate: '16.3%'
},
captcha: {
detected: false,
handled: false
},
timingBreakdown: {
browserInitMs: 245, // Browser initialization
navigationMs: 1523, // Page navigation
loadStrategyMs: 2341, // Load strategy wait
captchaMs: 45, // CAPTCHA detection/solving
waitActionsMs: 1325, // User's waitFor actions
screenshotMs: 0, // User screenshot capture (0 if not requested)
htmlCaptureMs: 89, // HTML extraction
totalMs: 5234 // Total render time
},
fetchResponses: [], // Array if fetchUrls was provided
retryAfter: 1 // Server-suggested polling interval (seconds)
}client.createRender(url, options)
Create a render job (low-level API).
Returns: Promise<{ renderId: string }>
client.getRender(renderId)
Get the status and result of a render job (low-level API).
Returns: Promise
client.getAccountBalance()
Get the current account balance.
Returns: Promise
AccountBalance:
{
totalBalanceCents: 1300, // Total balance in cents (also equals renders remaining)
totalBalanceFormatted: "$13.00", // Formatted as USD currency
breakdown: {
paid: {
cents: 1050, // Paid balance in cents
formatted: "$10.50" // Formatted as USD
},
free: {
cents: 200, // Free balance in cents
formatted: "$2.00" // Formatted as USD
},
bonus: {
cents: 50, // Bonus balance in cents
formatted: "$0.50" // Formatted as USD
}
}
}Example:
const balance = await client.getAccountBalance();
console.log(`Total: ${balance.totalBalanceFormatted}`);
console.log(`Renders remaining: ${balance.totalBalanceCents}`);Note: Since 1 cent = 1 render, totalBalanceCents directly shows how many renders you can perform.
Helper Methods
Browser7.waitForDelay(duration)
Create a delay wait action.
duration(number): Duration in milliseconds (100-60000)
Browser7.waitForDelay(3000)
// Returns: { type: 'delay', duration: 3000 }Browser7.waitForSelector(selector, state, timeout)
Create a selector wait action.
selector(string): CSS selectorstate(string, optional): 'visible', 'hidden', or 'attached' (default: 'visible')timeout(number, optional): Timeout in milliseconds (default: 30000)
Browser7.waitForSelector('.main-content', 'visible', 10000)
// Returns: { type: 'selector', selector: '.main-content', state: 'visible', timeout: 10000 }Browser7.waitForText(text, selector, timeout)
Create a text wait action.
text(string): Text to wait forselector(string, optional): CSS selector to limit search scopetimeout(number, optional): Timeout in milliseconds (default: 30000)
Browser7.waitForText('In Stock', '.availability', 10000)
// Returns: { type: 'text', text: 'In Stock', selector: '.availability', timeout: 10000 }Browser7.waitForClick(selector, timeout)
Create a click wait action.
selector(string): CSS selector of element to clicktimeout(number, optional): Timeout in milliseconds (default: 30000)
Browser7.waitForClick('.cookie-accept', 5000)
// Returns: { type: 'click', selector: '.cookie-accept', timeout: 5000 }Error Handling
try {
const result = await client.render('https://example.com');
console.log(result.html);
} catch (error) {
if (error.message.includes('Failed to start render')) {
console.error('API error:', error.message);
} else if (error.message.includes('Render failed')) {
console.error('Render failed:', error.message);
} else if (error.message.includes('timed out')) {
console.error('Render timed out');
} else {
console.error('Unexpected error:', error.message);
}
}Advanced Usage
Two-Step Rendering (Manual Polling)
// Step 1: Create render job
const { renderId } = await client.createRender('https://example.com', {
countryCode: 'US'
});
// Step 2: Poll manually when ready
let result;
while (true) {
result = await client.getRender(renderId);
if (result.status === 'completed') {
break;
} else if (result.status === 'failed') {
throw new Error(`Render failed: ${result.error}`);
}
// Wait before next poll (use server-suggested interval)
await new Promise(resolve =>
setTimeout(resolve, (result.retryAfter || 1) * 1000)
);
}
console.log(result.html);Custom API Endpoint
// Use regional endpoint
const client = new Browser7({
apiKey: 'your-api-key',
baseUrl: 'https://ca-api.browser7.com/v1'
});
// For local development/testing
const devClient = new Browser7({
apiKey: 'your-api-key',
baseUrl: 'http://localhost:3002/v1'
});Supported Countries
AT, BE, CA, CH, CZ, DE, FR, GB, HR, HU, IT, NL, PL, SK, US
See Browser7 Documentation for available cities per country.
CAPTCHA Support
Browser7 supports automatic CAPTCHA detection and solving for:
- reCAPTCHA v2 - Google's image-based CAPTCHA
- reCAPTCHA v3 - Google's score-based CAPTCHA
- Cloudflare Turnstile - Cloudflare's CAPTCHA alternative
Modes:
'disabled'(default) - Skip CAPTCHA detection (fastest, ~60-250ms saved)'auto'- Auto-detect and solve any CAPTCHA type'recaptcha_v2','recaptcha_v3','turnstile'- Solve specific type (faster than auto)
Recommended Workflow:
- First render: Use default (
captcha: 'disabled') - If HTML contains CAPTCHA: Re-render with
captcha: 'auto' - For known CAPTCHA sites: Always specify
captchamode
TypeScript Support
The SDK includes JSDoc comments for TypeScript IntelliSense:
import Browser7 from 'browser7';
const client = new Browser7({ apiKey: 'your-api-key' });
// TypeScript will infer types from JSDoc
const result = await client.render('https://example.com', {
countryCode: 'US', // TypeScript knows this is a string
blockImages: true // TypeScript knows this is a boolean
});
console.log(result.html); // TypeScript knows html is a stringContributing
Issues and pull requests are welcome! Please visit our GitHub repository.
License
MIT
Support
- 📧 Email: [email protected]
- 📚 Documentation: https://docs.browser7.com
- 🐛 Issues: https://github.com/browser7data/browser7-node/issues
