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

evomi-client

v1.0.3

Published

JavaScript client for Evomi API

Readme

Evomi JavaScript Client

The official JavaScript client for Evomi — a powerful web scraping and proxy platform. Extract data from any website with AI-powered processing, browser rendering, and a global proxy network.

Installation

npm install evomi-client

Quick Start

import { EvomiClient } from 'evomi-client';

const client = new EvomiClient({ apiKey: 'your-api-key' });

// Scrape a webpage
const result = await client.scrape('https://example.com');
console.log(result.content);

Core Features

  • Web Scraping — Extract content from any URL with automatic JS rendering detection
  • AI-Powered Extraction — Get structured data using natural language prompts
  • Crawling & Mapping — Discover and scrape entire websites
  • Proxy Network — Access residential, datacenter, and mobile proxies worldwide

Usage Examples

Basic Scraping

import { EvomiClient } from 'evomi-client';

const client = new EvomiClient({ apiKey: 'your-api-key' });

// Simple scrape (auto-detects if JS rendering is needed)
const result = await client.scrape('https://example.com');
console.log(result.content);

AI-Powered Data Extraction

Extract structured data without writing selectors:

const result = await client.scrape('https://example.com/products', {
  aiEnhance: true,
  aiPrompt: 'Extract all product names, prices, and availability',
});
console.log(result.ai_data);

Browser Mode for JavaScript Sites

Force browser rendering for dynamic content:

const result = await client.scrape('https://spa-example.com', {
  mode: 'browser',  // Forces headless browser
  waitSeconds: 2,   // Wait for dynamic content
});

Crawling Websites

Discover and scrape multiple pages:

const result = await client.crawl('example.com', {
  maxUrls: 50,
  depth: 2,
  urlPattern: '/blog/.*',  // Only crawl blog pages
});

Async Tasks

For long-running operations, use async mode:

// Start the crawl
const { task_id } = await client.crawl('example.com', { asyncMode: true });

// Check status later
const status = await client.getTaskStatus(task_id, 'crawl');
if (status.status === 'completed') {
  console.log(status.results);
}

Proxy String Builder

Evomi provides a proxy network you can use with any HTTP client. Build proxy strings for fetch, axios, or any other library:

import { EvomiClient, ProxyType } from 'evomi-client';

const client = new EvomiClient({ apiKey: 'your-api-key' });

// Build a proxy string for US residential proxy
const proxyString = await client.buildProxyString({
  proxyType: ProxyType.RESIDENTIAL,
  country: 'US',
  session: 'abc12345',  // Sticky session
});
console.log(proxyString);
// Output: http://user:[email protected]:1000

Manual Proxy Configuration

import { ProxyConfig, ProxyType, ProxyProtocol } from 'evomi-client';

const config = new ProxyConfig({
  proxyType: ProxyType.RESIDENTIAL,
  protocol: ProxyProtocol.HTTP,
  country: 'US',
  city: 'New York',
  username: 'your-username',
  password: 'your-password',
});

const proxyString = config.buildProxyString();

Proxy Types

| Type | Endpoint | Use Case | |------|----------|----------| | Residential | rp.evomi.com:1000 | Human-like browsing, anti-bot bypass | | Datacenter | dcp.evomi.com:2000 | Fast, high-volume requests | | Mobile | mp.evomi.com:3000 | Highest trust, mobile-specific targets |


API Reference

Scraping Operations

scrape(url, options)

Scrape a single URL with configurable options.

