npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

browser7

v1.0.0

Published

Official Node.js SDK for Browser7 - Geo-targeted web scraping with automatic CAPTCHA solving and wait actions

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 browser7

Requirements: 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 rendering

With 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 info

With 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 metrics

Fetch 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 responses

Check 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 options
    • apiKey (string, required): Your Browser7 API key
    • baseUrl (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 render
  • options (object, optional): Render options
  • onProgress (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 selector
  • state (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 for
  • selector (string, optional): CSS selector to limit search scope
  • timeout (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 click
  • timeout (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:

  1. First render: Use default (captcha: 'disabled')
  2. If HTML contains CAPTCHA: Re-render with captcha: 'auto'
  3. For known CAPTCHA sites: Always specify captcha mode

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 string

Contributing

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

Links