Switch to Rezo

From superagent

superagent pioneered the chainable HTTP API for JavaScript and has been a reliable workhorse for over a decade. If your project still depends on it, switching to Rezo gives you modern TypeScript, HTTP/2, built-in cookies, proxy rotation, stealth, lifecycle hooks, streaming with progress, and support for every JavaScript runtime — while the core API patterns remain straightforward.

Basic GET

// superagent
import superagent from 'superagent';

const { body } = await superagent.get('https://api.example.com/users');

// Rezo
import rezo from 'rezo';

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

POST with JSON

// superagent
const { body } = await superagent
  .post('https://api.example.com/users')
  .send({ name: 'Ada Lovelace', email: 'ada@example.com' })
  .set('Content-Type', 'application/json');

// Rezo
const { data } = await rezo.postJson('https://api.example.com/users', {
  name: 'Ada Lovelace',
  email: 'ada@example.com',
});

Headers

// superagent -- chainable .set()
const { body } = await superagent
  .get('https://api.example.com/data')
  .set('Authorization', 'Bearer token123')
  .set('Accept', 'application/json');

// Rezo -- headers object
const { data } = await rezo.get('https://api.example.com/data', {
  headers: {
    'Authorization': 'Bearer token123',
    'Accept': 'application/json',
  },
});

Authentication

// superagent
const { body } = await superagent
  .get('https://api.example.com/data')
  .auth('user', 'pass');

// bearer token
const { body: body2 } = await superagent
  .get('https://api.example.com/data')
  .auth('my-token', { type: 'bearer' });

// Rezo
const { data } = await rezo.get('https://api.example.com/data', {
  auth: { username: 'user', password: 'pass' },
});

// bearer token
const { data: data2 } = await rezo.get('https://api.example.com/data', {
  headers: { 'Authorization': 'Bearer my-token' },
});

Query Parameters

// superagent
const { body } = await superagent
  .get('https://api.example.com/users')
  .query({ page: 2, limit: 25 });

// Rezo
const { data } = await rezo.get('https://api.example.com/users', {
  params: { page: 2, limit: 25 },
});

File Upload

// superagent
const { body } = await superagent
  .post('https://api.example.com/upload')
  .attach('file', './report.pdf')
  .field('description', 'Monthly report');

// Rezo
import { RezoFormData } from 'rezo';
import { createReadStream } from 'node:fs';

const form = new RezoFormData();
form.append('file', createReadStream('./report.pdf'), 'report.pdf');
form.append('description', 'Monthly report');

const { data } = await rezo.post('https://api.example.com/upload', form);

Rezo also provides a dedicated upload method with progress tracking:

await rezo.upload('https://api.example.com/upload', {
  file: './report.pdf',
  fields: { description: 'Monthly report' },
  onProgress: ({ percent }) => console.log(`${percent}%`),
});

Error Handling

// superagent
try {
  await superagent.get('https://api.example.com/missing');
} catch (error) {
  console.log(error.status);    // 404
  console.log(error.response);  // response object
  console.log(error.message);   // "Not Found"
}

// Rezo -- structured errors with codes and recovery
import rezo, { RezoError } from 'rezo';

try {
  await rezo.get('https://api.example.com/missing');
} catch (error) {
  if (rezo.isRezoError(error)) {
    console.log(error.code);           // "REZ_HTTP_ERROR"
    console.log(error.status);         // 404
    console.log(error.isClientError);  // true
    console.log(error.isTimeout);      // false
    console.log(error.suggestion);     // "Check that the URL exists..."
  }
}

Timeouts

// superagent
await superagent
  .get('https://api.example.com/slow')
  .timeout({ response: 5000, deadline: 30000 });

// Rezo -- granular staged timeouts
const { data } = await rezo.get('https://api.example.com/slow', {
  timeout: {
    connect: 3_000,
    headers: 5_000,
    body: 15_000,
    total: 30_000,
  }
});

Retry

// superagent
await superagent
  .get('https://api.example.com/flaky')
  .retry(3);

// Rezo -- full retry configuration
const { data } = await rezo.get('https://api.example.com/flaky', {
  retry: {
    limit: 3,
    backoff: { delay: 1000, maxDelay: 10_000 },
    statusCodes: [429, 500, 502, 503, 504],
  }
});

