Browser tool: click coordinates drift because outerWidth/outerHeight diverge from the CDP-overridden viewport
Summary
The in-app Browser pane tool (mcp__Claude_Browser__*) delivers left_click/computer coordinates that map to the live page inconsistently, even when the page itself is completely static. Root cause appears to be that the tool's click-coordinate transform is based on the real underlying window's outerWidth/outerHeight, which drifts independently of the CSS viewport set via the resize_window tool (innerWidth/innerHeight), and independently of any actual page change.
This makes precise coordinate-based interaction (e.g. tapping a specific spot on a <canvas>-rendered video stream) unreliable — the same fractional target position works one moment and misses the next, with no visible cause on the page side.
Environment
- Claude Code CLI, macOS (Darwin 25.3.0)
- Reproduced against a local Node.js app (
ws-scrcpy, a web-based Android screen-mirroring client) rendering a live device stream into two stacked<canvas>elements inside the Browser pane.
Steps to reproduce
- Open any page with a
<canvas>element (or similar) in the Browser pane viapreview_start. - Call
resize_windowto set a fixed viewport, e.g.{width: 1000, height: 700}. Confirm viajavascript_toolthatinnerWidth/innerHeightread1000/700— this stays constant for the rest of the session. - Attach a capture-phase
mousedownlistener viajavascript_toolthat recordsevent.clientX,event.clientY, and simultaneouslyouterWidth,outerHeight,innerWidth,innerHeight,devicePixelRatio. - Issue several
computerleft_clickcalls at differentcoordinatevalues (e.g.[10,10],[200,100],[300,200],[500,500],[350,250]), spaced out with other tool calls in between (e.g.screenshot, morejavascript_execcalls). - Compare the recorded
clientX/clientYagainst the inputcoordinatefor each click.
Observed
- The effective scale factor (
clientX / inputX) is not stable: observed values include ~1.6x, ~4.104x, and ~3.58x across different clicks in the same session, withinnerWidth/innerHeightunchanged (1000x700) throughout. outerWidth/outerHeight, read viajavascript_execat different points, were also inconsistent across calls with zero action from the page or from us in between: observed 800x560, 1200x800, and other values, despiteinnerWidth/innerHeightand the target page's DOM (e.g. a canvas'sgetBoundingClientRect()) staying byte-for-byte identical.- Separately,
screenshotactions returned varying PNG pixel dimensions for the identical, unchanged page/viewport across consecutive calls (e.g.800x450,800x1090,698x1428,800x560,698x488), with no resize action performed by us. - A
requestAnimationFrameloop started viajavascript_exec, expected to log ~60 frames over 4 seconds, logged only 1 frame, firing att=5739ms— i.e., the tab went ~5.7 seconds without a single animation frame executing. This suggests the tab is being treated as backgrounded/throttled by the browser engine at least some of the time, even whilecomputer/screenshotactions are actively being issued against it.
Expected
resize_windowshould pin down the actual window/frame used for both screenshot capture and click-coordinate mapping, not just an independent CSS layout viewport override — so that a fixed CSS viewport implies a fixed, predictable click-coordinate space.- Coordinate mapping for
computeractions (click, etc.) should be based on the same, single source of truth as whatever thescreenshotaction reports (or a documented fixed reference size), so callers can reliably compute target coordinates from a screenshot. - The tab should not appear to be background-throttled while it's the active target of
computer/screenshottool calls.
Impact
Any workflow relying on the Browser pane's computer coordinate clicking against non-DOM content (canvas/video streams, custom-rendered UI) is unreliable — the same relative on-screen target can hit or miss unpredictably, with no way for the caller to detect or compensate for it ahead of time (only explicit screenshot calls report a size, and that size does not reliably predict the scale used by a subsequent left_click). Ref-based clicks on real DOM elements are unaffected and remain reliable, as does driving input through an out-of-band channel (e.g. adb for an Android device rendered via the canvas), which is the workaround currently in use.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