Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pinchtab/pinchtab/llms.txt

Use this file to discover all available pages before exploring further.

PinchTab includes built-in stealth features to help bypass bot detection systems and rotate browser fingerprints.

Overview

Stealth mode provides:
  • WebDriver property hiding
  • User agent rotation
  • Canvas fingerprint noise
  • Plugin spoofing
  • WebGL vendor override
  • Timezone and language spoofing
  • Hardware metrics randomization
Stealth features are automatically injected into every page load via Chrome DevTools Protocol

Stealth Levels

Configure stealth intensity via environment variable:
# Light (default) - Minimal overhead
BRIDGE_STEALTH=light pinchtab

# Medium - Balanced protection
BRIDGE_STEALTH=medium pinchtab

# Full - Maximum stealth (slower)
BRIDGE_STEALTH=full pinchtab
// Source: docs/references/configuration.md:22-27
// BRIDGE_STEALTH options:
// - light:  Basic patches (default, minimal overhead)
// - medium: More aggressive patches (some overhead)
// - full:   Maximum stealth (significant overhead, slowest)

Stealth Score

Get current stealth status:
curl http://localhost:9867/stealth/status | jq .
Response:
{
  "level": "high",
  "score": 93,
  "features": {
    "automation_controlled": true,
    "webdriver_hidden": true,
    "chrome_headless_new": true,
    "user_agent_override": true,
    "webgl_vendor_override": true,
    "plugins_spoofed": true,
    "languages_spoofed": true,
    "webrtc_leak_prevented": true,
    "timezone_spoofed": true,
    "canvas_noise": true,
    "font_spoofing": true,
    "hardware_concurrency": true,
    "device_memory": true
  },
  "chrome_flags": [
    "--disable-features=IsolateOrigins",
    "--disable-site-isolation-trials",
    "--disable-web-security"
  ],
  "headless_mode": false,
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
  "recommendations": [
    "Stealth mode is well configured"
  ]
}
// Source: internal/handlers/stealth.go:109-121
stealthScore := (enabledCount * 100) / len(features)

switch {
case stealthScore >= 80:
    level = "high"
case stealthScore >= 50:
    level = "medium"
case stealthScore >= 30:
    level = "basic"
default:
    level = "minimal"
}

Stealth Features

WebDriver Detection Prevention

Hides navigator.webdriver property:
// Without stealth:
navigator.webdriver === true  // Bot detected!

// With stealth:
navigator.webdriver === undefined  // Looks like real browser
// Source: internal/bridge/init.go:147-178
// Stealth script injected on every page:
stealthSeed := rand.Intn(1000000000)
seededScript := fmt.Sprintf(
    "var __pinchtab_seed = %d;\nvar __pinchtab_stealth_level = %q;\n",
    stealthSeed, cfg.StealthLevel
) + assets.StealthScript

// Inject via CDP:
if _, err := page.AddScriptToEvaluateOnNewDocument(stealthScript).Do(ctx); err != nil {
    return fmt.Errorf("failed to inject stealth script: %w", err)
}

Plugin Spoofing

Populates navigator.plugins with realistic fake plugins:
// Without stealth (headless):
navigator.plugins.length === 0  // Suspicious!

// With stealth:
navigator.plugins.length === 5  // PDF, Flash, etc.

Canvas Fingerprinting Protection

Adds noise to canvas operations:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.fillText('test', 10, 10);
const data = canvas.toDataURL();
// Returns slightly different hash each time (noise applied)
Canvas noise is subtle enough to pass fingerprinting but prevent exact matching

Chrome Runtime Injection

Defines window.chrome.runtime to mimic real Chrome:
// Without stealth:
window.chrome === undefined  // Not Chrome!

// With stealth:
window.chrome.runtime !== undefined  // Looks like Chrome

Fingerprint Rotation

Dynamically change browser fingerprint mid-session:

Rotate User Agent

# Rotate to Windows Chrome
curl -X POST http://localhost:9867/fingerprint/rotate \
  -H "Content-Type: application/json" \
  -d '{
    "tabId": "tab_abc123",
    "os": "windows",
    "browser": "chrome"
  }'
