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.

Overview

The Stealth API helps your browser automation avoid detection by:
  • Hiding automation indicators
  • Rotating browser fingerprints
  • Masking WebDriver presence
  • Randomizing user agent and headers
Stealth features help make automated browsers appear more like real user browsers.

Get Stealth Status

Check current stealth configuration.
GET /stealth/status
curl http://localhost:9867/stealth/status | jq .

Response (200 OK)

{
  "enabled": true,
  "level": "full",
  "features": {
    "hideWebDriver": true,
    "chromeRuntime": true,
    "permissions": true,
    "navigator": true,
    "plugins": true,
    "languages": true,
    "webGL": true,
    "audioContext": true
  },
  "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
  "platform": "MacIntel"
}

Response Fields

enabled
boolean
required
Whether stealth mode is active
level
string
required
Stealth level: light or full
features
object
required
Enabled stealth features
userAgent
string
required
Current user agent string
platform
string
required
Browser platform identifier

Rotate Fingerprint

Generate a new browser fingerprint.
POST /fingerprint/rotate
curl -X POST http://localhost:9867/fingerprint/rotate | jq .

Response (200 OK)

{
  "rotated": true,
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
  "platform": "Win32",
  "languages": ["en-US", "en"],
  "vendor": "Google Inc.",
  "webGLVendor": "Intel Inc.",
  "webGLRenderer": "Intel Iris OpenGL Engine"
}

Response Fields

rotated
boolean
required
Whether fingerprint was successfully rotated
userAgent
string
required
New user agent string
platform
string
required
New platform (Win32, MacIntel, Linux x86_64)
languages
array
required
Browser language preferences
vendor
string
required
Navigator vendor
webGLVendor
string
WebGL vendor string
webGLRenderer
string
WebGL renderer string

Stealth Levels

light

Basic stealth with minimal fingerprint changes:
  • Hides navigator.webdriver
  • Patches Chrome runtime
  • Randomizes basic headers
Best for: General automation where detection risk is low.

full

Comprehensive stealth with extensive fingerprinting:
  • All light features
  • Randomizes navigator properties
  • Spoofs plugins and permissions
  • Modifies WebGL fingerprint
  • Randomizes audio context
  • Custom canvas fingerprint
Best for: High-security scenarios, avoiding sophisticated detection.
Configure stealth level via environment variable or config file when starting PinchTab.

Stealth Features

hideWebDriver

Removes navigator.webdriver flag.
// Without stealth
console.log(navigator.webdriver);  // true

// With stealth
console.log(navigator.webdriver);  // undefined

chromeRuntime

Patches window.chrome.runtime to appear as normal Chrome browser.

permissions

Spoofs Permissions API to return realistic values. Randomizes navigator properties:
  • platform
  • vendor
  • hardwareConcurrency
  • deviceMemory

plugins

Adds realistic plugin list (e.g., PDF Viewer, Chrome PDF Plugin).

languages

Sets realistic language preferences.

webGL

Randomizes WebGL fingerprint to avoid tracking.

audioContext

Modifies AudioContext fingerprint.

Complete Example

import requests
import time

BASE = "http://localhost:9867"

# Check stealth status
resp = requests.get(f"{BASE}/stealth/status")
status = resp.json()
print(f"Stealth enabled: {status['enabled']}")
print(f"Level: {status['level']}")

# Rotate fingerprint
resp = requests.post(f"{BASE}/fingerprint/rotate")
fingerprint = resp.json()
print(f"\nNew fingerprint:")
print(f"User Agent: {fingerprint['userAgent']}")
print(f"Platform: {fingerprint['platform']}")

# Start instance with new fingerprint
inst = requests.post(f"{BASE}/instances/start",
    json={"mode": "headed"}).json()

# Open tab
tab = requests.post(f"{BASE}/instances/{inst['id']}/tabs/open",
    json={"url": "https://bot.sannysoft.com"}).json()

tab_id = tab["tabId"]

# Wait for page to load
time.sleep(5)

# Check detection
resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": "navigator.webdriver === undefined"
})
no_webdriver = resp.json()["result"]
print(f"\nWebDriver hidden: {no_webdriver}")

# Take screenshot to verify
resp = requests.get(
    f"{BASE}/tabs/{tab_id}/screenshot?raw=true&quality=90"
)
with open("stealth_test.jpg", "wb") as f:
    f.write(resp.content)

print("Screenshot saved to stealth_test.jpg")

