npm package: @neilton2026/stealth-client
Description: HTTP client stealth com TLS, HTTP/2, fingerprint e Akamai solver
Latest version: 1.0.2

# 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 real
```

### Por 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.json
```

---

## Instalação

```bash
# Node.js >= 20 obrigatório
cd stealth-client
npm install
```

**Dependê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

```typescript
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`)

```typescript
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`)

```typescript
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`)

```typescript
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:

```typescript
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 `impit` só suporta `chrome` e `firefox` como perfis TLS nativos.

---

## Gerenciamento de Cookies

O `SessionManager` persiste cookies automaticamente entre requests — igual a um browser real:

```typescript
// 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

```typescript
// 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:6MXehUM45Xi1KDRa@proxy.bestproxy.com:2312',
});
```

> **Atenção:** O `impit` tem problemas conhecidos com proxies HTTP autenticados em algumas versões. Se der `TunnelUnsuccessful`, 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):

```typescript
// 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:**
1. Extrai a URL do script `/_bm/...` do HTML da página
2. Baixa o script com cache (não baixa de novo na mesma sessão)
3. Pega o cookie `bm_sz` da sessão (seed do algoritmo)
4. Monta payload com dados do perfil (UA, screen, WebGL, canvas hash, fonts, plugins)
5. Gera o `sensor_data` encriptado via `akamai-v3-sensor-data-helper`
6. Refaz o request original com o `sensor_data` e o header `akamai-bmsc-token`

---

## Exemplo Completo — Fluxo com múltiplos requests

```typescript
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

```bash
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 typecheck
```

---

## Testar 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 `timeout` nas opções
- Verificar se o proxy está funcionando
- Testar sem proxy para isolar

### `StealthError: REQUEST_FAILED — TunnelUnsuccessful`
- Bug do `impit` com 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: false` se 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-platform` manualmente
- 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 `browser` e `os`

### Cloudflare bloqueando POSTs mesmo com GET passando
- Cloudflare valida `__cf_bm` e `cf_clearance` separadamente para POSTs
- `__cf_bm` é coletado automaticamente no GET e reenviado nos POSTs via cookie
- `cf_clearance` requer execução de JS real (precisa de Playwright/FlareSolverr)
- Solução sem browser real: só é possível se o `__cf_bm` for 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`:

```typescript
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.ts
```

**Regras para não ser detectado:**
1. Sempre faça o GET da página antes dos POSTs — coleta cookies de sessão
2. Não adicione headers que o Chrome real não envia (`X-Forwarded-For`, `Via`, etc.)
3. Não sobrescreva `sec-ch-ua`, `User-Agent`, `Sec-Fetch-*` — o cliente gera tudo correto
4. Se o site pede `Referer` nos POSTs, passe via `headers: { Referer: 'URL' }` nas opções
5. Use `locale: 'en-US'` para sites americanos (o `Accept-Language` precisa bater com o alvo)
6. Evite múltiplos requests rápidos — o `humanDelay` (800-2500ms) só é aplicado no Akamai solver; implemente seus próprios delays se necessário