Skip to content

Latest commit

Β 

History

History
79 lines (54 loc) Β· 6.45 KB

File metadata and controls

79 lines (54 loc) Β· 6.45 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

Camoufox is an anti-detect fork of Firefox for web scraping and automation. This repo is not the Firefox source β€” it is a build system that fetches upstream Firefox, applies a stack of patches + code additions, and produces a hardened, fingerprint-spoofing browser. The distinguishing design choice is that fingerprint spoofing happens at the C++/Juggler implementation level, not via injected JavaScript, so it is invisible to page-side inspection.

The actual Firefox tree lives in camoufox-<version>-<release>/ (e.g. camoufox-150.0.2-beta.25/), created by the build. That directory is generated β€” never edit it directly to make lasting changes; changes there are captured as patches (see "Making patches" below).

upstream.sh pins version / release, and is sourced+exported by the Makefile, so those variables flow into every script.

Build commands

The build system is designed for Linux. Windows and macOS binaries are cross-compiled from Linux β€” they are never built natively. (scripts/install-deps.sh covers macOS/Linux host dependencies for local make dir + bootstrap experimentation; a full production build path is Linux/Docker.)

bash scripts/install-deps.sh   # install host build deps (Python β‰₯3.11, Rust, aria2, p7zip, go, msitools, wget, sqlite)
make dir                       # fetch Firefox source, extract, copy additions/settings, apply all patches β†’ touches _READY
make bootstrap                 # install system deps (apt/dnf/pacman) + run `mach bootstrap` (one-time)
make build                     # ./mach build in the source dir
make run                       # run the built browser (wipes ~/.camoufox profile)
make run args="--headless https://test.com"
python3 multibuild.py --target linux windows macos --arch x86_64 arm64 i686   # full cross-platform build + package

make dir is the pipeline that matters: setup (fetch tarball via aria2c β†’ extract β†’ copy-additions.sh) β†’ python3 scripts/patch.py (applies every patch, writes mozconfig) β†’ _READY. mach requires Python β‰₯ 3.11 (stdlib tomllib); older python3 crashes with ModuleNotFoundError: No module named 'tomllib'.

Docker is the portable path: docker build -t camoufox-builder . then docker run -v "$(pwd)/dist:/app/dist" camoufox-builder --target <os> --arch <arch>.

Packaging: make package-linux|package-macos|package-windows arch=<arch> (wraps scripts/package.py). Launcher (Go): make build-launcher arch=<arch> os=<os>.

Working with patches (the core workflow)

Almost all browser-behavior changes are patches/*.patch (~49 patches: fingerprint-injection.patch, webgl-spoofing.patch, navigator-spoofing.patch, webrtc-ip-spoofing.patch, the playwright/ and librewolf/ and ghostery/ subdirs, etc.). Do not hand-edit patch files.

Use the developer UI instead:

make edits          # launches scripts/developer.py β€” apply/undo/create/manage patches
  • New patch: in the UI "Reset workspace" β†’ edit files in camoufox-*/ β†’ make build / make run to test β†’ "Write workspace to patch".
  • Edit existing patch: "Edit a patch" (resets workspace to that patch's state) β†’ edit β†’ "Write workspace to patch" to overwrite.

Low-level equivalents: make patch ./patches/x.patch, make unpatch ./patches/x.patch, make workspace ./patches/x.patch, make revert (reset to unpatched tag), make diff (diff against first-checkpoint). The source dir is a git repo with unpatched / first-checkpoint / checkpoint tags used by these targets.

Repository layout (the parts that require cross-file understanding)

  • patches/ β€” the diffs applied to Firefox source. This is where browser behavior is changed.
  • additions/ β€” whole files copied into the source tree (not diffs) by scripts/copy-additions.sh:
    • additions/camoucfg/ β€” the C++ config layer. MaskConfig.hpp reads the spoofing config (from CAMOU_CONFIG env var / camoufox.cfg) that the patches consult at the C++ level; MouseTrajectories.hpp is the human-cursor algorithm.
    • additions/juggler/ β€” Camoufox's patched Juggler (Firefox's Playwright automation protocol, the Firefox analog of CDP). This is where Playwright is made undetectable β€” the page agent runs in an isolated scope so injected automation JS is not visible to the page.
  • settings/ β€” camoufox.cfg, chrome.css, properties.json, camoucfg.jvv, prefs/policies. Copied into the source's lw/ dir by copy-additions.sh. Edit the built config with make edit-cfg.
  • scripts/ β€” patch.py (the patcher, LibreWolf-derived), developer.py (the make edits UI), package.py, copy-additions.sh, install-deps.sh.
  • pythonlib/ β€” the camoufox PyPI package: the Playwright-compatible Python interface that generates + injects fingerprints via BrowserForge and launches the binary. fingerprint-presets-v150.json holds real scraped fingerprints. This is the user-facing API; the browser binary is the backend.
  • jsonvv/ β€” JSON-with-validation format library used for camoucfg.jvv (config schema).
  • legacy/launcher/ β€” Go launcher binary.
  • assets/ β€” base.mozconfig and other build inputs.

Testing

Two suites, both required for PRs (they cover different layers):

  • build-tester/ β€” tests the raw binary directly (bypasses the Python package); fingerprints injected via generate_context_fingerprint + addInitScript and CAMOU_CONFIG. Run when changing patches / C++ / JS browser layer:
    cd build-tester && npm install && pip install -r requirements.txt
    python scripts/run_tests.py /path/to/camoufox-binary
  • service-tester/ β€” tests the Python package / service layer.
  • tests/ β€” Playwright tests, run via make tests (add headful=true for headful): points at camoufox-*/obj-*/dist/bin/camoufox-bin.

ccache is enabled in the build config β€” install it for fast incremental rebuilds (cold ~40 min, incremental ~5 min).

Constraints when editing this repo

  • The camoufox-*/ source directory is regenerated β€” persist changes as patches, never as edits committed to that tree.
  • Keep the Makefile diff clean against main unless a change genuinely belongs there β€” dependency setup lives in scripts/install-deps.sh, not the Makefile.
  • Every PR must be tied to a GitHub issue and pass both test suites (see CONTRIBUTING.md).