- Add ClickCoordinateEvent to handle coordinate-based clicking via CDP
- Replace broken page.mouse.click() with CDP Input.dispatchMouseEvent
- Add safety checks for file inputs, select elements, and print dialogs
- Add get_dom_element_at_coordinates() to BrowserSession for element
detection
- Add force parameter to ClickElementAction to optionally skip safety
checks
- Update _click_by_coordinate to dispatch ClickCoordinateEvent instead
of using mouse
This fixes coordinate clicking functionality by using CDP directly
instead of the broken Actor mouse object, matching the implementation
from mert/everything_coordinates.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Introduce ClickCoordinateEvent and replace mouse-based coordinate
clicks with CDP Input.dispatchMouseEvent, adding safety checks and an
optional force mode.
>
> - **Events**
> - Add `ClickCoordinateEvent` (x/y/button, `force` flag) with timeout.
> - **BrowserSession**
> - Add `get_dom_element_at_coordinates(x, y)` using
`DOM.getNodeForLocation` returning minimal `EnhancedDOMTreeNode`.
> - **DefaultActionWatchdog**
> - Handle `ClickCoordinateEvent` with safety checks (file input,
`<select>`, print -> PDF) and optional `force`.
> - Implement `_click_on_coordinate` using CDP
`Input.dispatchMouseEvent` (move/press/release) with timeouts and
logging.
> - Minor: model rebuild for new event; improved error paths.
> - **Tools** (`service.py`, `views.py`)
> - Extend `ClickElementAction` with `force: bool`.
> - Replace actor `page.mouse.click` with dispatch of
`ClickCoordinateEvent`; convert LLM-scaled coords; return
metadata/validation errors; handle `BrowserError`.
> - **Overall**
> - Coordinate clicking now uses CDP directly with guardrails and
optional bypass, improving reliability.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
36b2b93d9b. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes broken coordinate-based clicking by switching to CDP
Input.dispatchMouseEvent. Adds ClickCoordinateEvent with safety checks
and an optional force mode.
- **New Features**
- ClickCoordinateEvent to click by viewport coordinates via CDP.
- Safety checks for file inputs, selects, and print buttons; print
clicks can auto-generate PDFs.
- BrowserSession.get_dom_element_at_coordinates for lightweight element
detection.
- force flag on ClickElementAction to skip checks when needed.
- **Bug Fixes**
- Coordinate clicks now work reliably and surface validation errors via
the event bus.
<sup>Written for commit b2c56f63c7.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
- Add ClickCoordinateEvent to handle coordinate-based clicking via CDP
- Replace broken page.mouse.click() with CDP Input.dispatchMouseEvent
- Add safety checks for file inputs, select elements, and print dialogs
- Add get_dom_element_at_coordinates() to BrowserSession for element detection
- Add force parameter to ClickElementAction to optionally skip safety checks
- Update _click_by_coordinate to dispatch ClickCoordinateEvent instead of using mouse
This fixes coordinate clicking functionality by using CDP directly instead of
the broken Actor mouse object, matching the implementation from mert/everything_coordinates.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds ChatVercel to route chat requests through Vercel AI Gateway using
an OpenAI-compatible API. Enables access to many provider models with
rate limiting, caching, and monitoring, plus docs and an example.
- **New Features**
- Added ChatVercel (async) with temperature, max_tokens, top_p,
timeouts, retries, and optional base_url.
- Structured output: JSON schema for standard models; schema-optimized
prompt parsing for Google/Gemini and reasoning models.
- Returns token usage (incl. cached prompt tokens when available) and
stop_reason.
- Reuses OpenAI message format; added lazy imports and llm exports.
- Docs updated with a usage guide and example; requires VERCEL_API_KEY.
<sup>Written for commit fd665e01cd.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Introduce `ChatVercel` with Vercel AI Gateway support, plus docs and
example.
>
> - **LLM**:
> - Add `ChatVercel` model wrapping Vercel AI Gateway
(OpenAI-compatible) with config (`api_key`, `base_url`, `temperature`,
`max_tokens`, `top_p`, timeouts/retries), structured output (JSON
schema; prompt-based parsing for Google/reasoning models),
usage/stop_reason extraction, and error handling.
> - Add `VercelMessageSerializer` reusing OpenAI message format.
> - Expose via lazy imports/exports in `browser_use/__init__.py` and
`browser_use/llm/__init__.py`.
> - **Docs**:
> - Add Vercel AI Gateway section in `docs/supported-models.mdx` with
setup and env `VERCEL_API_KEY`.
> - **Examples**:
> - Add `examples/models/vercel_ai_gateway.py`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fd665e01cd. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
The issue was located in the file browser_use/browser/session within the
connect function.
It was just removing the trailing '/' and adding the string
'/json/version' which resulted in unexpected result.
**Expected:**
`https://xyz.com?a=b` --> `https://xyz.com/json/version?a=b`
**Actual Result:**
`https://xyz.com?a=b` --> `https://xyz.com?a=b/json/version`
**Previous code snippet:**
<img width="379" height="87" alt="Screenshot 2025-11-22 at 5 39 39 PM"
src="https://github.com/user-attachments/assets/1f4b0180-34fa-43f9-8c53-27a236880833"
/>
**Solution I implemented:**
<img width="381" height="307" alt="Screenshot 2025-11-22 at 6 48 48 PM"
src="https://github.com/user-attachments/assets/c35421c1-e36d-4fd0-8b01-805a11cb035c"
/>
Using the `urllib` library
- I used urlparse to parse self.cdp_url and extract the path component.
- I then transformed only the path by ensuring it did not have a
trailing slash and concatenating /json/version to it.
- Finally, I used urlunparse to reassemble the URL, substituting only
the transformed path
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fix CDP URL construction with query parameters by appending
/json/version to the path while preserving the query. Addresses Linear
issue #3587.
- **Bug Fixes**
- Build the /json/version URL using urllib.parse, changing only the
path.
- Preserve scheme, host, params, query, and fragment (e.g.,
https://xyz.com?a=b -> https://xyz.com/json/version?a=b).
- Apply only to HTTP(S) CDP URLs in connect; WebSocket URLs are
unchanged.
<sup>Written for commit 66f2da3abc.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
- Add cloud MCP server as recommended option with HTTP-based setup
- Include setup instructions for Claude Code, Claude Desktop, Cursor,
and Windsurf
- Document cloud-specific features (browser_task, profiles, monitoring)
- Reorganize local self-hosted MCP as alternative option
- Fix bash command syntax with quoted 'browser-use[cli]' for zsh
compatibility
- Add troubleshooting for PATH issues and CLI extras requirement
- Include full path examples for macOS/Linux uvx location
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Revamps MCP server docs by adding a recommended cloud HTTP server and
repositioning local self-hosted as an alternative. Adds quick setup for
Claude Code/Desktop, Cursor, Windsurf, and ChatGPT OAuth, documents
cloud tools, fixes CLI examples and troubleshooting, and removes
deprecated MCP examples.
- **New Features**
- Added cloud MCP server docs with HTTP setup and API key header.
- Provided setup snippets for Claude Code, Claude Desktop, Cursor,
Windsurf, and ChatGPT via OAuth.
- Documented cloud tools: browser_task, list_browser_profiles,
monitor_task, plus examples and monitoring tips.
- **Bug Fixes**
- Corrected uvx usage with '--from "browser-use[cli]"' and zsh-safe
quoting; noted CLI extras requirement.
- Added PATH troubleshooting and full-path uvx examples for macOS/Linux,
plus Claude Desktop config/log pointers.
<sup>Written for commit 5a36835264.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Replaces mouse wheel scrolling with CDP synthesizeScrollGesture (using
cached viewport when available) and always caches viewport size during
browser state build.
>
> - **Scrolling behavior**:
> - Replace `Input.dispatchMouseEvent` mouse wheel with
`Input.synthesizeScrollGesture` in
`browser_use/browser/watchdogs/default_action_watchdog.py` for realistic
scrolling, inverted `yDistance` handling, and faster speed.
> - Use cached `browser_session._original_viewport_size` when available;
improved logging and soft-fail fallback.
> - **Viewport caching**:
> - In `browser_use/browser/watchdogs/dom_watchdog.py`, always cache
`page_info.viewport_width/height` to
`browser_session._original_viewport_size` (removes dependency on
`llm_screenshot_size`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a396927435. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes broken scrolling in PDF viewers by switching to a realistic CDP
scroll gesture. Also improves coordinate reliability by caching viewport
size and adds a safe JS fallback.
- **Bug Fixes**
- Use Input.synthesizeScrollGesture instead of mouse wheel events.
- Cache viewport size from page info for accurate gesture coordinates.
- Correct scroll direction using yDistance and set faster gesture speed.
- Fall back to JS scrolling if CDP gesture fails (logged at debug).
<sup>Written for commit a396927435.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
Origin of this issue was from the file location :
browser-use/tools/service.py , specifically from the function:
_validate_and_fix_javascript
- The quote fixer was converting double-quoted selectors to template
literals but creating duplicate closing parentheses
- Example: querySelector("div[role='button']") became
querySelector(\div[role='button']`)) with an extra)`
- Regex patterns only matched selectors with exactly one single quote,
missing complex multi-attribute selectors
- This caused "JavaScript execution error: Uncaught" when the agent
tried to execute the "fixed" code
Here is the screenshot of previous regex patterns:
<img width="574" height="667" alt="Screenshot 2025-11-19 at 12 02 56 PM"
src="https://github.com/user-attachments/assets/01a18f4e-9480-4698-89c0-f639a9b9d9f5"
/>
Two bugs in the regex patterns:
- Missing closing delimiter: Patterns stopped at the closing " without
capturing the ) or ,, leaving it behind to create duplicates
- Single-quote requirement: Pattern [^"]*\'[^"]* required exactly one
single quote, failing on selectors like "div[role='button'][pressed]"
with multiple quotes
Changes Made
- Pattern updates: Changed [^"]*\'[^"]* to [^"]* to match any
double-quoted content
- Delimiter capture: Added \s*\) or \s*, to consume closing delimiters
and prevent duplicates
- Affected patterns:
- querySelector/querySelectorAll: Added \s*\)
- document.evaluate: Added \s*,
- .closest(): Added \s*\)
- .matches(): Added \s*\)
Here is the screenshot of changes i made:
<img width="543" height="659" alt="Screenshot 2025-11-19 at 12 06 53 PM"
src="https://github.com/user-attachments/assets/e80b9792-c168-4e16-be4f-b89970be7a81"
/>
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes the JavaScript quote fixer to handle double-quoted selectors and
XPath correctly, preventing malformed code and runtime errors. Addresses
#3620 by updating regex to consume closing delimiters and support
complex selectors.
- **Bug Fixes**
- Updated patterns to match any double-quoted content, not just strings
with a single quote.
- Captured trailing ) or , to prevent duplicate delimiters.
- Applied changes to document.evaluate (captures ,),
querySelector/querySelectorAll, .closest(), and .matches() (capture )).
- Resolves errors like extra ) and "JavaScript execution error:
Uncaught" during evaluation.
<sup>Written for commit 515a42bdac.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is
generating a summary for commit
020af1f5e9. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Enforce screenshot exclusion when `use_vision` is not 'auto', even with
custom tools.
Previously, the `screenshot` action was not consistently excluded if a
user provided custom tools, leading to `screenshot` being available when
it should have been disabled based on the `use_vision` setting. This fix
ensures the exclusion is always applied by calling
`self.tools.exclude_action('screenshot')` after tool initialization.
Additionally, a mutable default argument bug in `Tools` and `Registry`'s
`exclude_actions` parameter was resolved.
---
[Slack
Thread](https://browser-use.slack.com/archives/C08SZRT860M/p1763797970748989?thread_ts=1763797970.748989&cid=C08SZRT860M)
<a
href="https://cursor.com/background-agent?bcId=bc-8a53c0fb-52e8-4c81-a767-e3f0cc9418d7"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-cursor-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in
Cursor"
src="https://cursor.com/open-in-cursor.svg"></picture></a> <a
href="https://cursor.com/agents?id=bc-8a53c0fb-52e8-4c81-a767-e3f0cc9418d7"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-web-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web"
src="https://cursor.com/open-in-web.svg"></picture></a>
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Enforce screenshot exclusion when use_vision is not "auto", including
when users pass custom Tools. Fix a mutable default argument bug and add
tests to cover the behavior.
- **Bug Fixes**
- Always remove the screenshot action when use_vision != "auto", even
with custom Tools instances.
- Replace mutable default lists for exclude_actions with None and copy
the provided list.
- Add CI tests for all use_vision modes and custom Tools to prevent
regressions.
- **New Features**
- Introduce Tools.exclude_action() and Registry.exclude_action() to
remove actions after init and block re-registration.
<sup>Written for commit e00ad12c40.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Always remove `screenshot` when `use_vision` != `"auto"` (even with
custom tools), add `exclude_action()` to Tools/Registry, fix mutable
default args, and add CI tests.
>
> - **Agent**
> - Enforces `screenshot` exclusion when `use_vision` != `"auto"` by
calling `self.tools.exclude_action('screenshot')`, covering custom
`tools`/`controller`.
> - **Tools/Registry**
> - Add `Tools.exclude_action()` and `Registry.exclude_action()` to
remove actions post-init and prevent re-registration.
> - Fix mutable default list bug: use `exclude_actions: list[str] |
None` and copy inputs; update `Tools` to pass a new list to `Registry`.
> - **Tests**
> - Add CI tests for `use_vision` modes (true/false/auto), with and
without custom `Tools`, direct `exclude_action()` behavior, and
re-registration prevention.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e00ad12c40. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Previously, cache_control was applied to every content block and tool
call in a message, which could exceed Anthropic's limit of [4 cache
breakpoints per
request](https://platform.claude.com/docs/en/build-with-claude/prompt-caching).
This fix ensures cache_control is only applied to the last block in each
message type:
- Last text block in UserMessage/AssistantMessage content
- Last tool_use block when AssistantMessage has tool calls
- Only the last overall block when AssistantMessage has both content and
tools
This prevents exceeding the cache breakpoint limit while maintaining
correct caching behavior.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes cache_control placement so it applies only to the last block in
each Anthropic message, keeping requests within the 4-cache-breakpoint
limit. Prevents cache overflow in messages with multiple content parts
and/or tool calls while preserving correct caching.
- **Bug Fixes**
- Apply cache_control only to the last content/tool block to meet
Anthropic’s 4-breakpoint limit.
- Cover all cases: only content, only tool calls, and mixed content +
tools (last overall block wins).
- Added focused tests to verify last-block-only caching for text parts,
tool_use lists, and mixed messages.
<sup>Written for commit 5a3d340ec4.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is
generating a summary for commit
2ba8e0cef6. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Reduce default `max_actions_per_step` to 3 and add explicit action
limits and step verification instructions to flash prompts.
The added verification rules aim to prevent the agent from taking
premature or consequential actions (like submitting forms or navigating)
before confirming the success of the previous step, thereby improving
agent reliability and reducing errors in multi-step tasks.
---
[Slack
Thread](https://browser-use.slack.com/archives/D092QUQDC56/p1763774897814279?thread_ts=1763774897.814279&cid=D092QUQDC56)
<a
href="https://cursor.com/background-agent?bcId=bc-50d25809-8c25-4ded-b50c-9a0a39474eb9"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-cursor-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in
Cursor"
src="https://cursor.com/open-in-cursor.svg"></picture></a> <a
href="https://cursor.com/agents?id=bc-50d25809-8c25-4ded-b50c-9a0a39474eb9"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-web-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web"
src="https://cursor.com/open-in-web.svg"></picture></a>
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Lowered the default max actions per step to 3 and added step
verification rules to flash prompts to prevent premature navigation or
form submissions. This improves reliability in multi-step tasks and
reduces errors.
- **New Features**
- Added an action_rules block to flash prompts (including Anthropic)
with a per-step action limit and instructions to verify the previous
step before taking consequential actions and to check page state after
changes.
- **Refactors**
- Set max_actions_per_step to 3 across prompts.py, service.py, and
views.py.
<sup>Written for commit 2df1faabe8.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->