const result = await client.scrape('https://example.com', {
  mode: 'auto',              // 'request', 'browser', or 'auto'
  output: 'markdown',        // 'html', 'markdown', 'screenshot', 'pdf'
  device: 'windows',         // 'windows', 'macos', 'android'
  proxyType: 'residential',
  proxyCountry: 'US',
  proxySessionId: 'abc123',
  waitUntil: 'domcontentloaded',
  aiEnhance: true,
  aiPrompt: 'Extract product data',
  aiSource: 'markdown',
  jsInstructions: [{ click: '.load-more' }],
  executeJs: 'window.scrollTo(0, document.body.scrollHeight)',
  waitSeconds: 2,
  screenshot: false,
  pdf: false,
  excludedTags: ['nav', 'footer'],
  excludedSelectors: ['.ads'],
  blockResources: ['image', 'stylesheet'],
  additionalHeaders: { 'X-Custom': 'value' },
  captureHeaders: true,
  networkCapture: [{ url_pattern: '/api/.*' }],
  asyncMode: false,
  configId: 'cfg_abc123',
  schemeId: 'sch_abc123',
  extractScheme: [{ label: 'title', type: 'content', selector: 'h1' }],
  storageId: 'stor_abc123',
  useDefaultStorage: false,
  noHtml: false,
});

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | url | string | required | URL to scrape | | mode | string | 'auto' | Scraping mode: 'request', 'browser', 'auto' | | output | string | 'markdown' | Output format: 'html', 'markdown', 'screenshot', 'pdf' | | device | string | 'windows' | Device type: 'windows', 'macos', 'android' | | proxyType | string | 'residential' | Proxy type: 'datacenter', 'residential' | | proxyCountry | string | 'US' | Two-letter country code | | proxySessionId | string | — | Proxy session ID (6-8 chars) | | waitUntil | string | 'domcontentloaded' | Wait condition | | aiEnhance | boolean | false | Enable AI extraction | | aiPrompt | string | — | Prompt for AI extraction | | aiSource | string | — | AI source: 'markdown', 'screenshot' | | aiForceJson | boolean | true | Force AI response to valid JSON | | jsInstructions | array | — | JS actions: click, wait, fill, wait_for | | executeJs | string | — | Raw JavaScript to execute | | waitSeconds | number | 0 | Seconds to wait after page load | | screenshot | boolean | false | Capture screenshot | | pdf | boolean | false | Capture PDF | | excludedTags | array | — | HTML tags to remove | | excludedSelectors | array | — | CSS selectors to remove | | blockResources | array | — | Resource types to block | | additionalHeaders | object | — | Extra HTTP headers | | captureHeaders | boolean | false | Capture response headers | | networkCapture | array | — | Network capture filters | | asyncMode | boolean | false | Return immediately with task ID | | configId | string | — | Saved config ID | | schemeId | string | — | Saved extraction schema ID | | extractScheme | array | — | Inline extraction schema | | storageId | string | — | Storage config ID | | useDefaultStorage | boolean | false | Use default storage | | noHtml | boolean | false | Exclude HTML from response |

crawl(domain, options)

Crawl a website to discover and scrape multiple pages.

const result = await client.crawl('example.com', {
  maxUrls: 100,
  depth: 2,
  urlPattern: '/blog/.*',
  scraperConfig: { mode: 'browser', output: 'markdown' },
  asyncMode: false,
});

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | domain | string | required | Domain to crawl | | maxUrls | number | 100 | Maximum URLs to crawl | | depth | number | 2 | Crawl depth | | urlPattern | string | — | Regex pattern to filter URLs | | scraperConfig | object | — | Config for scraping each page | | asyncMode | boolean | false | Return immediately with task ID |

mapWebsite(domain, options)

Discover URLs from a website via sitemaps, CommonCrawl, or crawling.

const result = await client.mapWebsite('example.com', {
  sources: ['sitemap', 'commoncrawl'],
  maxUrls: 500,
  urlPattern: '/products/.*',
  checkIfLive: false,
  depth: 1,
  asyncMode: false,
});

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | domain | string | required | Domain to map | | sources | array | ['sitemap', 'commoncrawl'] | Sources: 'sitemap', 'commoncrawl', 'crawl' | | maxUrls | number | 500 | Maximum URLs to discover | | urlPattern | string | — | Regex pattern to filter URLs | | checkIfLive | boolean | false | Check if URLs are live | | depth | number | 1 | Crawl depth if using crawl source | | asyncMode | boolean | false | Return immediately with task ID |

searchDomains(query, options)

Find domains by searching the web.

// Single query
const result = await client.searchDomains('e-commerce platforms', {
  maxUrls: 20,
  region: 'us-en',
});

// Multiple queries (up to 10)
const result = await client.searchDomains(
  ['web scraping tools', 'data extraction services'],
  { maxUrls: 20, region: 'us-en' }
);

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | query | string or array | required | Search query or list of up to 10 queries | | maxUrls | number | 20 | Max domains per query (max: 100) | | region | string | 'us-en' | Region for results |

agentRequest(message)

Send a natural language request to the AI agent.

