@neilton2026/stealth-client
v1.0.2
Published
HTTP client stealth com TLS, HTTP/2, fingerprint e Akamai solver
Readme
StealthClient — Documentação Completa
Cliente HTTP stealth em TypeScript que impersona um browser Chrome real para bypassar detecções de bot (Cloudflare, Akamai, Datadome, Shape Security).
Arquitetura — 3 Camadas
StealthClient
├── fingerprint-generator (Apify) → Headers + fingerprint browser coerentes (rede Bayesiana)
├── impit (Rust / napi-rs) → TLS JA3/JA4 + HTTP/2 Akamai frame order idênticos ao Chrome
└── akamai-v3-sensor-data-helper → Resolve JS challenge do Akamai sem browser realPor que cada camada existe
| Camada | O que resolve |
|--------|---------------|
| fingerprint-generator | Garante que UA, sec-ch-ua, screen, WebGL e navigator são internamente consistentes — bot detectors cruzam esses valores |
| impit | TLS handshake idêntico ao Chrome real (JA3/JA4). Node.js padrão usa OpenSSL que é detectado por Cloudflare, Akamai etc. |
| akamai-v3-sensor-data-helper | Sites com Akamai Bot Manager exigem sensor_data gerado por JS executado no browser. Esta lib faz o reverse do algoritmo |
Estrutura de Arquivos
stealth-client/
├── src/
│ ├── stealth-client.ts # Classe principal — ponto de entrada
│ ├── types/index.ts # Todos os tipos TypeScript
│ ├── core/
│ │ ├── tls-client.ts # Wrapper do impit (TLS/HTTP2)
│ │ └── session.ts # Gerenciador de cookies e perfil de sessão
│ ├── profiles/
│ │ └── browser-profiles.ts # Geração de perfil + headers Chrome/Firefox
│ └── solvers/
│ └── akamai.ts # Solver do Akamai sensor_data
├── examples/
│ ├── fingerprint-test.ts # Testa fingerprint completo (TLS, headers, Cloudflare)
│ └── usage.ts # Exemplo de uso básico
├── package.json
└── tsconfig.jsonInstalação
# Node.js >= 20 obrigatório
cd stealth-client
npm installDependências principais:
| Pacote | Versão | Função |
|--------|--------|--------|
| impit | ^0.8.0 | TLS fingerprint (Rust nativo) |
| fingerprint-generator | ^2.1.81 | Geração de fingerprint coerente |
| akamai-v3-sensor-data-helper | ^1.0.0 | Resolver Akamai JS challenge |
| tsx | ^4.19.0 | Roda TypeScript direto sem build |
Uso Básico
import { StealthClient } from '../src/stealth-client.js';
const client = new StealthClient({
browser: 'chrome', // 'chrome' | 'firefox' | 'safari' | 'edge'
os: 'windows', // 'windows' | 'macos' | 'linux' | 'android' | 'ios'
locale: 'en-US', // idioma dos headers Accept-Language
});
// GET simples
const res = await client.get('https://site.com/pagina');
console.log(res.status, res.body);
// POST JSON
const post = await client.post('https://site.com/api', {
campo1: 'valor1',
campo2: 'valor2',
});
// POST com corpo customizado e headers extras
const post2 = await client.post('https://site.com/api', { data: 'x' }, {
headers: { 'X-Custom': 'valor' },
timeout: 15_000,
});Opções do Construtor (StealthClientOptions)
interface StealthClientOptions {
browser?: 'chrome' | 'firefox' | 'safari' | 'edge'; // default: 'chrome'
os?: 'windows' | 'macos' | 'linux' | 'android' | 'ios'; // default: 'windows'
locale?: string; // default: 'pt-BR' (ex: 'en-US', 'es-MX')
proxyUrl?: string; // ex: 'http://user:pass@host:port'
timeout?: number; // default: 30000 (ms)
solveAkamai?: boolean; // default: true — resolve sensor_data automaticamente
followRedirects?: boolean; // default: true
}Opções de Request (RequestOptions)
interface RequestOptions {
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
headers?: Record<string, string>; // headers adicionais (mesclados com os do perfil)
body?: string | URLSearchParams | Record<string, unknown>;
timeout?: number;
followRedirects?: boolean;
}Resposta (StealthResponse)
interface StealthResponse {
status: number; // HTTP status code
statusText: string; // ex: 'OK', 'Forbidden'
headers: Record<string, string>; // headers da resposta (lowercase)
cookies: Cookie[]; // cookies recebidos nesse request
body: string; // corpo da resposta como string
elapsed: number; // tempo do request em ms
url: string; // URL final (após redirects)
json<T>(): T; // parse do body como JSON (lança StealthError se inválido)
}Headers Gerados Automaticamente
GET (navegação principal)
sec-ch-ua: "Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/145.0.0.0 ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,...
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US
Priority: u=0, i
Cookie: <cookies automáticos da sessão>POST / AJAX (XHR interno da página)
sec-ch-ua: "Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/145.0.0.0 ...
Content-Type: application/json
Accept: */*
Origin: https://dominio-do-site.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,pt;q=0.9,...
Referer: <URL passada como referer>
Cookie: <cookies automáticos da sessão>IMPORTANTE: Nunca adicione
User-Agent,sec-ch-ua,Sec-Fetch-*manualmente. O cliente já gera tudo consistente. Só adicione headers extras específicos do site (ex:X-Requested-With, tokens customizados).
Fingerprint Gerado (Browser Profile)
O fingerprint-generator (Apify) usa uma rede Bayesiana treinada em dados reais de browsers. Cada execução gera um perfil diferente mas sempre internamente consistente:
const profile = client.getProfile();
profile.fingerprint.userAgent // 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/145 ...'
profile.fingerprint.screen // { width: 1920, height: 1080, colorDepth: 32, pixelDepth: 32, devicePixelRatio: 1 }
profile.fingerprint.navigator // { hardwareConcurrency: 16, deviceMemory: 8, platform: 'Win32', ... }
profile.fingerprint.webGl // { vendor: 'Google Inc. (NVIDIA)', renderer: 'ANGLE (NVIDIA ...)', ... }
profile.fingerprint.fonts // ['Arial', 'Calibri', 'Times New Roman', ...]
profile.meta.browserVersion // '145.0.0.0'
profile.meta.os // 'windows'TLS e HTTP/2 Fingerprint
O impit (binding Rust via napi-rs) substitui o stack TLS padrão do Node.js:
| Campo | Valor | Significado |
|-------|-------|-------------|
| JA4 | t13d1516h2_8daaf6152771_02713d6af862 | Chrome real no Windows |
| HTTP | http/2 | HTTP/2 com frame order do Chrome |
| TLS | TLSv1.3 | TLS 1.3 obrigatório |
| kex | X25519MLKEM768 | Key exchange do Chrome 130+ |
Edge/Safari são mapeados internamente para o fingerprint TLS do Chrome. O
impitsó suportachromeefirefoxcomo perfis TLS nativos.
Gerenciamento de Cookies
O SessionManager persiste cookies automaticamente entre requests — igual a um browser real:
// Cookies são coletados automaticamente em cada resposta
const res = await client.get('https://site.com');
// Próximo request já envia os cookies recebidos
// Injetar cookies manualmente (ex: sessão exportada do browser)
client.addCookies([
{
name: '__cf_bm',
value: 'abc123...',
domain: 'site.com',
path: '/',
secure: true,
httpOnly: true,
}
]);
// Ver todos os cookies da sessão
const stats = client.getSessionStats();
console.log(stats.cookieCount, stats.requestCount, stats.ageMs);Usando Proxy
// Proxy HTTP com autenticação
const client = new StealthClient({
proxyUrl: 'http://usuario:senha@host:porta',
});
// Proxy residencial (formato comum)
const client2 = new StealthClient({
proxyUrl: 'http://bp-sqsp1cakhi6w_area-US:[email protected]:2312',
});Atenção: O
impittem problemas conhecidos com proxies HTTP autenticados em algumas versões. Se derTunnelUnsuccessful, tente sem proxy primeiro para isolar o problema.
Akamai Bot Manager
O solver do Akamai é ativado automaticamente quando o cliente detecta um challenge (status 403 com corpo específico ou presença de /_bm/ na resposta):
// solveAkamai: true por default — funciona automaticamente
const client = new StealthClient({ solveAkamai: true });
const res = await client.get('https://site-com-akamai.com');
// Se receber challenge, o solver: baixa o JS do Akamai, gera sensor_data, refaz o request
// Desativar se o site não usa Akamai (evita overhead)
const client2 = new StealthClient({ solveAkamai: false });O que o solver faz internamente:
- Extrai a URL do script
/_bm/...do HTML da página - Baixa o script com cache (não baixa de novo na mesma sessão)
- Pega o cookie
bm_szda sessão (seed do algoritmo) - Monta payload com dados do perfil (UA, screen, WebGL, canvas hash, fonts, plugins)
- Gera o
sensor_dataencriptado viaakamai-v3-sensor-data-helper - Refaz o request original com o
sensor_datae o headerakamai-bmsc-token
Exemplo Completo — Fluxo com múltiplos requests
import { StealthClient } from '../src/stealth-client.js';
async function main() {
const client = new StealthClient({
browser: 'chrome',
os: 'windows',
locale: 'en-US',
proxyUrl: 'http://user:pass@proxy:8080', // opcional
timeout: 30_000,
});
// 1. GET inicial — coleta cookies de sessão (CSRF, __cf_bm, ASP.NET_SessionId etc.)
const page = await client.get('https://site.com/pagina-inicial');
console.log('GET status:', page.status);
console.log('Cookies coletados:', client.getSessionStats().cookieCount);
// 2. Extrair token CSRF do HTML se necessário
const csrfMatch = page.body.match(/name="__RequestVerificationToken" value="([^"]+)"/);
const csrfToken = csrfMatch?.[1] ?? '';
// 3. POST com dados — cookies da sessão são enviados automaticamente
const result = await client.post('https://site.com/api/acao', {
campo1: 'valor1',
campo2: 'valor2',
__RequestVerificationToken: csrfToken,
}, {
headers: {
'Referer': 'https://site.com/pagina-inicial',
},
});
console.log('POST status:', result.status);
console.log('Resposta:', result.body);
}
main().catch(console.error);Executar os Exemplos
cd stealth-client
# Testar fingerprint completo (TLS, headers, Cloudflare trace)
npx tsx examples/fingerprint-test.ts
# Exemplo de uso básico
npx tsx examples/usage.ts
# Build TypeScript (gera dist/)
npm run build
# Verificar tipos sem buildar
npm run typecheckTestar se o Fingerprint Está Correto
Use estes endpoints para verificar:
| URL | O que verifica |
|-----|----------------|
| https://tls.browserleaks.com/json | JA3, JA4, TLS version, cipher suites |
| https://www.cloudflare.com/cdn-cgi/trace | UA, HTTP version, TLS, localização, warp |
| https://httpbin.org/headers | Headers enviados exatamente como o servidor recebe |
| https://api.ip.cc | IP do proxy (ou IP real se sem proxy) |
Resultado esperado (Chrome real no Windows):
JA4: t13d1516h2_8daaf6152771_02713d6af862
HTTP: http/2
TLS: TLSv1.3
kex: X25519MLKEM768
uag: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/145.0.0.0 ...Erros Comuns e Soluções
StealthError: TIMEOUT
- Aumentar
timeoutnas opções - Verificar se o proxy está funcionando
- Testar sem proxy para isolar
StealthError: REQUEST_FAILED — TunnelUnsuccessful
- Bug do
impitcom proxies HTTP autenticados - Solução: testar com outro proxy ou sem proxy
StealthError: AKAMAI_SOLVE_FAILED — bm_sz não encontrado
- O GET inicial não retornou o cookie
bm_sz - O site pode não usar Akamai v3 ou a URL está errada
- Solução:
solveAkamai: falsese o site não usa Akamai
StealthError: REQUEST_FAILED — Http2 INTERNAL_ERROR
- O servidor detectou o fingerprint HTTP/2
- Pode ser que o site use Akamai v2 que verifica o frame order com mais rigor
- Solução: testar com
browser: 'firefox'
Headers sec-ch-ua inconsistentes com User-Agent
- NUNCA sobrescreva
sec-ch-ua,sec-ch-ua-mobile,sec-ch-ua-platformmanualmente - Esses valores são gerados pela rede Bayesiana para bater com o UA gerado
- Se precisar de uma versão específica do Chrome, mude nas opções
browsereos
Cloudflare bloqueando POSTs mesmo com GET passando
- Cloudflare valida
__cf_bmecf_clearanceseparadamente para POSTs __cf_bmé coletado automaticamente no GET e reenviado nos POSTs via cookiecf_clearancerequer execução de JS real (precisa de Playwright/FlareSolverr)- Solução sem browser real: só é possível se o
__cf_bmfor suficiente para o site em questão
Limitações Conhecidas
| Limitação | Motivo | Solução |
|-----------|--------|---------|
| JS fingerprint (canvas, WebGL real) | Requer GPU física e contexto de browser | Playwright com fingerprint-injector |
| cf_clearance (Cloudflare JS Challenge completo) | Requer execução de JS no browser | FlareSolverr ou Playwright headless |
| reCAPTCHA v2/v3 | Challenge humano | API de solvers: nextcaptcha, 2captcha, capmonster |
| Sites com behavioral analytics avançado | Monitoram mouse, scroll, timing de teclas | Só bypass com browser real + fingerprint injetado |
Adicionando um Novo Script de Automação
Crie em examples/meu-script.ts:
import { StealthClient } from '../src/stealth-client.js';
const client = new StealthClient({
browser: 'chrome',
os: 'windows',
locale: 'en-US',
});
// seu código aqui
// Executar:
// npx tsx examples/meu-script.tsRegras para não ser detectado:
- Sempre faça o GET da página antes dos POSTs — coleta cookies de sessão
- Não adicione headers que o Chrome real não envia (
X-Forwarded-For,Via, etc.) - Não sobrescreva
sec-ch-ua,User-Agent,Sec-Fetch-*— o cliente gera tudo correto - Se o site pede
Referernos POSTs, passe viaheaders: { Referer: 'URL' }nas opções - Use
locale: 'en-US'para sites americanos (oAccept-Languageprecisa bater com o alvo) - Evite múltiplos requests rápidos — o
humanDelay(800-2500ms) só é aplicado no Akamai solver; implemente seus próprios delays se necessário
