AlterLabAlterLab
SDKNode.jsTypeScript

Node.js SDK

The official Node.js/TypeScript SDK for AlterLab. Zero dependencies, fully typed, modern async API.

npm versionNode.js 18+TypeScript ReadyLicense: MITZero dependencies
Node.js 18+Full TypeScriptNative FetchZero DependenciesESM + CJS

Installation

npm install alterlab
yarn add alterlab
pnpm add alterlab

Quick Start

import { AlterLab } from 'alterlab';

// Initialize client
const client = new AlterLab({ apiKey: 'sk_live_...' });

// Scrape a website
const result = await client.scrape('https://example.com');

console.log(result.text);                  // Extracted text
console.log(result.json);                  // Structured JSON
console.log(result.billing.costDollars);   // Cost in USD
console.log(result.billing.tierUsed);      // Which tier succeeded

Client Options

import { AlterLab } from 'alterlab';

// Basic initialization
const client = new AlterLab({ apiKey: 'sk_live_...' });

// With all options
const client = new AlterLab({
  apiKey: 'sk_live_...',           // Required (or set ALTERLAB_API_KEY env var)
  baseUrl: 'https://alterlab.io',  // Custom API endpoint
  timeout: 120000,                  // Request timeout in ms
  maxRetries: 3,                    // Auto-retry on failures
  retryDelay: 1000,                 // Initial retry delay in ms
});

// From environment variable
// Set ALTERLAB_API_KEY=sk_live_...
const client = new AlterLab(); // Reads from env
OptionTypeDefaultDescription
apiKeystringenv varYour AlterLab API key
baseUrlstringalterlab.ioAPI base URL
timeoutnumber120000Request timeout in ms
maxRetriesnumber3Max retries on failure
retryDelaynumber1000Initial retry delay in ms

Scraping Methods

client.scrape(url, options?)

Main scraping method with auto mode detection.

const result = await client.scrape('https://example.com', {
  // Mode
  mode: 'auto',              // 'auto' | 'html' | 'js' | 'pdf' | 'ocr'

  // JavaScript options
  waitFor: '#content',       // CSS selector to wait for
  screenshot: true,          // Capture screenshot

  // Advanced options
  advanced: {
    renderJs: true,
    waitCondition: 'networkidle',
    mobile: false,
    viewportWidth: 1920,
    viewportHeight: 1080,
  },

  // Output options
  formats: ['text', 'json', 'markdown'],

  // Caching
  cache: true,
  cacheTtl: 3600,            // 1 hour

  // Cost controls
  costControls: {
    maxTier: 3,
    prefer: 'cost',
    failFast: true,
  },
});

client.scrapeHtml(url, options?)

HTML-only mode (fastest, cheapest).

const result = await client.scrapeHtml('https://example.com');
console.log(result.html);
console.log(result.billing.tierName); // 'curl' or 'http'

client.scrapeJs(url, options?)

JavaScript rendering with Playwright.

const result = await client.scrapeJs('https://spa-app.com', {
  screenshot: true,
  waitFor: '.loaded',
});

console.log(result.text);
console.log(result.screenshotUrl);

client.scrapePdf(url) / client.scrapeOcr(url)

Extract text from PDFs and images.

// PDF extraction
const pdfResult = await client.scrapePdf('https://example.com/doc.pdf');
console.log(pdfResult.text);

// OCR for images
const ocrResult = await client.scrapeOcr('https://example.com/image.png', {
  language: 'eng',
});
console.log(ocrResult.text);

Structured Extraction

// Extract specific fields with JSON Schema
const result = await client.scrape('https://store.com/product/123', {
  extractionSchema: {
    type: 'object',
    properties: {
      name: { type: 'string' },
      price: { type: 'number' },
      inStock: { type: 'boolean' },
      reviews: {
        type: 'array',
        items: { type: 'string' }
      }
    }
  }
});

console.log(result.json);
// { name: "Product", price: 29.99, inStock: true, reviews: [...] }
// Use a pre-built extraction profile
const result = await client.scrape('https://store.com/product/123', {
  extractionProfile: 'product'
});

console.log(result.json);
// { name, price, description, images, availability, ... }

// Available profiles: 'product', 'article', 'job_posting', 'contact'
// Extract using natural language prompt
const result = await client.scrape('https://news.example.com/article', {
  extractionPrompt: 'Extract the article title, author, date, and main content'
});

console.log(result.json);

Cost Controls

import { AlterLab } from 'alterlab';

const client = new AlterLab({ apiKey: 'sk_live_...' });