const result = await client.agentRequest(
  'Scrape example.com and extract all product prices'
);

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | message | string | required | Natural language request |

getTaskStatus(taskId, taskType)

Check the status of an async task.

const result = await client.getTaskStatus('abc123', 'scrape');
// taskType: 'scrape' | 'crawl' | 'map' | 'config_generate' | 'schema'

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | taskId | string | required | Task ID to check | | taskType | string | 'scrape' | Task type |


Config Management

Save and reuse scrape configurations.

listConfigs(options)

List all saved scrape configs.

const configs = await client.listConfigs({
  page: 1,
  perPage: 20,
  sortBy: 'created_at',
  sortOrder: 'desc',
});

createConfig(name, config)

Create a new scrape config.

const config = await client.createConfig('Product Scraper', {
  mode: 'browser',
  output: 'markdown',
});

getConfig(configId)

Get a scrape config by ID.

const config = await client.getConfig('cfg_abc123');

updateConfig(configId, options)

Update an existing scrape config.

const config = await client.updateConfig('cfg_abc123', {
  name: 'New Name',
  config: { mode: 'request' },
});

deleteConfig(configId)

Delete a scrape config.

await client.deleteConfig('cfg_abc123');

generateConfig(name, prompt)

Generate a scrape config from natural language using AI.

const config = await client.generateConfig(
  'Amazon Scraper',
  'Scrape product title and price from Amazon product pages'
);

Schema Management

Define reusable structured data extraction schemas.

listSchemas(options)

List all saved extraction schemas.

const schemas = await client.listSchemas({
  page: 1,
  perPage: 20,
  sortBy: 'created_at',
  sortOrder: 'desc',
});

createSchema(name, config, options)

Create a new extraction schema.

const schema = await client.createSchema(
  'Product Schema',
  {
    url: 'https://example.com/product',
    extract_scheme: [
      { label: 'title', type: 'content', selector: 'h1' },
      { label: 'price', type: 'content', selector: '.price' },
    ],
  },
  { test: true, fix: false }
);

getSchema(schemeId)

Get an extraction schema by ID.

const schema = await client.getSchema('sch_abc123');

updateSchema(schemeId, name, config, options)

Update an existing extraction schema.

const schema = await client.updateSchema(
  'sch_abc123',
  'Updated Schema',
  { url: '...', extract_scheme: [...] },
  { test: true }
);

deleteSchema(schemeId)

Delete an extraction schema.

await client.deleteSchema('sch_abc123');

getSchemaStatus(schemeId)

Get the test status of a schema.

const status = await client.getSchemaStatus('sch_abc123');

Schedule Management

Run scrape configs on a recurring schedule.

listSchedules(options)

List all scheduled jobs.

const schedules = await client.listSchedules({
  page: 1,
  perPage: 20,
  activeOnly: false,
});

createSchedule(name, configId, intervalMinutes, options)

Create a new scheduled scrape job.

const schedule = await client.createSchedule(
  'Daily Price Check',
  'cfg_abc123',
  1440,  // Daily (in minutes)
  { startTime: '09:00', stopOnError: true }
);

getSchedule(scheduleId)

Get a scheduled job by ID.

const schedule = await client.getSchedule('sched_abc123');

updateSchedule(scheduleId, options)

Update an existing scheduled job.

const schedule = await client.updateSchedule('sched_abc123', {
  name: 'New Name',
  intervalMinutes: 720,
});

deleteSchedule(scheduleId)

Delete a scheduled job.

await client.deleteSchedule('sched_abc123');

toggleSchedule(scheduleId)

Toggle a scheduled job active/inactive.

await client.toggleSchedule('sched_abc123');

listScheduleRuns(scheduleId, options)

Get execution history for a scheduled job.

const runs = await client.listScheduleRuns('sched_abc123', {
  page: 1,
  perPage: 20,
});

Storage Management

Connect cloud storage to automatically save scrape results.

listStorageConfigs()

List all storage configurations.

const configs = await client.listStorageConfigs();

createStorageConfig(name, storageType, config, options)

Create a new storage configuration.

// S3-compatible storage
const storage = await client.createStorageConfig(
  'My S3',
  's3_compatible',
  {
    bucket: 'my-bucket',
    region: 'us-east-1',
    access_key: '...',
    secret_key: '...',
  },
  { setAsDefault: true }
);

