Skip to content

Stealth Mode

The stealth feature replaces the default reqwest HTTP client with wreq, which spoofs TLS fingerprints and HTTP/2 settings to mimic real browsers. Combined with BrowserConfig::stealth(), it also patches JavaScript APIs (navigator, plugins, webGL) that bot-detection systems probe.

Build requirements

The stealth feature compiles BoringSSL from source. You need cmake and nasm on your build machine:

  • Ubuntu/Debian: sudo apt install cmake nasm
  • macOS: brew install cmake nasm
  • Windows: install via cmake.org and nasm.us

Experimental dependency status

Kumo's stealth feature uses wreq for TLS/HTTP2 browser fingerprint emulation and wreq-util for named browser profiles such as Chrome 131, Firefox 128, Safari 18, and Edge 127. Keep stealth behind an explicit feature flag and prefer the standard HTTP or browser fetchers unless you specifically need TLS fingerprint emulation.

Release gate

The published wreq-util crate metadata is currently copyleft-licensed (GPL-3.0 on the 2.x line and LGPL-3.0 on the 3.x release candidates). Review that license before enabling stealth in redistributable binaries.

Installation

kumo = { version = "0.3", features = ["stealth"] }

Migration Notes

Kumo 0.3.14 migrated the optional stealth fetcher from rquest to wreq because the previously locked rquest version was yanked. The public Kumo API is unchanged: keep using StealthHttpFetcher, StealthProfile, or CrawlEngine::builder().stealth(...) as before. Runtime TLS/HTTP2 fingerprints now come from wreq and wreq-util, so validate stealth behavior against your target sites after upgrading.

HTTP-Level Stealth

StealthHttpFetcher sends requests with a realistic TLS ClientHello and HTTP/2 SETTINGS frame:

use kumo::prelude::*;

CrawlEngine::builder()
    .stealth(StealthProfile::Chrome131)   // spoof Chrome 131 TLS/H2 fingerprint
    .run(MySpider)
    .await?;

Available profiles:

Profile Mimics
StealthProfile::Chrome131 Chrome 131 on Windows 10
StealthProfile::Firefox128 Firefox 128 LTS
StealthProfile::Safari18 Safari 18 on macOS Sequoia
StealthProfile::Edge127 Microsoft Edge 127

Browser-Level Stealth

When combined with the browser feature, BrowserConfig::stealth() also patches JavaScript APIs:

kumo = { version = "0.3", features = ["stealth", "browser"] }
CrawlEngine::builder()
    .browser(
        BrowserConfig::headless()
            .stealth()       // patch navigator, plugins, webGL, etc.
    )
    .run(MySpider)
    .await?;

When to Use Stealth

Use stealth when the target site:

  • Returns 403 or CAPTCHA to requests with non-browser TLS fingerprints (common with Cloudflare, Akamai, PerimeterX)
  • Checks navigator.webdriver or navigator.plugins in JavaScript

For most sites, standard HTTP with a realistic User-Agent header is sufficient. Stealth adds significant build time and is only needed for bot-detection-hardened sites.