Files
camoufox/pythonlib/camoufox/fpgen.yml
T
Jake WriterandClaude Opus 5.5 a3dbe40d1a fix: stop generating a canvas seed, and drop config keys nothing reads
The browser has not noised the canvas since #528, and no patch reads
canvas:seed (#721). The launcher still drew one on every launch and sent it
through CAMOU_CONFIG, and NewContext called a setCanvasSeed that does not
exist. They no longer do.

For users this changes nothing on any browser since #528: the value was
ignored. A config that still passes canvas:seed gets the usual "Skipping
unknown patch" notice instead of silence. On a browser from before #528, the
launcher no longer turns canvas noise on, which is the behaviour #528 chose.

The same audit found more keys declared in settings/properties.json that no
patch or Juggler file reads, so setting them did nothing:
- canvas:aaOffset, canvas:aaCapOffset
- memorysaver, pdfViewerEnabled, webrtc:localipv4/6
- navigator.onLine, navigator.cookieEnabled, navigator.languages
- navigator.appCodeName, appName, product, productSub. Firefox reports these
  constants itself, so fpgen.yml no longer maps them.
- webGl:parameters:blockIfNotDefined and its WebGL2 twin

test_config_schema now checks this direction too: every declared key must be
read by the browser, unless it is listed with a reason. Three are listed:
locale:script and navigator.doNotTrack, which the launcher applies itself,
and navigator.buildID (#780).

The build-tester grading followed the same wrong premise. It tracked canvas
collisions as an unfixed per-context leak. A canvas that is rendered rather
than noised follows the fonts and GPU, as it does on real machines, so canvas
collisions are now counted with the other device-level values. The tribal rule
that recorded it as an open question is now a settled one,
canvas-is-not-noised, with an automated check.

Closes #721.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:22:28 -06:00

69 lines
3.0 KiB
YAML

# Mappings of fpgen fingerprints to Camoufox config properties.
#
# fpgen (scrapfly/fingerprint-generator) replaced BrowserForge/Apify as the
# generator. The field set below is the one BrowserForge used to supply -- the
# rest of what fpgen carries (fonts, voices, WebGL parameters, system styles,
# permissions, RTC capabilities, audio) is NOT mapped here yet; Camoufox still
# draws those from its own catalogues. Wiring those through is the follow-up.
#
# Shape differences from browserforge.yml:
# - window geometry is its own `window` node, not part of `screen`
# - header values are lists
# - there is no extraProperties.globalPrivacyControl; GPC is a pref Camoufox
# owns (see utils.launch_options), so nothing maps to it
# - doNotTrack is deliberately NOT mapped: Camoufox sets DNT from its own
# config, and a drawn value is stripped unless the caller asked for one
navigator:
# fpgen's UAs trail the current release; the version is rewritten to the
# Camoufox Firefox version in _cast_to_properties.
userAgent: navigator.userAgent
appVersion: navigator.appVersion
oscpu: navigator.oscpu
platform: navigator.platform
hardwareConcurrency: navigator.hardwareConcurrency
# Never override productSub (#105)
# deviceMemory is not in Firefox, and fpgen reports the string "undefined"
# Locale is handled separately (locale:*)
maxTouchPoints: navigator.maxTouchPoints
screen:
availLeft: screen.availLeft
availTop: screen.availTop
availWidth: screen.availWidth
availHeight: screen.availHeight
height: screen.height
width: screen.width
colorDepth: screen.colorDepth
pixelDepth: screen.pixelDepth
window:
outerHeight: window.outerHeight
outerWidth: window.outerWidth
# innerWidth/innerHeight are deliberately NOT mapped.
#
# Spoofing them deadlocks Playwright: setViewportSize resizes the window and
# then waits for the page to report the size it asked for, and a spoofed
# innerWidth/innerHeight never changes, so the wait never ends. Camoufox
# already defaults to no_viewport for this reason (#666); this is the same
# trap reached through an explicit set_viewport_size() call.
#
# BrowserForge hid it by accident -- its Firefox samples carry innerWidth and
# innerHeight as 0, and _cast_to_properties skips falsy values, so these were
# never spoofed there either. fpgen reports the real numbers, which turned an
# unmapped field into a hang (tests/patches/humanize-edge-deadlock.py, which
# calls set_viewport_size, timed out at 600s in CI).
#
# Leaving them real is also the more coherent answer: the content area a page
# measures is then the one it actually has, which is what makes input at the
# bottom edge land (see BROWSER_CHROME_HEIGHT in coherence.py).
screenX: window.screenX
screenY: window.screenY
pageYOffset: screen.pageYOffset
# devicePixelRatio is not mapped: any value but 1 is a spoofing tell unless
# the whole geometry is scaled with it.
headers:
# accept-language is redundant with locale:*, user-agent with navigator.userAgent
accept-encoding: headers.Accept-Encoding