From Axios
If you know Axios, you already know Rezo. The API patterns are nearly identical — method signatures, interceptors, config merging, and error handling all work the same way. The difference is what ships out of the box: cookies, proxies, stealth, hooks, streaming, HTTP/2, and support for every JavaScript runtime.
Import Changes
// Axios
import axios from 'axios';
// Rezo -- same default export pattern
import rezo from 'rezo'; Instance Creation
// Axios
const client = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: { 'X-API-Key': 'abc123' },
});
// Rezo -- same pattern
const client = rezo.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: { 'X-API-Key': 'abc123' },
}); A simple timeout number works, but Rezo also supports staged timeouts with connect, headers, body, and total.
HTTP Methods
Every method you use in Axios works identically in Rezo:
// These are the same in both libraries
await client.get('/users');
await client.post('/users', { name: 'Ada' });
await client.put('/users/1', { name: 'Ada Lovelace' });
await client.patch('/users/1', { email: 'ada@example.com' });
await client.delete('/users/1');
await client.head('/users');
await client.options('/users'); Rezo also adds convenience methods for common content types:
// JSON with automatic Content-Type
await client.postJson('/users', { name: 'Ada' });
await client.putJson('/users/1', { name: 'Ada Lovelace' });
await client.patchJson('/users/1', { email: 'ada@example.com' });
// URL-encoded form
await client.postForm('/login', { user: 'ada', pass: 'secret' }); Interceptors
The interceptor API is identical:
// Axios
axios.interceptors.request.use(
(config) => {
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
},
(error) => Promise.reject(error)
);
axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
return refreshAndRetry(error.config);
}
return Promise.reject(error);
}
);
// Rezo -- same API
client.interceptors.request.use(
(config) => {
config.headers.set('Authorization', `Bearer ${getToken()}`);
return config;
},
(error) => Promise.reject(error)
);
client.interceptors.response.use(
(response) => response,
(error) => {
if (error.status === 401) {
return refreshAndRetry(error.config);
}
return Promise.reject(error);
}
); Rezo’s interceptors also support a runWhen predicate:
client.interceptors.request.use(
(config) => { /* ... */ return config; },
null,
{ runWhen: (config) => config.url.startsWith('/api/') }
); Error Handling
Axios errors carry response, request, and code. Rezo carries the same information plus boolean flags and recovery suggestions.
// Axios
try {
await axios.get('/api/data');
} catch (error) {
if (error.response) {
console.log(error.response.status);
console.log(error.response.data);
} else if (error.request) {
console.log('No response received');
} else {
console.log(error.message);
}
}
// Rezo
try {
await rezo.get('/api/data');
} catch (error) {
if (rezo.isRezoError(error)) {
console.log(error.code); // "REZ_HTTP_ERROR"
console.log(error.status); // 404
console.log(error.response?.data);
// Boolean flags -- no more manual status code checking
console.log(error.isTimeout); // false
console.log(error.isNetworkError); // false
console.log(error.isServerError); // false
console.log(error.isClientError); // true
// Recovery suggestion
console.log(error.suggestion); // "Check that the URL exists..."
}
} Query Parameters
// Axios
await axios.get('/users', {
params: { page: 2, limit: 25 },
paramsSerializer: (params) => qs.stringify(params),
});
// Rezo -- same pattern, custom serializer optional
await rezo.get('/users', {
params: { page: 2, limit: 25 },
}); Typed Responses
// Axios
const { data } = await axios.get<User[]>('/users');
// Rezo -- identical
const { data } = await rezo.get<User[]>('/users'); Cancel Requests
// Axios (modern)
const controller = new AbortController();
axios.get('/slow', { signal: controller.signal });
controller.abort();
// Rezo -- same AbortController pattern
const controller = new AbortController();
rezo.get('/slow', { signal: controller.signal });
controller.abort(); What You Gain by Switching
These are features Axios does not provide or requires third-party plugins to achieve.
Built-In Cookie Jar
Axios needs axios-cookiejar-support and tough-cookie to handle cookies. Rezo has a cookie jar built into every instance — no setup needed.
// Axios -- requires two extra packages
import axios from 'axios';
import { wrapper } from 'axios-cookiejar-support';
import { CookieJar } from 'tough-cookie';
const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
// Rezo -- cookies work automatically
const { data } = await rezo.get('https://example.com/login');
// Cookies from the response are stored and sent on subsequent requests
const { data: profile } = await rezo.get('https://example.com/profile'); If you need external control over the jar (exporting, importing, inspecting), you can pass one explicitly:
import { CookieJar } from 'rezo';
const jar = new CookieJar();
const client = rezo.create({ jar }); Proxy Manager
const client = rezo.create({
proxyManager: {
proxies: ['http://proxy1:8080', 'socks5://proxy2:1080'],
rotation: { strategy: 'random' },
autoDisableDeadProxies: true
}
}); Stealth Mode
import { RezoStealth } from 'rezo';
const client = rezo.create({
stealth: RezoStealth.chrome()
}); 26 Lifecycle Hooks
Beyond interceptors, Rezo provides hooks for DNS resolution, TCP connect, TLS handshake, redirects, retries, cookies, and more:
const client = rezo.create({
hooks: {
beforeRequest: [(config) => { /* ... */ }],
afterResponse: [(response) => { return response; }],
beforeRetry: [(config, error, ctx) => { /* ... */ }],
beforeRedirect: [(config, response) => { /* ... */ }],
afterCookie: [(cookies, config) => { /* ... */ }],
}
}); Streaming and Downloads
const download = await rezo.download(
'https://example.com/large-file.zip',
'./downloads/file.zip'
);
download.on('progress', (p) => console.log(`${p.percentage}%`)); HTTP/2
import rezo from 'rezo/adapters/http2';
const { data } = await rezo.get('https://api.example.com'); cURL Adapter
import rezo from 'rezo/adapters/curl';
const { data } = await rezo.get('https://api.example.com'); Staged Timeouts
const client = rezo.create({
timeout: {
connect: 5_000,
headers: 10_000,
body: 30_000,
total: 60_000,
}
}); Quick Migration Checklist
- Replace
import axios from 'axios'withimport rezo from 'rezo' - Replace
axios.create()withrezo.create() - Replace
error.response.statuswitherror.status - Replace header string assignments with
config.headers.set()in interceptors - Remove
axios-cookiejar-support— cookies are built in - Remove any retry plugins — use
retry: { limit: 3 }in config - Enjoy everything else that comes for free