#776·camoufox

Juggler mouse events have an empty PointerEvent.pointerType in v152.0.4-beta.30

Author: ma-ponyCreated Sep 14, 2026Updated Sep 14, 2026

Describe the bug

page.mouse.move(), down(), and up() produce trusted pointer events whose pointerType is "", although the input is explicitly a mouse. Applications that branch on event.pointerType === "mouse" consequently miss these events.

This reproduces through the official from camoufox.sync_api import Camoufox entry point on an ordinary local HTML fixture. Camoufox prepares the launch parameters and manages browser cleanup. No external website, proxy, or custom fingerprint configuration is required. Both headless and headed launches are affected.

Version

  • Camoufox browser: 152.0.4-beta.30, original release archive.
  • macOS 15.7.4, arm64; Python 3.10; Camoufox Python 0.5.6; Playwright Python 1.51.0.
  • Camoufox main inspected at 571e416ac1ee52f055afc1f4e2e8ccd2b8d2ec17 still has the relevant zero-valued input-source arguments. This is source inspection, not a runtime test of a freshly built main.

To reproduce

Use an unmodified 152.0.4-beta.30 as the active managed browser, then run the following. Set headless=False to reproduce in a visible window.

python
from camoufox.sync_api import Camoufox

with Camoufox(headless=True) as browser:
    page = browser.new_page()
    page.set_content("<body style='margin:0;height:600px'>Pointer fixture</body>")
    page.evaluate("""() => {
        window.events = [];
        for (const type of ['pointermove', 'pointerdown', 'pointerup']) {
            document.addEventListener(type, e => events.push({
                type: e.type, pointerType: e.pointerType, isTrusted: e.isTrusted
            }));
        }
    }""")
    page.mouse.move(100, 100)
    page.mouse.down()
    page.mouse.move(130, 120)
    page.mouse.up()
    print(page.evaluate("events"))

Expected: every recorded event has pointerType: "mouse".

Actual: all four events have pointerType: "" and isTrusted: true.

Supplementary isolation check: the earlier raw-Playwright launch of the same Camoufox browser also returned an empty type, while Playwright's bundled Firefox 135.0 returned "mouse". This is only an older-browser control; the primary reproduction above uses the official Camoufox wrapper.

Source and related upstream history

Playwright previously tracked the same symptom in #38376 and added a regression test in #38429. Its current PageHandler explicitly supplies MouseEvent.MOZ_SOURCE_MOUSE.

Camoufox currently passes zero in additions/juggler/input/MouseDispatch.js and the drag-event dispatch in additions/juggler/content/PageAgent.js. Its native JugglerSendMouseEvent copies that argument directly into mouseEventData.mInputSource in patches/playwright/0-playwright.patch.

Candidate fix and validation

Explicitly use the native MouseEvent.MOZ_SOURCE_MOUSE constant at the mouse dispatch sites. On beta.30 the parent-process calls are still in PageHandler; on current main they have moved into MouseDispatch.

The official synchronous Camoufox-entry regression script was run against original and equivalently patched beta.30 copies:

Browser Headless Headed
Original beta.30 empty pointerType; assertion fails empty pointerType; assertion fails
Equivalent JS mouse-source fix mouse; passes mouse; passes

The default managed-browser entry (no custom executable argument) also passes on the patched local installation. All observed events remain trusted. Separate prior official AsyncCamoufox checks passed for iframe input and unchanged touch input ("touch"). The native PointerEvent constructor remains unchanged. No page-property override is involved.

The current-main source patch and official-entry regression script are in PR #777. A fresh main build, Linux/Windows execution, and the repository's full build/service suites have not been run. The PageAgent native HTML drag path has not been separately exercised.

Please confirm the preferred fix location and whether this should be included in the next browser release. Changing only the Python dependency cannot replace this browser-side code.