Response:
{
  "status": "rotated",
  "fingerprint": {
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "platform": "Win32",
    "vendor": "Google Inc.",
    "screenWidth": 1920,
    "screenHeight": 1080,
    "language": "en-US",
    "timezoneOffset": -300,
    "cpuCores": 8,
    "memory": 8
  }
}

Supported Platforms

// Source: internal/handlers/stealth.go:266-291
osConfigs := map[string]map[string]fingerprint{
    "windows": {
        "chrome": {
            UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
            Platform:  "Win32",
            Vendor:    "Google Inc.",
        },
        "edge": {
            UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)... Edg/...",
            Platform:  "Win32",
        },
    },
    "mac": {
        "chrome": {
            UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
            Platform:  "MacIntel",
        },
        "safari": {
            UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)... Safari/...",
            Platform:  "MacIntel",
            Vendor:    "Apple Computer, Inc.",
        },
    },
}

Windows Chrome

Most common desktop fingerprint

Windows Edge

Alternative Windows browser

macOS Chrome

macOS with Chrome

macOS Safari

Native macOS browser

Random Fingerprint

# Let PinchTab choose randomly (70% Windows, 30% Mac)
curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{"tabId": "tab_abc123", "os": "random"}'
// Source: internal/handlers/stealth.go:293-300
os := req.OS
if os == "random" {
    if rand.Float64() < 0.7 {
        os = "windows"  // 70% chance
    } else {
        os = "mac"      // 30% chance
    }
}

Screen Resolution Rotation

Randomize screen dimensions:
// Source: internal/handlers/stealth.go:315-328
screens := [][]int{
    {1920, 1080},  // Full HD
    {1366, 768},   // Laptop
    {1536, 864},   // HD+
    {1440, 900},   // MacBook
    {2560, 1440},  // QHD
}

if req.Screen == "random" {
    screen := screens[rand.Intn(len(screens))]
    fp.ScreenWidth = screen[0]
    fp.ScreenHeight = screen[1]
}

Hardware Randomization

// Source: internal/handlers/stealth.go:342-343
fp.CPUCores = 4 + rand.Intn(4)*2  // 4, 6, 8, 10, 12
fp.Memory = 4 + rand.Intn(4)*2    // 4, 6, 8, 10, 12 GB

Complete Rotation Example

#!/bin/bash

# Start instance
INST=$(pinchtab instance start --mode headless | jq -r .id)

# Create tab
TAB=$(curl -s -X POST http://localhost:9867/instances/$INST/tabs/open | jq -r .tabId)

# Initial fingerprint (default)
curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"navigator.userAgent"}' | jq -r .result
# Mozilla/5.0 (X11; Linux x86_64)...

# Rotate to Windows
curl -s -X POST http://localhost:9867/fingerprint/rotate \
  -d '{
    "tabId":"'$TAB'",
    "os":"windows",
    "browser":"chrome",
    "screen":"random"
  }'

# Verify new fingerprint
curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"navigator.userAgent"}' | jq -r .result
# Mozilla/5.0 (Windows NT 10.0; Win64; x64)...

curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"navigator.platform"}' | jq -r .result
# Win32

curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"screen.width"}' | jq -r .result
# 1536 (randomized)

Fingerprint Persistence

1

Apply fingerprint

POST /fingerprint/rotate sets CDP overrides
2

Inject script

JavaScript overrides screen/hardware properties
3

Navigate

New pages inherit fingerprint automatically
4

Persist until rotation

Fingerprint remains until next rotation or tab close
// Source: internal/handlers/stealth.go:204-221
// CDP-level override (persists across navigations):
err := emulation.SetUserAgentOverride(fp.UserAgent).
    WithPlatform(fp.Platform).
    WithAcceptLanguage(fp.Language).
    Do(ctx)

// JavaScript override (re-injected on each page):
script := fmt.Sprintf(`
  Object.defineProperty(screen, 'width', { get: () => %d });
  Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => %d });
`, fp.ScreenWidth, fp.CPUCores)

