Stealth Overview
Rezo’s stealth module makes your HTTP requests indistinguishable from real browser traffic. Anti-bot systems like Cloudflare, Akamai, and DataDome identify automated clients by analyzing TLS fingerprints (JA3/JA4), HTTP/2 SETTINGS frames, header ordering, and client hints. RezoStealth controls all of these signals, presenting a consistent browser identity across every request.
How It Works
When you attach a RezoStealth instance to a Rezo client, it resolves a complete browser profile that governs:
- TLS fingerprint — cipher suites, signature algorithms, ECDH curves, ALPN protocols, all in exact browser order
- HTTP/2 SETTINGS —
HEADER_TABLE_SIZE,INITIAL_WINDOW_SIZE,MAX_CONCURRENT_STREAMS, and connection window size matching the target browser - Header ordering — headers sent in the exact order a real browser would send them
- Client hints —
sec-ch-ua,sec-ch-ua-platform,sec-ch-ua-mobilefor Chromium browsers - Sec-Fetch metadata —
sec-fetch-site,sec-fetch-mode,sec-fetch-user,sec-fetch-dest - Navigator properties — consistent
platform,hardwareConcurrency,deviceMemory,maxTouchPoints
The RezoStealth Class
import { Rezo } from 'rezo';
import { RezoStealth } from 'rezo/stealth'; The constructor accepts an optional input that determines which browser profile to use:
// Auto-detect from the User-Agent header in your config
const stealth = new RezoStealth();
// Use a specific named profile
const stealth = new RezoStealth('chrome-131');
// Random profile from a browser family
const stealth = new RezoStealth({ family: 'chrome' });
// Random profile from a family with a specific platform
const stealth = new RezoStealth({ family: 'chrome', platform: 'windows' });
// Rotate to a fresh identity on every request
const stealth = new RezoStealth({ rotate: true });
// Rotate within a family
const stealth = new RezoStealth({ rotate: true, family: 'firefox' }); Modes of Operation
Exact Profile
Pass a profile name string to use a specific browser version:
const rezo = new Rezo({
stealth: new RezoStealth('chrome-131')
});
const res = await rezo.get('https://example.com');
// All requests use Chrome 131 fingerprint, headers, and TLS settings Family Random
Pass a family option to pick a random version within that browser family:
const rezo = new Rezo({
stealth: new RezoStealth({ family: 'firefox' })
});
// Picks one of: firefox-115, firefox-121, firefox-128, firefox-133 Full Random
Omit profile and family to get a completely random browser profile:
const rezo = new Rezo({
stealth: RezoStealth.random()
});
// Could be any of the 18 available profiles Auto-Detect from User-Agent
Construct with no arguments. The stealth module parses your User-Agent header and selects the closest matching profile:
const rezo = new Rezo({
stealth: new RezoStealth(),
headers: {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
});
// Detects Chrome 131 from the UA and uses chrome-131 profile Rotate Per Request
Enable rotate: true to generate a fresh browser identity for every resolve() call. This is concurrency-safe — each request gets its own profile:
const rezo = new Rezo({
stealth: new RezoStealth({ rotate: true })
});
// Request 1: might use safari-18.2 on macOS
await rezo.get('https://example.com/page1');
// Request 2: might use chrome-128 on Windows
await rezo.get('https://example.com/page2'); You can constrain rotation to a family:
const rezo = new Rezo({
stealth: new RezoStealth({ rotate: true, family: 'chrome' })
});
// Every request picks a random Chrome version Factory Methods
RezoStealth provides static factories for common configurations:
// Specific profile by name
const stealth = RezoStealth.from('safari-17.4');
// Random within a family
const stealth = RezoStealth.chrome(); // random Chrome profile
const stealth = RezoStealth.firefox(); // random Firefox profile
const stealth = RezoStealth.safari(); // random Safari profile
const stealth = RezoStealth.edge(); // random Edge profile
// Fully random from any browser
const stealth = RezoStealth.random();
// Auto-detect from a User-Agent string
const stealth = RezoStealth.fromUserAgent(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15'
);
// Returns a Safari 18.2 stealth profile Integration with Rezo
Pass the stealth instance in the Rezo constructor options:
import { Rezo } from 'rezo';
import { RezoStealth } from 'rezo/stealth';
const client = new Rezo({
stealth: RezoStealth.chrome(),
baseURL: 'https://protected-site.com'
});
// All requests now use Chrome TLS fingerprint, header order, client hints, etc.
const response = await client.get('/api/data'); Overriding Specific Values
Use RezoStealthOptions to selectively override parts of a profile while keeping the rest intact:
const rezo = new Rezo({
stealth: new RezoStealth({
profile: 'chrome-131',
platform: 'macos',
language: 'fr-FR,fr;q=0.9,en;q=0.8',
headers: {
'accept-language': 'fr-FR,fr;q=0.9'
}
})
}); Reading Resolved Values
After resolution, you can inspect the stealth profile:
const stealth = RezoStealth.chrome();
console.log(stealth.profileName); // e.g. "chrome-128"
console.log(stealth.profile.family); // "chrome"
console.log(stealth.profile.engine); // "blink" Runtime Considerations
Bun Runtime
Bun uses BoringSSL (the same TLS library as Chrome), which means it can produce a Chrome-like JA3/JA4 fingerprint natively. Stealth with Bun works against virtually all TLS fingerprinting systems.
Node.js Runtime
Node.js uses OpenSSL, which cannot produce a Chrome-like JA3/JA4 fingerprint regardless of cipher configuration. For production stealth against advanced anti-bot systems (Cloudflare, Akamai, DataDome), consider using curl-impersonate via the cURL adapter, which patches BoringSSL for Chrome-identical TLS behavior.
Stealth on Node.js still provides correct header ordering, client hints, HTTP/2 SETTINGS, and User-Agent management — it only falls short on the TLS fingerprint itself.