// Google Cloud Storage
const storage = await client.createStorageConfig(
  'My GCS',
  'gcs',
  { bucket: 'my-bucket', credentials_json: '...' }
);

// Azure Blob Storage
const storage = await client.createStorageConfig(
  'My Azure',
  'azure_blob',
  { container: 'my-container', connection_string: '...' }
);

updateStorageConfig(storageId, options)

Update an existing storage configuration.

const storage = await client.updateStorageConfig('stor_abc123', {
  name: 'Renamed Storage',
  setAsDefault: true,
});

deleteStorageConfig(storageId)

Delete a storage configuration.

await client.deleteStorageConfig('stor_abc123');

Webhook Notifications

Receive real-time notifications when your scraping operations complete, fail, or start. Webhooks support Discord, Slack, and custom HTTP endpoints.

Quick Start

const result = await client.scrape('https://example.com', {
  webhook: {
    url: 'https://your-webhook-endpoint.com/webhook',
    type: 'custom',
    events: ['completed', 'failed'],
  },
});

Webhook Configuration

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | url | string | Yes | Your webhook endpoint URL | | type | string | Yes | Webhook type: 'discord', 'slack', or 'custom' | | events | array | Yes | List of events to subscribe to | | secret | string | No | Secret key for HMAC signature (custom webhooks only) |

Supported Events

| Operation | Events | |-----------|--------| | Scrape | scrape.started, scrape.completed, scrape.failed | | Crawl | crawl.started, crawl.completed, crawl.failed | | Map | map.started, map.completed, map.failed | | Search | search.started, search.completed, search.failed | | Schedule | schedule.started, schedule.completed, schedule.failed, schedule.paused |

You can use shorthand notation: ['completed', 'failed'] or full names: ['scrape.completed', 'scrape.failed'].

Webhook Types

Discord Webhooks

const result = await client.scrape('https://example.com', {
  webhook: {
    url: 'https://discord.com/api/webhooks/...',
    type: 'discord',
    events: ['completed', 'failed'],
  },
});

Discord webhooks receive rich embeds with operation details.

Slack Webhooks

const result = await client.scrape('https://example.com', {
  webhook: {
    url: 'https://hooks.slack.com/services/...',
    type: 'slack',
    events: ['completed', 'failed'],
  },
});

Slack webhooks receive formatted attachments with operation details.

Custom Webhooks

const result = await client.scrape('https://example.com', {
  webhook: {
    url: 'https://your-server.com/webhook',
    type: 'custom',
    events: ['completed', 'failed'],
    secret: 'your-secret-key',  // Optional HMAC signature
  },
});

Custom Webhook Payload

Custom webhooks receive a JSON POST request with the following structure:

{
    "event": "scrape.completed",
    "timestamp": "2026-03-06T20:51:00Z",
    "user_id": 123,
    "username": "user_name",
    "task_id": "abc123",
    "data": {
        "url": "https://example.com",
        "domain": "example.com",
        "status_code": 200,
        "credits_used": 1.5
    },
    "signature": "sha256=..."
}

| Field | Type | Description | |-------|------|-------------| | event | string | The event that triggered the webhook | | timestamp | string | ISO 8601 timestamp | | user_id | number | Your user ID | | username | string | Your username | | task_id | string | The task ID associated with the operation | | data | object | Operation-specific data | | signature | string | HMAC SHA256 signature (if secret configured) |

Security: HMAC Signature Verification

When you provide a secret, custom webhooks include an HMAC SHA256 signature in the payload. Verify the signature to ensure requests are from Evomi:

import crypto from 'crypto';

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = 'sha256=' + 
    crypto.createHmac('sha256', secret)
      .update(payload)
      .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler (e.g., Express)
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'] || '';
  
  if (!verifyWebhook(req.body, signature, 'your-secret-key')) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const data = JSON.parse(req.body);
  // Process the webhook...
  res.json({ received: true });
});

The signature is sent in the X-Webhook-Signature header.

Usage Examples

Per-Request Webhook

Add a webhook to any scraping operation:

const result = await client.scrape('https://example.com', {
  webhook: {
    url: 'https://your-server.com/webhook',
    type: 'custom',
    events: ['scrape.completed', 'scrape.failed'],
    secret: 'your-secret-key',
  },
});

