Node.js SDK

@browser-forest/sdk is the official Browser Forest Node.js SDK, providing a type-safe API wrapper with a Stripe-style resource-oriented design.

Installation

npm install @browser-forest/sdk
# or
pnpm add @browser-forest/sdk
Note: The SDK uses Node.js 20+ built-in fetch — no additional dependencies like node-fetch are needed.

Initialization

import { BrowserForestClient } from '@browser-forest/sdk';

const client = new BrowserForestClient({
  apiKey: 'bf_live_xxxxxxxxxxxxxxxxxxxx',
  // baseUrl: 'https://bf.mktindex.com/api/v1',  // optional, default
  // timeout: 30000,                               // optional, ms, default 30s
});

Sessions

// Create Session
const session = await client.sessions.create({
  contextId: 'ctx_xxx',   // optional
  proxyId: 'prx_xxx',     // optional
  url: 'https://google.com',  // optional
});
console.log(session.cdpUrl); // wss://bf.mktindex.com/ws/session/ses_xxx

// List Sessions
const sessions = await client.sessions.list();

// Get Session
const s = await client.sessions.get('ses_xxx');

// Stop Session
await client.sessions.stop('ses_xxx');

Contexts

// Create Context
const ctx = await client.contexts.create({ name: 'my-account' });

// List Contexts
const contexts = await client.contexts.list();

// Get Context
const c = await client.contexts.get('ctx_xxx');

// Delete Context
await client.contexts.delete('ctx_xxx');

Proxies

// Create proxy
const proxy = await client.proxies.create({
  name: 'US Proxy',
  type: 'http',
  host: 'proxy.example.com',
  port: 8080,
  username: 'user',    // optional
  password: 'pass',    // optional
  country: 'US',       // optional
});

// Test proxy
const result = await client.proxies.test('prx_xxx');
console.log(result.healthy, result.latencyMs);

// Delete proxy
await client.proxies.delete('prx_xxx');

Scrape

const result = await client.scrape.scrape({
  url: 'https://example.com',
  contextId: 'ctx_xxx',         // optional
  proxyId: 'prx_xxx',           // optional
  waitFor: 2000,                // optional, ms
  javascript: 'return document.title',  // optional
});

console.log(result.html);      // full HTML
console.log(result.title);     // page title
console.log(result.jsResult);  // JS execution result

Authentication

// Login
const { token } = await client.auth.login({
  email: '[email protected]',
  password: 'yourpassword',
});

// Create API Key (requires JWT token)
const apiKey = await client.auth.createApiKey({ name: 'my-key' });

// List API Keys
const keys = await client.auth.listApiKeys();

// Revoke API Key
await client.auth.revokeApiKey('key_id');

Usage

const stats = await client.usage.get();
console.log(stats);
// {
//   totalSessions: 42,
//   totalDurationSeconds: 3600,
//   avgDurationSeconds: 85.7
// }

Error Handling

The SDK provides specific error classes for each HTTP error, all extending BrowserForestError:

import {
  BrowserForestError,
  AuthenticationError,
  NotFoundError,
  BadRequestError,
  ConflictError,
  RateLimitError,
} from '@browser-forest/sdk';

try {
  const session = await client.sessions.get('ses_nonexistent');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Session not found');
  } else if (err instanceof AuthenticationError) {
    console.log('Invalid API key');
  } else if (err instanceof BrowserForestError) {
    console.log('API error:', err.message, err.status);
  }
}

Error Types

Error ClassHTTP StatusDescription
AuthenticationError401API Key is invalid or missing
NotFoundError404Resource not found
BadRequestError400Invalid request parameters
ConflictError409Resource conflict (e.g., email already registered)
RateLimitError429Too many requests
LaunchFailedError503Browser launch failed
WorkerUnavailableError503Worker unavailable
ApiErrorOtherGeneric API error

Complete Example

import { BrowserForestClient } from '@browser-forest/sdk';
import puppeteer from 'puppeteer-core';

const client = new BrowserForestClient({
  apiKey: process.env.BROWSER_FOREST_API_KEY!,
});

async function main() {
  // Create Context (for persistent state)
  const ctx = await client.contexts.create({ name: 'my-scrape-session' });

  // Create Session
  const session = await client.sessions.create({ contextId: ctx.id });
  console.log('Session started:', session.id);

  // Connect to browser
  const browser = await puppeteer.connect({
    browserWSEndpoint: session.cdpUrl,
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');

  const title = await page.title();
  console.log('Page title:', title);

  await browser.disconnect();

  // Stop Session (auto-save state to Context)
  await client.sessions.stop(session.id);
  console.log('Session stopped, state saved to context');
}

main().catch(console.error);