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 }); Built-In Cookie Jar
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
| Feature | Rezo | superagent |
|---|---|---|
| Node.js | Yes | Yes |
| Browsers | Yes | Yes |
| Deno / Edge | Yes | No |
| React Native | Yes | Partial |
| TypeScript | First-class strict types | Community types |
| HTTP/2 | Yes | No |
| Cookie jar | Built-in | Plugin |
| Cookie persistence | JSON and Netscape | No |
| Proxy support | Built-in (HTTP, HTTPS, SOCKS4, SOCKS5) | Plugin |
| Proxy rotation | Built-in with health monitoring | No |
| Stealth mode | 18 browser profiles | No |
| Lifecycle hooks | 26 hooks | No |
| Interceptors | Request and response | No |
| Retry with backoff | Full (backoff, conditions, status codes) | Basic (count only) |
| Staged timeouts | Full (connect, headers, body, total) | Partial (response, deadline) |
| Downloads with progress | Built-in | No |
| Uploads with progress | Built-in | No |
| Request queue | Built-in with rate limiting | No |
| Response caching | Built-in | No |
| DNS caching | Built-in | No |
| Web crawler | Built-in | No |
| Site cloning | Built-in | No |
| cURL adapter | Yes | No |
| Error codes | 70+ with recovery suggestions | None |
| Active maintenance | Active | Minimal |