Browser Use Version
0.13.10 (main at 4cbe921)
Bug Description, Steps to Reproduce, Screenshots
A disabled form control with a click listener is offered to the agent (the serialized DOM shows it as [N]<button disabled=true />), and click on it returns a success result:
error: None
extracted_content: Clicked button "Place order" id=place
handler ran: False
The browser never dispatches clicks to a disabled control, so nothing happened. Because error is not set, multi_act() keeps running the queued actions (it stops on error), a single-action step is not counted toward max_failures, and the model is told the click worked.
Why the control is offered at all: is_interactive() returns early for elements with a JS click listener, before its accessibility disabled check (dom/serializer/clickable_elements.py). Without a listener the same disabled button is not offered. Framework buttons are affected the same way: I checked a disabled Vue 3 button with @click and a disabled React 18 button with onClick; both are offered and click returns Clicked button "Place order".
Where it shows up: a button that the page enables asynchronously after input, for example after a debounced availability check. When the model types and clicks in the same step, the click lands while the button is still disabled and comes back as Clicked ....
Probes against local pages, real Vue/React pages and the raw data are here: https://github.com/yotambraun/browser-use/tree/69c69ad6abdc474a2475d6cb10449571b5d49fac
Failing Python Code
import asyncio
from pytest_httpserver import HTTPServer
from browser_use.browser import BrowserProfile, BrowserSession
from browser_use.tools.service import Tools
PAGE = """<html><body>
<button id="place" disabled>Place order</button>
<script>
document.getElementById('place').addEventListener('click', () => { window.ordered = true })
</script>
</body></html>"""
async def main():
server = HTTPServer()
server.start()
server.expect_request('/').respond_with_data(PAGE, content_type='text/html')
session = BrowserSession(browser_profile=BrowserProfile(headless=True, user_data_dir=None))
await session.start()
tools = Tools()
await tools.navigate(url=server.url_for('/'), new_tab=False, browser_session=session)
await session.get_browser_state_summary()
index = next(i for i, el in (await session.get_selector_map()).items() if el.attributes.get('id') == 'place')
result = await tools.click(index=index, browser_session=session)
cdp = await session.get_or_create_cdp_session()
ordered = await cdp.cdp_client.send.Runtime.evaluate(
params={'expression': 'window.ordered === true', 'returnByValue': True}, session_id=cdp.session_id
)
print('error: ', result.error)
print('extracted_content:', result.extracted_content)
print('handler ran: ', ordered['result']['value'])
await session.kill()
server.stop()
asyncio.run(main())
LLM Model
Not needed for the reproduction (the action is called directly).
Operating System & Browser Versions
Linux (WSL2), Chromium from browser-use install, headless.
Browser Use Version
0.13.10 (main at 4cbe921)
Bug Description, Steps to Reproduce, Screenshots
A disabled form control with a click listener is offered to the agent (the serialized DOM shows it as
[N]<button disabled=true />), andclickon it returns a success result:The browser never dispatches clicks to a disabled control, so nothing happened. Because
erroris not set,multi_act()keeps running the queued actions (it stops onerror), a single-action step is not counted towardmax_failures, and the model is told the click worked.Why the control is offered at all:
is_interactive()returns early for elements with a JS click listener, before its accessibilitydisabledcheck (dom/serializer/clickable_elements.py). Without a listener the same disabled button is not offered. Framework buttons are affected the same way: I checked a disabled Vue 3 button with@clickand a disabled React 18 button withonClick; both are offered andclickreturnsClicked button "Place order".Where it shows up: a button that the page enables asynchronously after input, for example after a debounced availability check. When the model types and clicks in the same step, the click lands while the button is still disabled and comes back as
Clicked ....Probes against local pages, real Vue/React pages and the raw data are here: https://github.com/yotambraun/browser-use/tree/69c69ad6abdc474a2475d6cb10449571b5d49fac
Failing Python Code
LLM Model
Not needed for the reproduction (the action is called directly).
Operating System & Browser Versions
Linux (WSL2), Chromium from
browser-use install, headless.