# Cleanup
requests.post(f"{BASE}/instances/{inst['id']}/stop")

Fingerprint Rotation Strategy

Per-Session Rotation

Rotate fingerprint for each new session:
def create_stealth_session():
    # Rotate fingerprint
    requests.post("http://localhost:9867/fingerprint/rotate")
    
    # Start instance
    inst = requests.post("http://localhost:9867/instances/start",
        json={"mode": "headless"}).json()
    
    return inst["id"]

# Each session gets new fingerprint
session1 = create_stealth_session()
session2 = create_stealth_session()

Periodic Rotation

Rotate fingerprint periodically during long-running sessions:
import time
import threading

def rotate_periodically(interval_seconds=3600):
    """Rotate fingerprint every hour"""
    while True:
        time.sleep(interval_seconds)
        resp = requests.post("http://localhost:9867/fingerprint/rotate")
        print(f"Fingerprint rotated: {resp.json()['userAgent']}")

# Start rotation thread
thread = threading.Thread(target=rotate_periodically, args=(3600,))
thread.daemon = True
thread.start()

Detection Testing

Test your stealth configuration against detection tools:

Bot Detection Sites

detection_sites = [
    "https://bot.sannysoft.com",
    "https://arh.antoinevastel.com/bots/areyouheadless",
    "https://pixelscan.net",
    "https://www.browserscan.net"
]

for site in detection_sites:
    # Navigate
    requests.post(f"{BASE}/tabs/{tab_id}/navigate",
        json={"url": site, "waitFor": "networkidle"})
    
    time.sleep(3)
    
    # Take screenshot
    name = site.split("//")[1].replace("/", "_")
    resp = requests.get(f"{BASE}/tabs/{tab_id}/screenshot?raw=true")
    
    with open(f"detection_{name}.jpg", "wb") as f:
        f.write(resp.content)
    
    print(f"Tested: {site}")

Check WebDriver Flag

resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
    "expression": """
        ({
            webdriver: navigator.webdriver,
            plugins: navigator.plugins.length,
            languages: navigator.languages,
            platform: navigator.platform,
            vendor: navigator.vendor
        })
    """
})

result = resp.json()["result"]
print("Detection check:")
print(f"  webdriver: {result['webdriver']}")  # Should be undefined
print(f"  plugins: {result['plugins']}")      # Should be > 0
print(f"  platform: {result['platform']}")

Best Practices

Enable Stealth Early

Configure stealth before starting instances:
# Set environment variable
export STEALTH_LEVEL=full
pinchtab

Rotate Between Sessions

# ✅ Good: New fingerprint per task
for task in tasks:
    requests.post(f"{BASE}/fingerprint/rotate")
    run_task(task)

# ❌ Bad: Same fingerprint for all tasks
for task in tasks:
    run_task(task)

Combine with Proxies

Use stealth with rotating proxies for maximum anonymity:
# Rotate both fingerprint and proxy
requests.post(f"{BASE}/fingerprint/rotate")
inst = requests.post(f"{BASE}/instances/start", json={
    "mode": "headless",
    "proxy": get_next_proxy()
})

Test Regularly

def test_stealth(tab_id):
    """Test if stealth is working"""
    resp = requests.post(f"{BASE}/tabs/{tab_id}/evaluate", json={
        "expression": "navigator.webdriver === undefined"
    })
    
    if not resp.json()["result"]:
        print("WARNING: WebDriver detected!")
        return False
    
    print("Stealth check passed")
    return True

Limitations

  • Stealth reduces detection risk but doesn’t guarantee invisibility
  • Some sophisticated detection methods may still identify automation
  • Stealth features may impact performance slightly
  • Not all websites can be fooled by stealth techniques

What Stealth Can’t Hide

  • Network patterns (same IP, timing)
  • Mouse movement patterns
  • Behavioral analysis
  • Server-side detection

Mitigation

Combine stealth with:
  • Proxy rotation
  • Random delays
  • Human-like mouse movements
  • Varied browsing patterns

Configuration

Set stealth level via environment variable:
# Light stealth
STEALTH_LEVEL=light pinchtab

# Full stealth (recommended)
STEALTH_LEVEL=full pinchtab

# Disable stealth
STEALTH_LEVEL=none pinchtab
Or in config file (~/.pinchtab/config.yaml):
stealth:
  enabled: true
  level: full

Next Steps

Authentication

Secure your API

Cookies

Manage cookies and sessions

Navigation

Navigate with stealth

Profiles

Use profiles for state persistence