Skip to content

Latest commit

Β 

History

History
144 lines (108 loc) Β· 5.57 KB

File metadata and controls

144 lines (108 loc) Β· 5.57 KB

Camoufox Service Tests

End-to-end antibot-detection tests that verify a pip-installed camoufox release works correctly β€” both the Firefox binary and the Python package β€” using real proxies for each browser context.

Prerequisites

  • Python 3.9+
  • Node.js (for building the TypeScript checks bundle via esbuild)
  • At least one proxy in proxies.txt

Quick Start

# 1. Add your proxies (see format below)
# 2. Run the test script β€” it handles everything else automatically
./run_tests.sh

run_tests.sh will:

  1. Install npm deps in ../build-tester/ (for esbuild, first run only)

  2. Create a .venv virtualenv (first run only)

  3. Build a wheel from ../pythonlib and install it (tests the actual packaged artifact)

  4. Phase 1 β€” run the suite against the locally compiled binary, auto-detected from:

    • macOS: ../camoufox-*/obj-*-apple-darwin/dist/Camoufox.app/Contents/MacOS/camoufox
    • Linux: ../camoufox-*/obj-*-linux-*/dist/bin/camoufox-bin

    Skipped (with a notice) if no local build is found. On macOS, the script also copies properties.json from Camoufox.app/Contents/Resources/ into MacOS/ so pythonlib can locate it next to the binary.

  5. Phase 2 β€” download the official binary (--browser-version, default official/stable) and run the suite against it

  6. Exit 0 only if both phases pass

Use --binary local or --binary fetched to run only one phase.

Heads-up on Phase 2: if the latest official/stable is much older than the local pythonlib (e.g. v135 binary vs pythonlib targeting v149+), the binary may not understand newer fingerprint patches and the test page can fail to produce results. Pin a newer binary with --browser-version to avoid this.

Proxies

Tests require real proxies. Each context gets its own proxy, and the WebRTC IP is automatically derived from the proxy server address.

Create proxies.txt in this directory with one proxy per line:

user:pass@domain:port

Example:

alice:secret123@proxy1.example.com:10000
bob:hunter2@proxy2.example.com:10000
alice:secret123@proxy1.example.com:10001
  • Blank lines and lines starting with # are ignored
  • Proxies are assigned round-robin across the 6 test profiles
  • Fewer proxies than profiles is fine β€” they cycle
  • 127.0.0.1 and localhost are bypassed automatically so the local test-page server stays reachable

Manual Setup

If you prefer to run steps individually:

# Install build-tester deps (once)
cd ../build-tester && npm install && cd ../service-tester

# Create and activate virtualenv
python3 -m venv .venv
source .venv/bin/activate

# Build wheel from local source and install it
pip install build
(cd ../pythonlib && rm -rf dist && python -m build --wheel -o dist)
pip install --force-reinstall ../pythonlib/dist/*.whl

# Download the browser binary
python -m camoufox fetch

# Run tests
python run_tests.py

Options

./run_tests.sh [options]
python run_tests.py [options]

  --browser-version VER   Camoufox version specifier (default: official/stable)
                          e.g. official/prerelease/146.0.1-beta.50
  --profile-count N       Number of profiles to test (1-6, default: 6)
  --proxies PATH          Path to proxies file (default: proxies.txt)
  --headful               Run with visible browser window
  --no-cert               Skip certificate generation
  --save-cert PATH        Save certificate text to a file
  --secret KEY            HMAC signing key for the certificate
  --binary MODE           Which binary to test: local | fetched | both (default: both)
                          (run_tests.sh only β€” orchestrates the two phases)
  --executable-path PATH  Run against a specific binary path
                          (run_tests.py only β€” used internally by phase 1)

What It Tests

6 browser contexts run simultaneously β€” 3 macOS profiles and 3 Linux profiles β€” each with:

  • A unique fingerprint generated by camoufox via BrowserForge (navigator, screen, WebGL, fonts, voices, audio/canvas seeds)
  • A distinct timezone
  • Its own proxy, with WebRTC ICE candidates spoofed to the proxy's IP

Each context is scored across these categories:

Category What it checks
Automation Detection Playwright/CDP artefacts
JS Engine V8 vs SpiderMonkey signals
Lie Detection Inconsistent property overrides
Firefox APIs Firefox-specific API presence
Cross-Signal Consistency across navigator, screen, etc.
CSS Fingerprint CSS rendering fingerprint
Canvas Noise Canvas hash uniqueness and stability
WebGL Render WebGL rendering hash
Audio Integrity AudioContext fingerprint
Font Platform OS-consistent font availability
Speech Voices Voice list matches declared OS
WebRTC IP matches proxy server address
Stability Fingerprint stable over time with other contexts open
Headless Detection No headless mode signals

Interpreting Results

Grade Meaning
A All checks pass
B 1–2 failures (minor)
C 3–5 failures
D 6–10 failures
F 11+ failures

A grade of A or B exits with code 0. Anything worse exits with code 1.

The cross-profile uniqueness section confirms each context has distinct audio, canvas, timezone, and screen fingerprints β€” verifying camoufox generates genuinely different identities per context.

Failure Triage

If a check fails, fix it in the Python package (../pythonlib/camoufox/), not in the test. The test is intentionally a black-box validator β€” it only uses the public AsyncNewContext API and trusts camoufox to produce correct fingerprints.