// Limit to cheap tiers only
const result = await client.scrape('https://example.com', {
  costControls: {
    maxTier: 2,           // Don't go above HTTP tier
    prefer: 'cost',       // Optimize for lowest cost
    failFast: true,       // Error instead of escalating
    maxCostDollars: 0.001 // Cap cost at $0.001
  }
});

// Estimate cost before scraping
const estimate = await client.estimateCost('https://linkedin.com');
console.log(`Estimated: $${estimate.estimatedCostDollars.toFixed(4)}`);
console.log(`Confidence: ${estimate.confidence}`);
console.log(`Likely tier: ${estimate.tierName}`);

💰 BYOP Discount: Get 20% off by using your own proxy integration

const result = await client.scrape('https://example.com', {
  advanced: {
    useOwnProxy: true,
    proxyCountry: 'US'  // Optional geo targeting
  }
});

if (result.billing.byopApplied) {
  console.log(`Saved ${result.billing.byopDiscountPercent}%!`);
}

Async Jobs

import { AlterLab } from 'alterlab';

const client = new AlterLab({ apiKey: 'sk_live_...' });

// Start an async job (returns immediately)
const jobId = await client.scrapeAsync('https://example.com', {
  mode: 'js',
  advanced: { screenshot: true }
});

console.log(`Job started: ${jobId}`);

// Option 1: Poll manually
const status = await client.getJobStatus(jobId);
console.log(`Status: ${status.status}`);
console.log(`Progress: ${status.progress}%`);

// Option 2: Wait for completion (blocking)
const result = await client.waitForJob(jobId, {
  pollInterval: 2000,  // Check every 2 seconds
  timeout: 300000      // 5 minute timeout
});

console.log(result.text);

Error Handling

import {
  AlterLab,
  AuthenticationError,
  InsufficientCreditsError,
  RateLimitError,
  ScrapeError,
  TimeoutError,
  ValidationError,
} from 'alterlab';

const client = new AlterLab({ apiKey: 'sk_live_...' });

try {
  const result = await client.scrape('https://example.com');
  console.log(result.text);
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.log('Invalid API key');
  } else if (error instanceof InsufficientCreditsError) {
    console.log(`Balance: $${error.balanceDollars}`);
    console.log('Please top up your balance');
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof ValidationError) {
    console.log(`Invalid request: ${error.message}`);
  } else if (error instanceof ScrapeError) {
    console.log(`Scraping failed: ${error.message}`);
  } else if (error instanceof TimeoutError) {
    console.log('Request timed out');
  }
}
ExceptionHTTP CodeDescription
AuthenticationError401Invalid or missing API key
InsufficientCreditsError402Insufficient balance
RateLimitError429Too many requests
ValidationError400Invalid request parameters
ScrapeError422Scraping failed
TimeoutError-Request timed out

TypeScript

The SDK is written in TypeScript and exports all types. Your IDE will provide full autocomplete and type checking.

import {
  AlterLab,
  AlterLabConfig,
  ScrapeResult,
  ScrapeOptions,
  BillingDetails,
  CostControls,
  AdvancedOptions,
  UsageStats,
  CostEstimate,
  JobStatus,
} from 'alterlab';

// All types are exported
const options: ScrapeOptions = {
  mode: 'js',
  screenshot: true,
  costControls: {
    maxTier: 3,
    prefer: 'cost',
  },
};

const result: ScrapeResult = await client.scrape('https://example.com', options);

// Full autocomplete for all fields
const billing: BillingDetails = result.billing;
console.log(billing.costDollars);
console.log(billing.tierName);
console.log(billing.escalationPath);

API Reference

Full Documentation

For complete API reference including all types and methods, see the GitHub repository.

ScrapeResult

interface ScrapeResult {
  requestId: string;
  url: string;
  finalUrl: string;
  statusCode: number;
  text: string;
  html: string;
  json: Record<string, unknown> | null;
  markdownContent: string | null;
  title: string | null;
  author: string | null;
  screenshotUrl: string | null;
  pdfUrl: string | null;
  cached: boolean;
  responseTimeMs: number;
  sizeBytes: number;
  billing: BillingDetails;
}

BillingDetails

interface BillingDetails {
  tierUsed: number;           // 1-5
  tierName: TierName;         // 'curl' | 'http' | 'stealth' | 'browser' | 'captcha'
  costMicrocents: number;     // 1,000,000 = $1
  costDollars: number;
  byopApplied: boolean;
  byopDiscountPercent: number;
  escalationPath: TierEscalation[];
}