page.AddScriptToEvaluateOnNewDocument(script).Do(ctx)

Chrome Version Preservation

Fingerprint rotation preserves Chrome version:
// Source: tests/integration/config_test.go:104-107
// Chrome version is preserved after fingerprint rotation
// (fingerprint rotation should preserve Chrome version from BRIDGE_CHROME_VERSION)
if initialVersion != rotatedVersion {
    t.Errorf("expected Chrome version to be preserved")
}
Before rotation:
Chrome/120.0.6099.109
After rotation:
Chrome/120.0.6099.109  (same version)
This ensures consistency and avoids detection based on version mismatches

Stealth Recommendations

Get personalized recommendations:
// Source: internal/handlers/stealth.go:147-173
func (h *Handlers) getStealthRecommendations(features map[string]bool) []string {
    recommendations := []string{}
    
    if !features["user_agent_override"] {
        recommendations = append(recommendations, "Enable user agent rotation")
    }
    if !features["canvas_noise"] {
        recommendations = append(recommendations, "Add canvas fingerprint noise")
    }
    if !features["webrtc_leak_prevented"] {
        recommendations = append(recommendations, "Block WebRTC to prevent IP leaks")
    }
    // ...
    
    if len(recommendations) == 0 {
        recommendations = append(recommendations, "Stealth mode is well configured")
    }
    
    return recommendations
}

Testing Stealth

Verify stealth features are working:
# Navigate to bot detection test site
curl -X POST http://localhost:9867/tabs/$TAB/navigate \
  -d '{"url":"https://bot.sannysoft.com"}'

sleep 3

# Check WebDriver detection
curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"navigator.webdriver"}' | jq .result
# null (not detected)

# Check plugins
curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"navigator.plugins.length"}' | jq .result
# 5 (spoofed)

# Check chrome runtime
curl -s -X POST http://localhost:9867/tabs/$TAB/evaluate \
  -d '{"expression":"typeof window.chrome"}' | jq .result
# "object" (injected)

Performance Impact

Stealth Overhead

LevelOverheadUse Case
light~5%Default, production
medium~15%Moderate detection
full~30%Aggressive detection

Optimize Performance

# Use light stealth for speed
BRIDGE_STEALTH=light pinchtab

# Only rotate fingerprint when needed
# (Don't rotate on every navigation)

Common Workflows

Rotate Per Target

# Different fingerprint for each target site
curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{"tabId":"'$TAB1'","os":"windows"}'

curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{"tabId":"'$TAB2'","os":"mac"}'

Periodic Rotation

# Rotate every N requests
for i in {1..10}; do
  if [ $((i % 5)) -eq 0 ]; then
    curl -X POST http://localhost:9867/fingerprint/rotate \
      -d '{"tabId":"'$TAB'","os":"random"}'
  fi
  
  # Make request
  curl -X POST http://localhost:9867/tabs/$TAB/navigate \
    -d '{"url":"https://example.com/page'$i'"}'
done

Best Practices

Use Realistic Fingerprints

Good:
# Common combinations
curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{"os":"windows","browser":"chrome"}'
Bad:
# Unusual combination (raises suspicion)
{"os":"mac","browser":"edge"}  # Edge rarely used on Mac

Match Fingerprint to Target

# Scraping US sites
curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{
    "os":"windows",
    "language":"en-US",
    "timezone":-300
  }'

# Scraping EU sites
curl -X POST http://localhost:9867/fingerprint/rotate \
  -d '{
    "os":"windows",
    "language":"de-DE",
    "timezone":-60
  }'

Combine with Profiles

# Use persistent profile + fingerprint rotation
pinchtab profile create stealth-profile
INST=$(curl -s -X POST http://localhost:9867/instances/start \
  -d '{"profileId":"stealth-profile"}' | jq -r .id)

# Cookies persist across fingerprint rotations

Next Steps

Browser Profiles

Combine stealth with persistent sessions

Headless Mode

Run stealth in headless mode

Common Patterns

Advanced anti-detection techniques

Stealth API

Complete stealth API reference