Switch to Rezo

Why Rezo

Most HTTP libraries solve one problem well and leave you to piece together the rest. Rezo ships everything a production HTTP client needs in a single package: cookie management, proxy rotation, browser stealth, web crawling, staged timeouts, response caching, request queuing, and full site cloning. It runs on every JavaScript runtime without changing a line of code.

One Client, Every Runtime

Rezo runs on Node.js, Bun, Deno, browsers, React Native, and edge runtimes like Cloudflare Workers. Your application code stays identical — Rezo automatically selects the right adapter for the environment.

// This code runs everywhere -- no conditional imports, no polyfills
import rezo from 'rezo';

// Callable like fetch()
const { data } = await rezo('https://api.example.com/users');

// Or use named methods
const { data: users } = await rezo.get('https://api.example.com/users');

Six Adapters, Auto-Selected

Rezo ships with six adapters, each optimized for a specific runtime:

AdapterRuntimeBest For
HTTPNode.js, BunServer-side requests with full control
HTTP/2Node.js, BunMultiplexed connections, server push
cURLNode.jsTLS fingerprint impersonation, debugging
FetchBrowsers, Deno, Bun, EdgeUniversal compatibility
XHRBrowsersUpload progress events, legacy support
React NativeReact Native, ExpoMobile HTTP with native bridge

The adapter picker detects your environment at import time and selects the best option. You can also set an adapter explicitly per-instance or per-request.

Every Rezo instance carries a cookie jar. Cookies are captured from Set-Cookie headers, stored per domain and path, and sent back automatically on subsequent requests. No third-party plugins required.

import { Rezo, CookieJar } from 'rezo';

const jar = new CookieJar();
const client = rezo.create({ jar });

// Login -- cookies are captured automatically
await client.postJson('https://example.com/login', { user: 'ada', pass: 'secret' });

// Authenticated request -- cookies are sent automatically
const { data } = await client.get('https://example.com/dashboard');

// Export cookies for persistence
const json = jar.toJSON();           // JSON format
const netscape = jar.toNetscape();   // Netscape/cURL format

Proxy Rotation with Health Monitoring

Rezo’s ProxyManager rotates through a pool of proxies with health tracking, automatic failover, and support for HTTP, HTTPS, SOCKS4, and SOCKS5 protocols.

import { Rezo, ProxyManager } from 'rezo';

const proxies = new ProxyManager([
  'http://proxy1.example.com:8080',
  'socks5://proxy2.example.com:1080',
  'https://user:pass@proxy3.example.com:3128',
]);

const client = rezo.create({ proxyManager: proxies });

// Each request uses the next healthy proxy
await client.get('https://target.com/page1');
await client.get('https://target.com/page2');

18 Browser Stealth Profiles

The stealth module makes requests indistinguishable from real browser traffic. It controls TLS fingerprints, HTTP/2 SETTINGS frames, header ordering, client hints, and navigator properties.

import rezo from 'rezo';
import { RezoStealth } from 'rezo/stealth';

const stealth = new RezoStealth('chrome-131');
const client = rezo.create({ stealth });

// Request looks identical to Chrome 131 on the wire
const { data } = await client.get('https://protected-site.com');

18 profiles across Chrome, Firefox, Safari, Edge, Opera, and Brave. Use rotate: true for a fresh identity on every request.

Web Crawler with SQLite Persistence

Rezo includes a production-grade web crawler with queue-based URL processing, robots.txt compliance, memory monitoring, and resumable sessions backed by SQLite.

import { Crawler } from 'rezo/crawler';

const crawler = new Crawler({
  startUrls: ['https://example.com'],
  maxDepth: 3,
  concurrency: 10,
  respectRobotsTxt: true,
});

for await (const result of crawler) {
  console.log(result.url, result.status);
}

26 Lifecycle Hooks

Hooks let you intercept every phase of the HTTP lifecycle: DNS resolution, TCP connect, TLS handshake, redirect, retry, cookie processing, and more. Each hook point accepts an array of handlers.

const client = rezo.create({
  hooks: {
    beforeRequest: [(config) => { config.headers.set('X-Trace', uuid()); }],
    afterResponse: [(response) => { log(response.timing); return response; }],
    beforeRetry: [(config, error, context) => { refreshToken(config); }],
  }
});

Staged Timeouts

Instead of a single timeout, Rezo provides granular control over each phase of a request:

const client = rezo.create({
  timeout: {
    connect: 5_000,    // TCP connection
    headers: 10_000,   // Time to first byte
    body: 30_000,      // Full body download
    total: 60_000,     // Overall request limit
  }
});

Response and DNS Caching

Cache responses in memory or with a custom store. DNS results are cached to eliminate redundant lookups.

const client = rezo.create({
  cache: { ttl: 60_000, maxSize: 100 },
  dnsCache: { ttl: 300_000 },
});

// First request hits the server
await client.get('https://api.example.com/config');

// Second request served from cache
await client.get('https://api.example.com/config');

Request Queue with Per-Domain Concurrency

The built-in request queue prevents overwhelming servers with configurable concurrency and rate limiting.

const client = rezo.create({
  queueOptions: {
    enable: true,
    options: {
      concurrency: 5,
      interval: 1000,
      intervalCap: 2,
    }
  }
});

Full Site Cloning

The wget module mirrors entire websites to disk, converting links for offline browsing.

import { Wget } from 'rezo/wget';

const wget = new Wget({
  url: 'https://docs.example.com',
  outputDir: './mirror',
  depth: 5,
  convertLinks: true,
});

await wget.run();

70+ Structured Error Codes

Every error carries a machine-readable code, boolean classification flags, and a recovery suggestion. No more guessing what went wrong.

import rezo, { RezoError } from 'rezo';

try {
  await rezo.get('https://api.example.com/data');
} catch (error) {
  if (rezo.isRezoError(error)) {
    console.log(error.code);        // "REZ_TIMEOUT"
    console.log(error.isTimeout);   // true
    console.log(error.suggestion);  // "Increase the timeout or check server health"
  }
}

TypeScript-First

Rezo is written in strict TypeScript from the ground up. Every method, option, and response is fully typed with generics, overloads, and discriminated unions.

interface User {
  id: number;
  name: string;
}

// data is typed as User[]
const { data } = await rezo.get<User[]>('/api/users');

// Full IDE autocomplete on config
await rezo.get('/api/users', {
  params: { page: 1 },
  timeout: { total: 5000 },
  retry: { limit: 3 },
});

Feature Comparison

How Rezo compares to other popular HTTP libraries:

FeatureRezoAxiosGotnode-fetchUndicisuperagent
TypeScript-native
Node.js
Browsers
Deno / Edge
React Native
HTTP/2
Cookie jar● Built-in◑ Plugin◑ Plugin◑ Plugin
Cookie persistence● Built-in
Proxy rotation● Built-in
SOCKS proxy● Built-in◑ Plugin
Stealth / TLS fingerprint● Built-in
Web crawler● Built-in
Lifecycle hooks● 26 hooks◑ 2◑ 9
Staged timeouts● 4 phases◑ Single◑ Partial◑ Single
Response caching● Built-in◑ Plugin
DNS caching● Built-in◑ Plugin
Request queue● Built-in
Site cloning (wget)● Built-in
cURL adapter
Downloads + progress● Built-in◑ Partial◑ Partial
Uploads + progress● Built-in◑ Partial
Retry with backoff● Built-in◑ Plugin◑ Plugin
Structured error codes● 70+◑ 6◑ ~12◑ ~10
Recovery suggestions

Next Steps

Ready to switch? Pick the guide that matches your current library: