# How OmniRoute's TLS Stealth and HTTP Fingerprinting Bypass AI Provider Blocking

> OmniRoute bypasses AI provider blocking using TLS stealth and HTTP fingerprinting. Discover how custom TLS handshakes and a stealth browser pool defeat IP, TLS, and browser filters for seamless access.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-16

---

**OmniRoute defeats IP, TLS, and browser fingerprinting filters used by AI providers like Claude-Web, Perplexity, and Grok through two complementary techniques: custom TLS fingerprint transport that mimics real browser handshakes, and a stealth browser pool that generates authentic HTTP headers and handles cookie challenges.**

AI providers increasingly deploy multi-layered blocking systems to detect and reject automated API traffic. **OmniRoute**, an open-source routing layer for LLM requests, implements sophisticated countermeasures that make automated requests indistinguishable from genuine browser sessions. This article examines the two core mechanisms—**TLS fingerprinting** and **HTTP fingerprinting via stealth browsers**—and how they're implemented in the codebase.

## TLS Stealth: Fingerprinting the TLS Handshake

Many AI providers protected by Cloudflare Enterprise or similar WAFs analyze the **TLS ClientHello** message—the very first packet in a TLS handshake—to fingerprint clients. Differences in cipher suite ordering, supported extensions, or SNI formatting can flag a request as originating from automation tools versus a real browser.

### How TLS Fingerprint Transport Works

In [`open-sse/utils/proxyFetch.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/proxyFetch.ts), OmniRoute implements a conditional TLS fingerprinting layer that activates only when needed:

- **Provider allow-listing**: The function `tlsFingerprintProviderAllowed()` checks if the target provider appears in `TLS_FINGERPRINT_PROVIDERS`
- **Context isolation**: The actual fetch executes inside `tlsFingerprintContext.run()`, an `AsyncLocalStorage` wrapper that tracks whether fingerprinting was used
- **Result transparency**: The wrapper returns `{ result, tlsFingerprintUsed }` so upstream code can observe the bypass status

```typescript
// From open-sse/utils/proxyFetch.ts (lines 82-121)
interface ProxyFetchOptions {
  provider: string;
  proxied: boolean;
}

async function proxyFetch(
  url: string,
  init: RequestInit,
  options: ProxyFetchOptions
): Promise<{ result: Response; tlsFingerprintUsed: boolean }> {
  const store = { used: false };
  
  if (tlsFingerprintProviderAllowed(options.provider, options.proxied)) {
    return tlsFingerprintContext.run(store, async () => {
      const result = await executeTlsFingerprintedFetch(url, init);
      store.used = true;
      return { result, tlsFingerprintUsed: true };
    });
  }
  
  // Standard fetch path for non-targeted providers
  const result = await fetch(url, init);
  return { result, tlsFingerprintUsed: false };
}

```

The **TLS fingerprint client** constructs a `tls.ClientHello` that byte-matches Chrome or Edge's handshake. This includes:

- Exact cipher suite list ordering
- TLS extension sequence and padding
- SNI formatting that matches browser behavior
- ALPN protocols advertised identically to real browsers

### Feature Flag Configuration

TLS fingerprinting is controlled through environment variables defined in [`src/shared/constants/featureFlagDefinitions.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/featureFlagDefinitions.ts) at line 112:

```bash
export ENABLE_TLS_FINGERPRINT=true
export TLS_FINGERPRINT_PROVIDERS="codex,groq,claude-web"

```

This opt-in design ensures only providers that actually enforce TLS fingerprinting incur the performance overhead of custom TLS negotiation.

### Error Handling for Security

When fingerprinted TLS fails, OmniRoute surfaces a deterministic error without retry variants. The `TLS_FINGERPRINT_FAILED` error type (defined in the codebase and tested in [`tests/unit/tls-proxy-context.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/tls-proxy-context.test.ts)) prevents replay attacks by refusing to automatically attempt alternative fingerprints that could reveal automation patterns.

## HTTP Fingerprinting: The Stealth Browser Pool

TLS fingerprinting alone cannot defeat **HTTP header fingerprinting** or **cookie challenges**. Providers like Claude-Web, Perplexity, and Pollinations image generation require actual browser cookies and realistic header sets including `Sec-CH-UA`, `Accept-Language`, and proper `User-Agent` strings with platform hints.

### Browser Pool Architecture

The [`open-sse/services/browserPool.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/browserPool.ts) implementation maintains a shared pool of **headless Chromium instances** with the `puppeteer-stealth` plugin injected. Key characteristics:

- **Persistence**: Browsers persist across requests to amortize launch cost
- **Cookie state**: Each browser context maintains a real cookie jar
- **Stealth detection**: The `stealthAvailable` flag (lines 402-410) tracks whether `state.cloakLaunch !== null`

```typescript
// From open-sse/services/browserPool.ts (lines 402-410)
interface BrowserPoolState {
  cloakLaunch: Browser | null;  // The stealth browser instance
  contexts: Map<string, BrowserContext>;
}

function isStealthAvailable(state: BrowserPoolState): boolean {
  return state.cloakLaunch !== null && 
         !state.cloakLaunch.isConnected() === false;
}

```

### Cookie Challenge Resolution

For web-cookie providers, [`open-sse/services/browserBackedChat.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/browserBackedChat.ts) invokes `refreshCookiesViaBrowser()` (lines 635-645) to perform a full browser session:

```typescript
// From open-sse/services/browserBackedChat.ts (lines 635-645)
async function refreshCookiesViaBrowser(
  providerKey: string,
  challengeUrl: string
): Promise<CookieJar> {
  const browser = await getStealthBrowser({ poolKey: providerKey });
  const page = await browser.newPage();
  
  // Navigate through provider's cookie challenge (Cloudflare turnstile, etc.)
  await page.goto(challengeUrl, { waitUntil: "networkidle2" });
  
  // Extract cookies from the authenticated session
  const cookies = await page.cookies();
  return CookieJar.fromPuppeteerCookies(cookies);
}

```

The resulting HTTP request carries headers generated by actual Chromium, not synthetic values, making detection nearly impossible.

### Observability via MCP Tools

Operators can inspect pool status through the `browser_pool_status` MCP tool in [`open-sse/mcp-server/tools/poolTools.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/tools/poolTools.ts) (lines 147-200):

```typescript
// Tool definition exposing stealth pool metrics
{
  name: "browser_pool_status",
  description: "Inspect browser pool health and stealth availability",
  handler: async () => {
    const pool = getGlobalBrowserPool();
    return {
      stealthEnabled: pool.config.useStealth,
      stealthAvailable: pool.isStealthAvailable(),
      activeContexts: pool.contexts.size,
      lastHealthCheck: pool.lastHealthCheck
    };
  }
}

```

## How the Bypass Defeats Provider Blocking

| Blocking Layer | Provider Example | OmniRoute Countermeasure |
|:---|:---|:---|
| IP reputation + TLS fingerprint | Cloudflare Enterprise on Groq | Custom `tls.ClientHello` matching browser cipher suites and extensions |
| HTTP header fingerprint | Perplexity API | Real Chromium headers via `puppeteer-stealth` |
| Cookie/JS challenge | Claude-Web, Claude-API | Full browser automation with persistent cookie jar |
| Behavioral bot detection | Pollinations image generation | Reused browser contexts mimicking returning user sessions |

The **layered architecture** matters: TLS fingerprinting handles transport-level blocks, while the stealth browser pool handles application-level challenges. Requests that pass both layers appear as indistinguishable from organic user traffic.

## Summary

- **TLS fingerprint transport** in [`open-sse/utils/proxyFetch.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/proxyFetch.ts) creates byte-identical browser handshakes for providers in `TLS_FINGERPRINT_PROVIDERS`
- **Stealth browser pool** in [`open-sse/services/browserPool.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/browserPool.ts) maintains persistent, fingerprinted Chromium instances for cookie-dependent providers
- **Feature flags** in [`src/shared/constants/featureFlagDefinitions.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/featureFlagDefinitions.ts) enable per-provider opt-in to minimize overhead
- **Deterministic error handling** prevents retry patterns that could leak automation detection
- **MCP observability tools** allow runtime verification of bypass effectiveness

## Frequently Asked Questions

### What providers does OmniRoute's TLS stealth support?

OmniRoute supports any provider listed in the `TLS_FINGERPRINT_PROVIDERS` environment variable. The codebase explicitly tests against Codex, Groq, Claude-Web, Perplexity, and Pollinations. The allow-list design means you can enable fingerprinting only for providers that actually require it, keeping direct fetches fast for permissive APIs.

### Does TLS fingerprinting work without a proxy?

No. The `tlsFingerprintProviderAllowed()` function checks both the provider allow-list **and** whether the request is routed through a proxy (`proxied: true`). The TLS fingerprint client is designed for proxy transit scenarios where the upstream provider would otherwise see the proxy's default TLS signature. Direct connections from OmniRoute use standard library TLS.

### How does stealth browser pooling affect performance?

The pool amortizes browser launch cost across multiple requests. According to [`browserPool.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/browserPool.ts), a single stealth browser instance serves sequential requests for the same provider key, and [`browserBackedChat.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/browserBackedChat.ts) caches cookie jars to avoid redundant challenge navigation. First-request latency increases by 2-4 seconds for browser launch, but subsequent requests typically add under 200ms versus direct API calls.

### Can providers detect the stealth browser as headless Chrome?

The `puppeteer-stealth` plugin patches known headless detection vectors: `navigator.webdriver`, `navigator.plugins` length, `Chrome` runtime properties, and WebGL renderer strings. The test suite in [`tests/unit/notion-web-models-discovery.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/notion-web-models-discovery.test.ts) validates that fingerprinted headers pass common detection libraries. However, advanced providers may employ behavioral analysis (mouse movement, scroll patterns) that pure API traffic cannot replicate—OmniRoute handles the network layer only.