Schedule with Webhook

Attach a webhook to a scheduled job:

const schedule = await client.createSchedule(
  'Daily Price Check',
  'cfg_abc123',
  1440,
  {
    webhook: {
      url: 'https://your-server.com/webhook',
      type: 'discord',
      events: ['completed', 'failed'],
    },
  }
);

Crawl with Webhook

const result = await client.crawl('example.com', {
  maxUrls: 100,
  webhook: {
    url: 'https://hooks.slack.com/services/...',
    type: 'slack',
    events: ['crawl.completed', 'crawl.failed'],
  },
});

Public API

Access proxy credentials and related data.

getProxyData()

Get detailed information about your proxy products.

const data = await client.getProxyData();
// Returns: { products: { rp: {...}, sdc: {...}, mp: {...} }, ... }

getTargetingOptions()

Get available targeting parameters for different proxy types.

const options = await client.getTargetingOptions();

getScraperData()

Get information about your Scraper API access.

const data = await client.getScraperData();
// Returns: { credits: ..., concurrency_limit: ..., ... }

getBrowserData()

Get information about your Browser API access.

const data = await client.getBrowserData();
// Returns: { credits: ..., concurrency_limit: ..., endpoint: ..., ... }

rotateSession(sessionId, product)

Force an IP address change for an existing proxy session.

const result = await client.rotateSession('abc12345', 'rp');
// product: 'rpc', 'rp', 'sdc', 'mp'

generateProxies(options)

Generate proxy strings with specific targeting parameters.

const proxies = await client.generateProxies({
  product: 'rp',
  countries: 'US,GB,DE',
  city: 'New York',
  session: 'sticky',
  amount: 10,
  protocol: 'http',
  lifetime: 30,
  adblock: true,
});
// Returns plain text, one proxy per line

| Parameter | Type | Description | |-----------|------|-------------| | product | string | Proxy product type | | countries | string | ISO country codes, comma-separated | | city | string | Target city name | | region | string | Target region | | isp | string | Target ISP name | | session | string | 'sticky' or 'hard' | | amount | number | Number of proxies to generate (1-100) | | format | string | Output format (1, 2, or 3) | | prependProtocol | boolean | Prepend protocol to proxy string | | protocol | string | 'http' or 'socks5' | | lifetime | number | Session duration in minutes | | adblock | boolean | Enable ad-blocking |


Account Info

getAccountInfo()

Get account info including credit balance.

const info = await client.getAccountInfo();
console.log(info.credits);

Proxy Helpers

buildProxyConfig(options)

Build a proxy configuration with credentials from the Public API.

import { ProxyType, ProxyProtocol, ResidentialMode } from 'evomi-client';

const config = await client.buildProxyConfig({
  proxyType: ProxyType.RESIDENTIAL,
  protocol: ProxyProtocol.HTTP,
  country: 'US',
  city: 'New York',
  region: 'California',
  continent: 'north.america',
  isp: 'att',
  session: 'abc12345',
  lifetime: 30,
  mode: ResidentialMode.SPEED,
  latency: 100,
  fraudscore: 20,
  device: 'windows',
  http3: true,
});

buildProxyString(options)

Build a proxy connection string directly.

const proxyString = await client.buildProxyString({
  proxyType: ProxyType.RESIDENTIAL,
  country: 'US',
  session: 'abc12345',
});

Configuration

API Key

Set your API key via environment variable:

export EVOMI_API_KEY="your-api-key"

Or pass it directly:

const client = new EvomiClient({ apiKey: 'your-api-key' });

Proxy Credentials (Optional)

If you have separate credentials for the proxy API:

const client = new EvomiClient({
  apiKey: 'your-api-key',
  publicApiKey: 'your-proxy-api-key',
});

Error Handling

try {
  const result = await client.scrape('https://example.com');
} catch (error) {
  console.error('Scraping failed:', error.message);
}

Credits & Pricing

All operations consume credits:

  • Base request: 1 credit
  • Browser mode: 5x multiplier
  • Residential proxy: 2x multiplier
  • AI enhancement: +30 credits

Credit usage is returned in the result:

console.log(result._credits_used);
console.log(result._credits_remaining);

Requirements

  • Node.js >= 18 (for native fetch)

Links

License

MIT