browser_click
Click a DOM element in Chrome/Edge by CSS selector or semantic text, role, or ARIA label; it stops on ambiguity or blocking modals and reports delivery status.
Instructions
Click a DOM element in Chrome/Edge. Two ways to target: (1) selector — a CSS selector (combines browser_locate + mouse_click; stable across repaints); or (2) by-axis (semantic) — by:'text'|'regex'|'role'|'ariaLabel' + pattern, so you do not have to build a CSS selector for dynamic-class SPAs. by-axis resolves to a SINGLE actionable element (climbing to a clickable ancestor up to 3 levels, hit-testing for occlusion) and STOPS with code:'BrowserAmbiguousTarget' (candidates[] + next[] hints) when 2+ actionable elements match, or code:'BrowserNoActionableTarget' when matches exist but none is clickable — it never guesses. If the target is behind a modal dialog blocking the page, BOTH targeting modes STOP with code:'BrowserModalBlocking' (context.blockingElement {name, role}) instead of clicking through to the backdrop — dismiss the dialog (its close button or Escape) and retry; a plain navigation drawer does not count as blocking. Optionally add role to filter (by:'text',pattern:'Save',role:'button') and scope to narrow the search. Provide EITHER selector OR by+pattern (not both). Pass tabId+port so the server auto-guards (verifies tab readyState and identity) and returns post.perception.status. lensId is optional for advanced pinned-tab workflows. Caveats: selector mode fails if the element is outside the visible viewport — scroll it into view with browser_eval("document.querySelector('sel').scrollIntoView()") first (by-axis only resolves in-viewport actionable targets). hints.verifyDelivery:{status:'delivered'|'unverifiable', reason, observedSignals:{mutationCount,urlChanged,activeElementChanged}} reports the post-click observation in 2 values: 'delivered' fires only when mutationCount>0 OR urlChanged (activeElementChanged is recorded in observedSignals but intentionally NOT a delivery signal — plain clicks on focusable controls always update focus, treating that as 'delivered' would mask silent-fail regressions); 'unverifiable' reason ∈ {'iframe_context_mismatch','no_dom_mutation','probe_install_failed','probe_read_failed'}. CDP emits 2 values only (focus_only is a UIA-path concept, N/A here). BrowserClickNotDelivered is reserved-only (false-positive risk too high to emit) — degradation reads from 'unverifiable' status.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| by | No | Semantic axis to target by INSTEAD of a CSS selector: 'text' (visible text), 'regex', 'role' (ARIA/implicit role), 'ariaLabel'. Pair with `pattern`. The server resolves to a SINGLE actionable element — climbing to a clickable ancestor up to 3 levels — and STOPS with a candidate list (code:'BrowserAmbiguousTarget') if the match is ambiguous; it never guesses. | |
| port | No | Chrome/Edge CDP remote debugging port (default 9222; configurable via desktop-touch-config.json) | |
| role | No | Optional ARIA/implicit-role filter AND-combined with `by` (e.g. by:'text', pattern:'Save', role:'button'). | |
| fixId | No | Approve a pending suggestedFix (one-shot, 15s TTL). Selector mode only. | |
| scope | No | Optional CSS selector to limit the `by`-axis search scope (disambiguation). | |
| tabId | No | Tab ID from browser_open. Omit to use the first page tab. | |
| lensId | No | Optional perception lens ID. Guards (target.identityStable) are evaluated before clicking, and a perception envelope is attached to post.perception on success. | |
| include | No | Optional response-shape opt-in. `['envelope']` returns the self-documenting envelope (`_version` / `data` / `as_of` / `confidence`). `['raw']` forces raw shape (overrides DESKTOP_TOUCH_ENVELOPE=1 server default). Default behaviour is raw shape (compat with existing clients). | |
| narrate | No | Narration level. "rich": include UIA diff in post.rich (appeared/disappeared/valueDeltas, and nameDeltas when an element's name changed, such as a calculator display) — usually removes the need for a verification screenshot. It is withheld, with post.rich.diffDegraded saying why, when the diff cannot be shown to describe the window that was acted on. On click_element and keyboard (and set_element_value where the server registers it), which resolve the target window before acting: another open window's title contains the text this call resolved to, whether you named the hwnd or the server did — "@active" and the dialog rescue both resolve one ("ambiguous_title"); or the target moved between the snapshot and the action ("target_changed"). On those and on mouse_click, retrying with a fixId also withholds it, because the stored fix names a window this cannot see ("fix_target_unknown") — browser tools keep their diff on a fixId retry, because theirs is a tab diff and does not depend on a window title. mouse_click and mouse_drag accept an hwnd and still take their snapshots by windowTitle, so nothing else is withheld for them: verify those with a screenshot. A window too large to read whole is withheld too ("tree_truncated"). The action itself is unaffected in every case; only the diff is. Default: "minimal". | minimal |
| pattern | No | Value matched against the chosen `by` axis (required when `by` is set). | |
| selector | No | CSS selector for the target element (e.g. '#submit', '.btn'). Provide EITHER selector OR by+pattern. | |
| caseSensitive | No | Case-sensitive matching for by:'text'/'regex' (default false). | |
| scrollIntoView | No | When true, if the target is outside the viewport, scroll it into view (centered) before clicking, instead of failing with ElementNotInViewport. Default false preserves the explicit scrollIntoView-then-retry workflow. Selector mode only (by-axis resolves only in-viewport actionable targets). |