tested locally and worked
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Ensures newly focused tabs in headless mode apply the configured
viewport (width, height, device scale factor) so window size is
respected. Fixes inconsistent rendering when switching tabs.
- **Bug Fixes**
- On AgentFocusChangedEvent, call _cdp_set_viewport for the focused tab
via its target_id, with error handling and debug logs.
<!-- End of auto-generated description by cubic. -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Ensure newly focused tabs apply the configured viewport (width,
height, device scale factor) so window size is respected.
>
> - **Browser session (CDP)**:
> - On `AgentFocusChangedEvent`, set viewport on the focused tab using
`_cdp_set_viewport` with `event.target_id`.
> - Includes debug logging and error handling for viewport application
in `browser_use/browser/session.py`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
89990d360d. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Pass authentication headers to CDPClient and the /json/version fetch so
remote browser connections succeed with services that require auth. Adds
tests to verify headers flow through connect() for both ws and http
paths.
- **Bug Fixes**
- Use BrowserProfile.headers as additional_headers when creating
CDPClient.
- Include headers in httpx GET to /json/version when resolving the
WebSocket URL.
<sup>Written for commit 885ec7cc6f.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Improve demo mode with a new in-browser panel and persistent logs, plus
a display option for full panel or a minimal “last action + memory”
overlay. Also removes step-start and completion-summary demo logs to
keep output clean.
- **New Features**
- Added demo panel script generator with two modes: full side panel and
bottom-right “last action + memory” view.
- New profile setting: demo_mode_display = 'full' | 'last' (default
'last').
- Demo overlay now registers on new pages/tabs and updates on
navigation; logs and final result persist across reloads.
<sup>Written for commit c951b94193.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
### Problem
The `event_timeout` fields on all event classes were evaluated at
**module import time**, not at instance creation time. This meant that
environment variables like `TIMEOUT_TypeTextEvent` had to be set
**before** importing `browser_use`, making dynamic runtime configuration
impossible.
```python
# This didn't work:
import os
from browser_use.browser.events import TypeTextEvent
os.environ["TIMEOUT_TypeTextEvent"] = "60" # Too late - already evaluated to 15.0
event = TypeTextEvent(...)
print(event.event_timeout) # 15.0 ❌
```
### Solution
Changed all `event_timeout` field defaults from:
```python
event_timeout: float | None = _get_timeout('TIMEOUT_X', 15.0)
```
To:
```python
event_timeout: float | None = Field(default_factory=lambda: _get_timeout('TIMEOUT_X', 15.0))
```
Using `default_factory` defers the
[_get_timeout()](cci:1://file:///Users/tomergal/CascadeProjects/browser-use/browser_use/browser/events.py:15:0-42:15)
call until each event instance is created, allowing users to set timeout
environment variables at any point before creating events.
### After this fix
```python
import os
from browser_use.browser.events import TypeTextEvent
os.environ["TIMEOUT_TypeTextEvent"] = "60"
event = TypeTextEvent(...)
print(event.event_timeout) # 60.0 ✅
```
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Make event timeouts read environment variables at runtime by deferring
evaluation to event instantiation. This enables dynamic configuration
(e.g., setting TIMEOUT_* after import) to take effect when creating
events.
- **Bug Fixes**
- Switched all event_timeout fields to use Field(default_factory=...) so
_get_timeout runs per instance.
- TIMEOUT_* env vars are now read when an event is created, not at
module import time.
- Defaults remain unchanged if no env vars are set.
<sup>Written for commit 00462f9282.
Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Fixes enum serialization in structured outputs and preserves valid title
fields in JSON Schemas. This stabilizes agent action/result dumps and
Gemini function schema generation.
- **Bug Fixes**
- Serialize actions, results, and done payloads with mode='json' to
correctly handle enums (including nested values).
- In Gemini schema cleaning, only remove metadata-level title; keep
property title and allow it in required. Pass parent context to nested
items.
- Recursively process type values in schema optimization to resolve refs
nested under type.
- Keep Gemini schemas valid by inserting a placeholder when object
properties would be empty.
<sup>Written for commit 1c9a87b98f.
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.
<!-- 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. -->