Redirects

// superagent
await superagent
  .get('https://example.com/old-page')
  .redirects(5);

// Rezo
const { data } = await rezo.get('https://example.com/old-page', {
  maxRedirects: 5,
});

What You Gain by Switching

TypeScript-First

superagent’s types are community-maintained @types/superagent. Rezo is written in strict TypeScript with generics, overloads, and discriminated unions.

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

const { data } = await rezo.get<User[]>('/api/users');
// data is User[] with full IDE autocomplete

HTTP/2

superagent does not support HTTP/2. Rezo provides a dedicated HTTP/2 adapter:

import rezo from 'rezo';
import http2Adapter from 'rezo/adapters/http2';

const client = rezo.create({ adapter: http2Adapter });

superagent requires the superagent-cookie plugin. Rezo includes a cookie jar with persistence:

import { Rezo, CookieJar } from 'rezo';

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

await client.postJson('https://example.com/login', { user: 'ada', pass: 'secret' });
const { data } = await client.get('https://example.com/dashboard');

jar.toJSON();      // export for persistence
jar.toNetscape();  // cURL-compatible format

Proxy Rotation

import { Rezo, ProxyManager } from 'rezo';

const client = rezo.create({
  proxyManager: new ProxyManager([
    'http://proxy1:8080',
    'socks5://proxy2:1080',
    'https://proxy3:3128',
  ]),
});
// Automatic rotation, health monitoring, failover

Stealth Mode

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

const client = rezo.create({
  stealth: new RezoStealth({ family: 'chrome', rotate: true }),
});

18 browser profiles with TLS fingerprinting, HTTP/2 SETTINGS emulation, and header ordering.

26 Lifecycle Hooks

const client = rezo.create({
  hooks: {
    beforeRequest: [(config) => {
      config.headers.set('X-Request-ID', crypto.randomUUID());
    }],
    afterResponse: [(response) => {
      console.log(`${response.status} in ${response.timing.total}ms`);
      return response;
    }],
    beforeRetry: [(config, error, ctx) => {
      console.log(`Retry #${ctx.retryCount}`);
    }],
  }
});

Streaming and Downloads

// Stream response
const response = await rezo.get('https://example.com/feed', {
  responseType: 'stream',
});

// Download with progress
await rezo.download('https://example.com/large-file.zip', {
  outputPath: './file.zip',
  onProgress: ({ percent, transferred, total }) => {
    console.log(`${percent}% (${transferred}/${total})`);
  }
});

Multi-Runtime Support

superagent works in Node.js and browsers. Rezo adds Deno, Bun, React Native, and edge runtimes with automatic adapter selection.

Web Crawler and Site Cloning

import { Crawler } from 'rezo/crawler';

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

for await (const result of crawler) {
  console.log(result.url, result.status);
}
import { Wget } from 'rezo/wget';

await new Wget({
  url: 'https://docs.example.com',
  outputDir: './mirror',
  convertLinks: true,
}).run();

Feature Comparison

FeatureRezosuperagent
Node.jsYesYes
BrowsersYesYes
Deno / EdgeYesNo
React NativeYesPartial
TypeScriptFirst-class strict typesCommunity types
HTTP/2YesNo
Cookie jarBuilt-inPlugin
Cookie persistenceJSON and NetscapeNo
Proxy supportBuilt-in (HTTP, HTTPS, SOCKS4, SOCKS5)Plugin
Proxy rotationBuilt-in with health monitoringNo
Stealth mode18 browser profilesNo
Lifecycle hooks26 hooksNo
InterceptorsRequest and responseNo
Retry with backoffFull (backoff, conditions, status codes)Basic (count only)
Staged timeoutsFull (connect, headers, body, total)Partial (response, deadline)
Downloads with progressBuilt-inNo
Uploads with progressBuilt-inNo
Request queueBuilt-in with rate limitingNo
Response cachingBuilt-inNo
DNS cachingBuilt-inNo
Web crawlerBuilt-inNo
Site cloningBuilt-inNo
cURL adapterYesNo
Error codes70+ with recovery suggestionsNone
Active maintenanceActiveMinimal