Skip to main content
Glama


šŸ“ Here's a Python example that uses Pure CDP Mode (sb_cdp):(It navigates to Browserscan where it bypasses bot-detection.)

from seleniumbase import sb_cdp

sb = sb_cdp.Chrome()
sb.goto("https://browserscan.net/bot-detection")
sb.sleep(3)
sb.quit()

šŸŽ­ Here's an example script that uses Stealthy Playwright Mode:(Playwright connects to a stealthy SeleniumBase browser session.)

from playwright.sync_api import sync_playwright
from seleniumbase import sb_cdp

sb = sb_cdp.Chrome(guest=True)
endpoint_url = sb.get_endpoint_url()

with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(endpoint_url)
    page = browser.contexts[0].pages[0]
    page.goto("https://bot.sannysoft.com/")
    page.wait_for_timeout(500)

from seleniumbase import sb_cdp

sb = sb_cdp.Chrome()
sb.goto("https://seleniumbase.io/demo_page")
sb.type("input", "Quickly type text!")
sb.press_keys("textarea", "Slowly type text!")
sb.click("#myButton")
sb.set_value("input#mySlider", "100")
sb.click_visible_elements("input.checkBoxClassB")
sb.select_option_by_text("#mySelect", "Set to 75%")
sb.hover_and_click("#myDropdown", "#dropOption2")
sb.click("#checkBox1")
sb.drag_and_drop("img#logo", "div#drop2")
sb.nested_click("iframe#myFrame3", ".fBox")
sb.highlight("#myButton")
sb.quit()

from seleniumbase import sb_cdp

sb = sb_cdp.Chrome(locale="en", ad_block=True)
sb.goto("https://browserscan.net/bot-detection")
sb.flash("Test Results", duration=1.5, pause=0.5)
sb.assert_element('strong:contains("Normal")')
print("Bot Not Detected")
sb.flash('strong:contains("Normal")', pause=1)
sb.quit()

from seleniumbase import sb_cdp

sb = sb_cdp.Chrome()
sb.goto("https://news.ycombinator.com/submitted?id=seleniumbase")
elements = sb.find_elements("span.titleline > a")
for element in elements:
    print("* " + element.text)

šŸ™ Stealthy CDP Mode examples are located in ./examples/cdp_mode/.

šŸŽ­ Stealthy Playwright examples are located in ./examples/cdp_mode/playwright/.



python SCRIPT.py --chromium  # Use the unbranded Chromium browser
python SCRIPT.py --cft  # Use Chrome-for-testing
python SCRIPT.py --edge  # Use Microsoft Edge
python SCRIPT.py --brave  # Use Brave browser

Google Chrome is the default browser. Only unbranded Chromium and Chrome-for-Testing get downloaded automatically if not already present on the system.

The Chromium browser can also be set via method args, eg: cft=True, use_chromium=True, browser="edge", browser="brave", etc. Eg:

sb = sb_cdp.Chrome(use_chromium=True)

from seleniumbase import SB

with SB(uc=True, test=True) as sb:
    url = "https://google.com/ncr"
    sb.activate_cdp_mode(url)
    sb.click_if_visible('button:contains("Accept all")')
    sb.type('[name="q"]', "SeleniumBase GitHub page")
    sb.click('[value="Google Search"]')
    sb.sleep(4)  # The "AI Overview" sometimes loads
    print(sb.get_page_title())
    sb.save_as_pdf_to_logs()
    sb.save_page_source_to_logs()
    sb.save_screenshot_to_logs()
    print("Logs have been saved to: ./latest_logs/")

from seleniumbase import SB

with SB(uc=True, test=True, locale="en") as sb:
    url = "https://gitlab.com/users/sign_in"
    sb.activate_cdp_mode(url)
    sb.sleep(2)
    sb.solve_captcha()
    # (The rest is for testing and demo purposes)
    sb.assert_text("Username", '[for="user_login"]', timeout=3)
    sb.assert_element('label[for="user_login"]')
    sb.highlight('button:contains("Sign in")')
    sb.highlight('h1:contains("GitLab")')
    sb.post_message("SeleniumBase wasn't detected", duration=4)

šŸ’” sb.solve_captcha() handles CAPTCHAs that aren't bypassed automatically.(If no CAPTCHA is present on the current page, then nothing happens.)


from seleniumbase import sb_cdp

sb = sb_cdp.Chrome(incognito=True)
sb.goto("https://gitlab.com/users/sign_in")
sb.sleep(2)
sb.solve_captcha()
sb.highlight('h1:contains("GitLab")')
sb.highlight('button:contains("Sign in")')
sb.quit()

šŸ“š The SeleniumBase/examples/ folder includes over 150 ready-to-run examples of E2E testing. Examples that start with test_ or end with _test.py/_tests.py run with pytest. Other examples run directly with raw python (those generally start with raw_ to avoid confusion).

from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)  # Call pytest

class MyTestClass(BaseCase):
    def test_swag_labs(self):
        self.goto("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_text("Backpack", "div.cart_item")
        self.click("button#checkout")
        self.type("input#first-name", "SeleniumBase")
        self.type("input#last-name", "Automation")
        self.type("input#postal-code", "77123")
        self.click("input#continue")
        self.click("button#finish")
        self.assert_text("Thank you for your order!")

pytest test_get_swag.py


pytest test_coffee_cart.py --demo

pytest test_demo_site.py

Easy to type, click, select, toggle, drag & drop, and more.

(For more examples, see the SeleniumBase/examples/ folder.)




from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class TestSimpleLogin(BaseCase):
    def test_simple_login(self):
        self.goto("seleniumbase.io/simple/login")
        self.type("#username", "demo_user")
        self.type("#password", "secret_pass")
        self.click('a:contains("Sign in")')
        self.assert_exact_text("Welcome!", "h1")
        self.assert_element("img#image1")
        self.highlight("#image1")
        self.click_link("Sign out")
        self.assert_text("signed out", "#top_message")
from seleniumbase import SB

with SB() as sb:
    sb.goto("seleniumbase.io/simple/login")
    sb.type("#username", "demo_user")
    sb.type("#password", "secret_pass")
    sb.click('a:contains("Sign in")')
    sb.assert_exact_text("Welcome!", "h1")
    sb.assert_element("img#image1")
    sb.highlight("#image1")
    sb.click_link("Sign out")
    sb.assert_text("signed out", "#top_message")
from seleniumbase import Driver

driver = Driver()
try:
    driver.goto("seleniumbase.io/simple/login")
    driver.type("#username", "demo_user")
    driver.type("#password", "secret_pass")
    driver.click('a:contains("Sign in")')
    driver.assert_exact_text("Welcome!", "h1")
    driver.assert_element("img#image1")
    driver.highlight("#image1")
    driver.click_link("Sign out")
    driver.assert_text("signed out", "#top_message")
finally:
    driver.quit()

šŸ”µ Add Python and Git to your System PATH.

šŸ”µ Using a Python virtual env is recommended.

šŸ”µ How to install seleniumbase from PyPI using pip:

pip install seleniumbase
  • (Add --upgrade OR -U to upgrade SeleniumBase.)

  • (Add --force-reinstall to upgrade indirect packages.)

šŸ”µ How to install seleniumbase from a GitHub clone:

git clone https://github.com/seleniumbase/SeleniumBase.git
cd SeleniumBase/
pip install -e .

šŸ”µ How to upgrade an existing install from a GitHub clone:

git pull
pip install -e .

šŸ”µ Type seleniumbase or sbase to verify that SeleniumBase was installed successfully:

 ___      _          _             ___              
/ __| ___| |___ _ _ (_)_  _ _ __  | _ ) __ _ ______ 
\__ \/ -_) / -_) ' \| | \| | '  \ | _ \/ _` (_-< -_)
|___/\___|_\___|_||_|_|\_,_|_|_|_\|___/\__,_/__|___|
----------------------------------------------------

╭──────────────────────────────────────────────────╮
│  * USAGE: "seleniumbase [COMMAND] [PARAMETERS]"  │
│  *    OR:        "sbase [COMMAND] [PARAMETERS]"  │
│                                                  │
│ COMMANDS:        PARAMETERS / DESCRIPTIONS:      │
│    get / install    [DRIVER_NAME] [OPTIONS]      │
│    methods          (List common Python methods) │
│    options          (List common pytest options) │
│    behave-options   (List common behave options) │
│    gui / commander  [OPTIONAL PATH or TEST FILE] │
│    behave-gui       (SBase Commander for Behave) │
│    caseplans        [OPTIONAL PATH or TEST FILE] │
│    mkdir            [DIRECTORY] [OPTIONS]        │
│    mkfile           [FILE.py] [OPTIONS]          │
│    mkrec / codegen  [FILE.py] [OPTIONS]          │
│    recorder         (Open Recorder Desktop App.) │
│    record           (If args: mkrec. Else: App.) │
│    mkpres           [FILE.py] [LANG]             │
│    mkchart          [FILE.py] [LANG]             │
│    print            [FILE] [OPTIONS]             │
│    translate        [SB_FILE.py] [LANG] [ACTION] │
│    convert          [WEBDRIVER_UNITTEST_FILE.py] │
│    extract-objects  [SB_FILE.py]                 │
│    inject-objects   [SB_FILE.py] [OPTIONS]       │
│    objectify        [SB_FILE.py] [OPTIONS]       │
│    revert-objects   [SB_FILE.py] [OPTIONS]       │
│    encrypt / obfuscate                           │
│    decrypt / unobfuscate                         │
│    proxy            (Start a basic proxy server) │
│    download server  (Get Selenium Grid JAR file) │
│    grid-hub         [start|stop] [OPTIONS]       │
│    grid-node        [start|stop] --hub=[HOST/IP] │
│                                                  │
│ *  EXAMPLE => "sbase get chromedriver stable"    │
│ *  For command info => "sbase help [COMMAND]"    │
│ *  For info on all commands => "sbase --help"    │
╰──────────────────────────────────────────────────╯

āœ… SeleniumBase automatically downloads webdrivers as needed, such as chromedriver.

*** chromedriver to download = 149.0.7827.54 (Latest Stable)

Downloading chromedriver-mac-arm64.zip from:
https://storage.googleapis.com/chrome-for-testing-public/149.0.7827.54/mac-arm64/chromedriver-mac-arm64.zip ...
Download Complete!

Extracting ['chromedriver'] from chromedriver-mac-arm64.zip ...
Unzip Complete!

The file [chromedriver] was saved to:
~/github/SeleniumBase/seleniumbase/drivers/
chromedriver

Making [chromedriver 149.0.7827.54] executable ...
[chromedriver 149.0.7827.54] is now ready for use!

šŸ”µ If you've cloned SeleniumBase, you can run tests from the examples/ folder.

cd examples/
pytest my_first_test.py

from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class MyTestClass(BaseCase):
    def test_swag_labs(self):
        self.goto("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_exact_text("Products", "span.title")
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_exact_text("Your Cart", "span.title")
        self.assert_text("Backpack", "div.cart_item")
        self.click("button#checkout")
        self.type("#first-name", "SeleniumBase")
        self.type("#last-name", "Automation")
        self.type("#postal-code", "77123")
        self.click("input#continue")
        self.assert_text("Checkout: Overview")
        self.assert_text("Backpack", "div.cart_item")
        self.assert_text("29.99", "div.inventory_item_price")
        self.click("button#finish")
        self.assert_exact_text("Thank you for your order!", "h2")
        self.assert_element('img[alt="Pony Express"]')
        self.js_click("a#logout_sidebar_link")
        self.assert_element("div#login_button_container")

self.goto(url)  # Navigate the browser window to the URL.
self.open(url)  # Same as `self.goto(url)`
self.activate_cdp_mode()  # Activate CDP Mode from UC Mode.
self.type(selector, text)  # Update the field with the text.
self.click(selector)  # Click the element with the selector.
self.click_link(link_text)  # Click the link containing text.
self.go_back()  # Navigate back to the previous URL.
self.select_option_by_text(dropdown_selector, option)
self.hover_and_click(hover_selector, click_selector)
self.drag_and_drop(drag_selector, drop_selector)
self.get_text(selector)  # Get the text from the element.
self.get_current_url()  # Get the URL of the current page.
self.get_page_source()  # Get the HTML of the current page.
self.get_attribute(selector, attribute)  # Get element attribute.
self.get_title()  # Get the title of the current page.
self.switch_to_frame(frame)  # Switch into the iframe container.
self.switch_to_default_content()  # Leave the iframe container.
self.open_new_window()  # Open a new window in the same browser.
self.switch_to_window(window)  # Switch to the browser window.
self.switch_to_default_window()  # Switch to the original window.
self.get_new_driver(OPTIONS)  # Open a new driver with OPTIONS.
self.switch_to_driver(driver)  # Switch to the browser driver.
self.switch_to_default_driver()  # Switch to the original driver.
self.wait_for_element(selector)  # Wait until element is visible.
self.is_element_visible(selector)  # Return element visibility.
self.is_text_visible(text, selector)  # Return text visibility.
self.sleep(seconds)  # Do nothing for the given amount of time.
self.save_screenshot(name)  # Save a screenshot in .png format.
self.assert_element(selector)  # Verify the element is visible.
self.assert_text(text, selector)  # Verify text in the element.
self.assert_exact_text(text, selector)  # Verify text is exact.
self.assert_title(title)  # Verify the title of the web page.
self.assert_downloaded_file(file)  # Verify file was downloaded.
self.assert_no_404_errors()  # Verify there are no broken links.
self.assert_no_js_errors()  # Verify there are no JS errors.

šŸ”µ For the complete list of SeleniumBase methods, see: Method Summary

self.type("input", "dogs\n")  # (The "\n" presses ENTER)

Most SeleniumBase scripts can be run with pytest, pynose, or pure python. Not all test runners can run all test formats. For example, tests that use the sb pytest fixture can only be run with pytest. (See Syntax Formats) There's also a Gherkin test format that runs with behave.

pytest coffee_cart_tests.py --rs
pytest test_sb_fixture.py --demo
pytest test_suite.py --rs --html=report.html --dashboard

pynose basic_test.py --mobile
pynose test_suite.py --headless --report --show-report

python raw_sb.py
python raw_test_scripts.py

behave realworld.feature
behave calculator.feature -D rs -D dashboard
  • Python files that start with test_ or end with _test.py.

  • Python methods that start with test_.

With a SeleniumBase pytest.ini file present, you can modify default discovery settings. The Python class name can be anything because seleniumbase.BaseCase inherits unittest.TestCase to trigger autodiscovery.

pytest --co -q
pytest [FILE_NAME.py]::[CLASS_NAME]::[METHOD_NAME]

pynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]

āœ… SeleniumBase supports all major browsers and operating systems:

āœ… SeleniumBase works on all popular CI/CD platforms:

šŸ”µ Demo Mode helps you see what a test is doing. If a test is moving too fast for your eyes, run it in Demo Mode to pause the browser briefly between actions, highlight page elements being acted on, and display assertions:

pytest my_first_test.py --demo

šŸ”µ time.sleep(seconds) can be used to make a test wait at a specific spot:

import time; time.sleep(3)  # Do nothing for 3 seconds.

šŸ”µ Debug Mode with Python's built-in pdb library helps you debug tests:

breakpoint()  # Shortcut for "import pdb; pdb.set_trace()"

(pdb commands: n, c, s, u, d => next, continue, step, up, down)

šŸ”µ To pause an active test that throws an exception or error, (and keep the browser window open while Debug Mode begins in the console), add --pdb as a pytest option:

pytest test_fail.py --pdb

šŸ”µ To start tests in Debug Mode, add --trace as a pytest option:

pytest test_coffee_cart.py --trace

āœ… Here are some useful command-line options that come with pytest:

-v  # Verbose mode. Prints the full name of each test and shows more details.
-q  # Quiet mode. Print fewer details in the console output when running tests.
-x  # Stop running the tests after the first failure is reached.
--html=report.html  # Creates a detailed pytest-html report after tests finish.
--co | --collect-only  # Show what tests would get run. (Without running them)
--co -q  # (Both options together!) - Do a dry run with full test names shown.
-n=NUM  # Multithread the tests using that many threads. (Speed up test runs!)
-s  # See print statements. (Should be on by default with pytest.ini present.)
--junit-xml=report.xml  # Creates a junit-xml report after tests finish.
--pdb  # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)
--trace  # Enter Debug Mode at the beginning of each test. (Don't use with CI!)
-m=MARKER  # Run tests with the specified pytest marker.

āœ… SeleniumBase provides additional pytest command-line options for tests:

--browser=BROWSER  # (The web browser to use. Default: "chrome".)
--chrome  # (Shortcut for "--browser=chrome". On by default.)
--edge  # (Shortcut for "--browser=edge".)
--firefox  # (Shortcut for "--browser=firefox".)
--safari  # (Shortcut for "--browser=safari".)
--opera  # (Shortcut for "--browser=opera".)
--brave  # (Shortcut for "--browser=brave".)
--comet  # (Shortcut for "--browser=comet".)
--chromium  # (Shortcut for using base `Chromium`)
--settings-file=FILE  # (Override default SeleniumBase settings.)
--env=ENV  # (Set the test env. Access with "self.env" in tests.)
--account=STR  # (Set account. Access with "self.account" in tests.)
--data=STRING  # (Extra test data. Access with "self.data" in tests.)
--var1=STRING  # (Extra test data. Access with "self.var1" in tests.)
--var2=STRING  # (Extra test data. Access with "self.var2" in tests.)
--var3=STRING  # (Extra test data. Access with "self.var3" in tests.)
--variables=DICT  # (Extra test data. Access with "self.variables".)
--user-data-dir=DIR  # (Set the Chrome user data directory to use.)
--protocol=PROTOCOL  # (The Selenium Grid protocol: http|https.)
--server=SERVER  # (The Selenium Grid server/IP used for tests.)
--port=PORT  # (The Selenium Grid port used by the test server.)
--cap-file=FILE  # (The web browser's desired capabilities to use.)
--cap-string=STRING  # (The web browser's desired capabilities to use.)
--proxy=SERVER:PORT  # (Connect to a proxy server:port as tests are running)
--proxy=USERNAME:PASSWORD@SERVER:PORT  # (Use an authenticated proxy server)
--proxy-bypass-list=STRING # (";"-separated hosts to bypass, Eg "*.foo.com")
--proxy-pac-url=URL  # (Connect to a proxy server using a PAC_URL.pac file.)
--proxy-pac-url=USERNAME:PASSWORD@URL  # (Authenticated proxy with PAC URL.)
--proxy-driver  # (If a driver download is needed, will use: --proxy=PROXY.)
--multi-proxy  # (Allow multiple authenticated proxies when multi-threaded.)
--agent=STRING  # (Modify the web browser's User-Agent string.)
--mobile  # (Use the mobile device emulator while running tests.)
--metrics=STRING  # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
--chromium-arg="ARG=N,ARG2"  # (Set Chromium args, ","-separated, no spaces.)
--firefox-arg="ARG=N,ARG2"  # (Set Firefox args, comma-separated, no spaces.)
--firefox-pref=SET  # (Set a Firefox preference:value set, comma-separated.)
--extension-zip=ZIP  # (Load a Chrome Extension .zip|.crx, comma-separated.)
--extension-dir=DIR  # (Load a Chrome Extension directory, comma-separated.)
--disable-features="F1,F2"  # (Disable features, comma-separated, no spaces.)
--binary-location=PATH  # (Set path of the Chromium browser binary to use.)
--driver-version=VER  # (Set the chromedriver or uc_driver version to use.)
--sjw  # (Skip JS Waits for readyState to be "complete" or Angular to load.)
--wfa  # (Wait for AngularJS to be done loading after specific web actions.)
--pls=PLS  # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
--headless  # (The default headless mode. Linux uses this mode by default.)
--headless1  # (Use Chrome's old headless mode. Fast, but has limitations.)
--headless2  # (Use Chrome's new headless mode, which supports extensions.)
--headed  # (Run tests in headed/GUI mode on Linux OS, where not default.)
--xvfb  # (Run tests using the Xvfb virtual display server on Linux OS.)
--xvfb-metrics=STRING  # (Set Xvfb display size on Linux: "Width,Height".)
--locale=LOCALE_CODE  # (Set the Language Locale Code for the web browser.)
--interval=SECONDS  # (The autoplay interval for presentations & tour steps)
--start-page=URL  # (The starting URL for the web browser when tests begin.)
--archive-logs  # (Archive existing log files instead of deleting them.)
--archive-downloads  # (Archive old downloads instead of deleting them.)
--time-limit=SECONDS  # (Safely fail any test that exceeds the time limit.)
--slow  # (Slow down the automation. Faster than using Demo Mode.)
--demo  # (Slow down and visually see test actions as they occur.)
--demo-sleep=SECONDS  # (Set the wait time after Slow & Demo Mode actions.)
--highlights=NUM  # (Number of highlight animations for Demo Mode actions.)
--message-duration=SECONDS  # (The time length for Messenger alerts.)
--check-js  # (Check for JavaScript errors after page loads.)
--ad-block  # (Block some types of display ads from loading.)
--host-resolver-rules=RULES  # (Set host-resolver-rules, comma-separated.)
--block-images  # (Block images from loading during tests.)
--do-not-track  # (Indicate to websites that you don't want to be tracked.)
--verify-delay=SECONDS  # (The delay before MasterQA verification checks.)
--ee | --esc-end  # (Lets the user end the current test via the ESC key.)
--recorder  # (Enables the Recorder for turning browser actions into code.)
--rec-sb-mgr  # (A Recorder Mode that generates SB() context manager code.)
--rec-sb-cdp  # (A Recorder Mode that generates Pure CDP Mode sb_cdp code.)
--rec-behave  # (Same as Recorder Mode, but also generates behave-gherkin.)
--rec-sleep  # (If the Recorder is enabled, also records self.sleep calls.)
--rec-print  # (If the Recorder is enabled, prints output after tests end.)
--disable-cookies  # (Disable Cookies on websites. Pages might break!)
--disable-js  # (Disable JavaScript on websites. Pages might break!)
--disable-csp  # (Disable the Content Security Policy of websites.)
--disable-ws  # (Disable Web Security on Chromium-based browsers.)
--enable-ws  # (Enable Web Security on Chromium-based browsers.)
--enable-sync  # (Enable "Chrome Sync" on websites.)
--uc | --undetected  # (Use undetected-chromedriver to evade bot-detection.)
--uc-cdp-events  # (Capture CDP events when running in "--undetected" mode.)
--log-cdp  # ("goog:loggingPrefs", {"performance": "ALL", "browser": "ALL"})
--remote-debug  # (Sync to Chrome Remote Debugger chrome://inspect/#devices)
--ftrace | --final-trace  # (Debug Mode after each test. Don't use with CI!)
--dashboard  # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)
--dash-title=STRING  # (Set the title shown for the generated dashboard.)
--enable-3d-apis  # (Enables WebGL and 3D APIs.)
--swiftshader  # (Chrome "--use-gl=angle" / "--use-angle=swiftshader-webgl")
--incognito  # (Enable Chrome's Incognito mode.)
--guest  # (Enable Chrome's Guest mode.)
--dark  # (Enable Chrome's Dark mode.)
--devtools  # (Open Chrome's DevTools when the browser opens.)
--rs | --reuse-session  # (Reuse browser session for all tests.)
--rcs | --reuse-class-session  # (Reuse session for tests in class.)
--crumbs  # (Delete all cookies between tests reusing a session.)
--disable-beforeunload  # (Disable the "beforeunload" event on Chrome.)
--window-position=X,Y  # (Set the browser's starting window position.)
--window-size=WIDTH,HEIGHT  # (Set the browser's starting window size.)
--maximize  # (Start tests with the browser window maximized.)
--screenshot  # (Save a screenshot at the end of each test.)
--no-screenshot  # (No screenshots saved unless tests directly ask it.)
--visual-baseline  # (Set the visual baseline for Visual/Layout tests.)
--external-pdf  # (Set Chromium "plugins.always_open_pdf_externally":True.)
--timeout-multiplier=MULTIPLIER  # (Multiplies the default timeout values.)
--list-fail-page  # (After each failing test, list the URL of the failure.)

(See the full list of command-line option definitions here. For detailed examples of command-line options, see customizing_test_runs.md)


šŸ”µ During test failures, logs and screenshots from the most recent test run will get saved to the latest_logs/ folder. Those logs will get moved to archived_logs/ if you add --archive_logs to command-line options, or have ARCHIVE_EXISTING_LOGS set to True in settings.py, otherwise log files with be cleaned up at the start of the next test run. The test_suite.py collection contains tests that fail on purpose so that you can see how logging works.

cd examples/

pytest test_suite.py --chrome

pytest test_suite.py --firefox

An easy way to override seleniumbase/config/settings.py is by using a custom settings file. Here's the command-line option to add to tests: (See examples/custom_settings.py) --settings_file=custom_settings.py (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)

šŸ”µ To pass additional data from the command-line to tests, add --data="ANY STRING". Inside your tests, you can use self.data to access that.

šŸ”µ When running tests with pytest, you'll want a copy of pytest.ini in your root folders. When running tests with pynose, you'll want a copy of setup.cfg in your root folders. These files specify default configuration details for tests. Test folders should also include a blank init.py file to allow your test files to import other files from that folder.

šŸ”µ sbase mkdir DIR creates a folder with config files and sample tests:

sbase mkdir ui_tests

That new folder will have these files:

ui_tests/
ā”œā”€ā”€ __init__.py
ā”œā”€ā”€ my_first_test.py
ā”œā”€ā”€ parameterized_test.py
ā”œā”€ā”€ pytest.ini
ā”œā”€ā”€ requirements.txt
ā”œā”€ā”€ setup.cfg
ā”œā”€ā”€ test_demo_site.py
└── boilerplates/
    ā”œā”€ā”€ __init__.py
    ā”œā”€ā”€ base_test_case.py
    ā”œā”€ā”€ boilerplate_test.py
    ā”œā”€ā”€ classic_obj_test.py
    ā”œā”€ā”€ page_objects.py
    ā”œā”€ā”€ sb_fixture_test.py
    └── samples/
        ā”œā”€ā”€ __init__.py
        ā”œā”€ā”€ google_objects.py
        ā”œā”€ā”€ google_test.py
        ā”œā”€ā”€ sb_swag_test.py
        └── swag_labs_test.py

ProTipā„¢: You can also create a boilerplate folder without any sample tests in it by adding -b or --basic to the sbase mkdir command:

sbase mkdir ui_tests --basic

That new folder will have these files:

ui_tests/
ā”œā”€ā”€ __init__.py
ā”œā”€ā”€ pytest.ini
ā”œā”€ā”€ requirements.txt
└── setup.cfg

Of those files, the pytest.ini config file is the most important, followed by a blank __init__.py file. There's also a setup.cfg file (for pynose). Finally, the requirements.txt file can be used to help you install seleniumbase into your environments (if it's not already installed).

ProTipā„¢: Add --gha to include a GitHub Actions .yml file with default settings:

ui_tests/
└── .github                    
    └── workflows/             
        └── python-package.yml

Let's try an example of a test that fails:

""" test_fail.py """
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class MyTestClass(BaseCase):

    def test_find_army_of_robots_on_xkcd_desert_island(self):
        self.goto("https://xkcd.com/731/")
        self.assert_element("div#ARMY_OF_ROBOTS", timeout=1)  # This should fail

You can run it from the examples/ folder like this:

pytest test_fail.py

šŸ”µ You'll notice that a logs folder, ./latest_logs/, was created to hold information (and screenshots) about the failing test. During test runs, past results get moved to the archived_logs folder if you have ARCHIVE_EXISTING_LOGS set to True in settings.py, or if your run tests with --archive-logs. If you choose not to archive existing logs, they will be deleted and replaced by the logs of the latest test run.


šŸ”µ The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

pytest --dashboard --rs --headless

šŸ”µ Additionally, you can host your own SeleniumBase Dashboard Server on a port of your choice. Here's an example of that using Python's http.server:

python -m http.server 1948

šŸ”µ Now you can navigate to http://localhost:1948/dashboard.html in order to view the dashboard as a web app. This requires two different terminal windows: one for running the server, and another for running the tests, which should be run from the same directory. (Use Ctrl+C to stop the http server.)

šŸ”µ Here's a full example of what the SeleniumBase Dashboard may look like:

pytest test_suite.py test_image_saving.py --dashboard --rs --headless

āœ… Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

pytest test_suite.py --html=report.html

āœ… When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example: --dashboard --html=dashboard.html), then the Dashboard will become an advanced html report when all the tests complete.

āœ… Here's an example of an upgraded html report:

pytest test_suite.py --dashboard --html=report.html

If viewing pytest html reports in Jenkins, you may need to configure Jenkins settings for the html to render correctly. This is due to Jenkins CSP changes.

You can also use --junit-xml=report.xml to get an xml report instead. Jenkins can use this file to display better reporting for your tests.

pytest test_suite.py --junit-xml=report.xml

The --report option gives you a fancy report after your test suite completes.

pynose test_suite.py --report

(NOTE: You can add --show-report to immediately display pynose reports after the test suite completes. Only use --show-report when running tests locally because it pauses the test run.)

(The behave_bdd/ folder can be found in the examples/ folder.)

behave behave_bdd/features/ -D dashboard -D headless

You can also use --junit to get .xml reports for each behave feature. Jenkins can use these files to display better reporting for your tests.

behave behave_bdd/features/ --junit -D rs -D headless

See: https://allurereport.org/docs/pytest/

SeleniumBase no longer includes allure-pytest as part of installed dependencies. If you want to use it, install it first:

pip install allure-pytest

Now your tests can create Allure results files, which can be processed by Allure Reports.

pytest test_suite.py --alluredir=allure_results

If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add --proxy=IP_ADDRESS:PORT as an argument on the command line.

pytest proxy_test.py --proxy=IP_ADDRESS:PORT

If the proxy server that you wish to use requires authentication, you can do the following (Chromium only):

pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT

SeleniumBase also supports SOCKS4 and SOCKS5 proxies:

pytest proxy_test.py --proxy="socks4://IP_ADDRESS:PORT"

pytest proxy_test.py --proxy="socks5://IP_ADDRESS:PORT"

To make things easier, you can add your frequently-used proxies to PROXY_LIST in proxy_list.py, and then use --proxy=KEY_FROM_PROXY_LIST to use the IP_ADDRESS:PORT of that key.

pytest proxy_test.py --proxy=proxy1

šŸ”µ If you wish to change the User-Agent for your browser tests (Chromium and Firefox only), you can add --agent="USER AGENT STRING" as an argument on the command-line.

pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU"

šŸ”µ self.accept_alert() automatically waits for and accepts alert pop-ups. self.dismiss_alert() automatically waits for and dismisses alert pop-ups. On occasion, some methods like self.click(SELECTOR) might dismiss a pop-up on its own because they call JavaScript to make sure that the readyState of the page is complete before advancing. If you're trying to accept a pop-up that got dismissed this way, use this workaround: Call self.find_element(SELECTOR).click() instead, (which will let the pop-up remain on the screen), and then use self.accept_alert() to accept the pop-up (more on that here). If pop-ups are intermittent, wrap code in a try/except block.

šŸ”µ Learn about SeleniumBase Interactive Walkthroughs (in the examples/tour_examples/ folder). It's great for prototyping a website onboarding experience.


Here's an example of running tests with some additional features enabled:

pytest [YOUR_TEST_FILE.py] --with-db-reporting --with-s3-logging

šŸ”µ Navigating to a web page: (and related commands)

self.goto("https://xkcd.com/378/")  # This method opens the specified page.

self.go_back()  # This method navigates the browser to the previous page.

self.go_forward()  # This method navigates the browser forward in history.

self.refresh_page()  # This method reloads the current page.

self.get_current_url()  # This method returns the current page URL.

self.get_page_source()  # This method returns the current page source.

ProTipā„¢: You can use the self.get_page_source() method with Python's find() command to parse through HTML to find something specific. (For more advanced parsing, see the BeautifulSoup example.)

source = self.get_page_source()
head_open_tag = source.find('<head>')
head_close_tag = source.find('</head>', head_open_tag)
everything_inside_head = source[head_open_tag+len('<head>'):head_close_tag]

šŸ”µ Clicking:

To click an element on the page:

self.click("div#my_id")

ProTipā„¢: In most web browsers, you can right-click on a page and select Inspect Element to see the CSS selector details that you'll need to create your own scripts.

šŸ”µ Typing Text:

self.type(selector, text) # updates the text from the specified element with the specified value. An exception is raised if the element is missing or if the text field is not editable. Example:

self.type("input#id_value", "2012")

You can also use self.add_text() or the WebDriver .send_keys() command, but those won't clear the text box first if there's already text inside.

šŸ”µ Getting the text from an element on a page:

text = self.get_text("header h2")

šŸ”µ Getting the attribute value from an element on a page:

attribute = self.get_attribute("#comic img", "title")

šŸ”µ Asserting existence of an element on a page within some number of seconds:

self.wait_for_element_present("div.my_class", timeout=10)

(NOTE: You can also use: self.assert_element_present(ELEMENT))

šŸ”µ Asserting visibility of an element on a page within some number of seconds:

self.wait_for_element_visible("a.my_class", timeout=5)

(NOTE: The short versions of that are self.find_element(ELEMENT) and self.assert_element(ELEMENT). The find_element() version returns the element.)

Since the line above returns the element, you can combine that with .click() as shown below:

self.find_element("a.my_class", timeout=5).click()

# But you're better off using the following statement, which does the same thing:

self.click("a.my_class")  # DO IT THIS WAY!

ProTipā„¢: You can use dots to signify class names (Ex: div.class_name) as a simplified version of div[class="class_name"] within a CSS selector.

You can also use *= to search for any partial value in a CSS selector as shown below:

self.click('a[name*="partial_name"]')

šŸ”µ Asserting visibility of text inside an element on a page within some number of seconds:

self.assert_text("Make it so!", "div#trek div.picard div.quotes")
self.assert_text("Tea. Earl Grey. Hot.", "div#trek div.picard div.quotes", timeout=3)

(NOTE: self.find_text(TEXT, ELEMENT) and self.wait_for_text(TEXT, ELEMENT) also do this. For backwards compatibility, older method names were kept, but the default timeout may be different.)

šŸ”µ Asserting Anything:

self.assert_true(var1 == var2)

self.assert_false(var1 == var2)

self.assert_equal(var1, var2)

šŸ”µ Useful Conditional Statements: (with creative examples)

ā“ is_element_visible(selector): (visible on the page)

if self.is_element_visible('div#warning'):
    print("Red Alert: Something bad might be happening!")

ā“ is_element_present(selector): (present in the HTML)

if self.is_element_present('div#top_secret img.tracking_cookie'):
    self.contact_cookie_monster()  # Not a real SeleniumBase method
else:
    current_url = self.get_current_url()
    self.contact_the_nsa(url=current_url, message="Dark Zone Found")  # Not a real SeleniumBase method
def is_there_a_cloaked_klingon_ship_on_this_page():
    if self.is_element_present("div.ships div.klingon"):
        return not self.is_element_visible("div.ships div.klingon")
    return False

ā“ is_text_visible(text, selector): (text visible on element)

if self.is_text_visible("You Shall Not Pass!", "h1"):
    self.goto("https://www.youtube.com/watch?v=3xYXUeSmb-Y")
def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):
    selector = "div.superbowl_%s div.commercials div.transcript div.picard" % superbowl_year
    if self.is_text_visible("Yes, it was I who summoned you all here.", selector):
        return "Picard Paramount+ Superbowl Ad 2020"
    elif self.is_text_visible("Commander, signal the following: Our Network is Secure!"):
        return "Picard Mirror Universe iboss Superbowl Ad 2018"
    elif self.is_text_visible("For the Love of Marketing and Earl Grey Tea!", selector):
        return "Picard Mirror Universe HubSpot Superbowl Ad 2015"
    elif self.is_text_visible("Delivery Drones... Engage", selector):
        return "Picard Mirror Universe Amazon Superbowl Ad 2015"
    elif self.is_text_visible("Bing it on Screen!", selector):
        return "Picard Mirror Universe Microsoft Superbowl Ad 2015"
    elif self.is_text_visible("OK Glass, Make it So!", selector):
        return "Picard Mirror Universe Google Superbowl Ad 2015"
    elif self.is_text_visible("Number One, I've Never Seen Anything Like It.", selector):
        return "Picard Mirror Universe Tesla Superbowl Ad 2015"
    elif self.is_text_visible("Let us make sure history never forgets the name ... Facebook", selector):
        return "Picard Mirror Universe Facebook Superbowl Ad 2015"
    elif self.is_text_visible("""With the first link, the chain is forged.
                              The first speech censored, the first thought forbidden,
                              the first freedom denied, chains us all irrevocably.""", selector):
        return "Picard Mirror Universe Wikimedia Superbowl Ad 2015"
    else:
        raise Exception("Reports of my assimilation are greatly exaggerated.")

ā“ is_link_text_visible(link_text):

if self.is_link_text_visible("Stop! Hammer time!"):
    self.click_link("Stop! Hammer time!")
self.switch_to_window(1)  # This switches to the new tab (0 is the first one)

šŸ”µ iframes follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:

self.switch_to_frame("iframe")
# ... Now perform actions inside the iframe
self.switch_to_parent_frame()  # Exit the current iframe

To exit from multiple iframes, use self.switch_to_default_content(). (If inside a single iframe, this has the same effect as self.switch_to_parent_frame().)

self.switch_to_frame('iframe[name="frame1"]')
self.switch_to_frame('iframe[name="frame2"]')
# ... Now perform actions inside the inner iframe
self.switch_to_default_content()  # Back to the main page

šŸ”µ You can also use a context manager to act inside iframes:

with self.frame_switch("iframe"):
    # ... Now perform actions while inside the code block
# You have left the iframe

This also works with nested iframes:

with self.frame_switch('iframe[name="frame1"]'):
    with self.frame_switch('iframe[name="frame2"]'):
        # ... Now perform actions while inside the code block
    # You are now back inside the first iframe
# You have left all the iframes
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>

šŸ”µ It's OK if you want to use jQuery on a page that doesn't have it loaded yet. To do so, run the following command first:

self.activate_jquery()
self.execute_script("jQuery, window.scrollTo(0, 600)")  # Scrolling the page

self.execute_script("jQuery('#annoying-widget').hide()")  # Hiding elements on a page

self.execute_script("jQuery('#hidden-widget').show(0)")  # Showing hidden elements on a page

self.execute_script("jQuery('#annoying-button a').remove()")  # Removing elements on a page

self.execute_script("jQuery('%s').mouseover()" % (mouse_over_item))  # Mouse-over elements on a page

self.execute_script("jQuery('input#the_id').val('my_text')")  # Fast text input on a page

self.execute_script("jQuery('div#dropdown a.link').click()")  # Click elements on a page

self.execute_script("return jQuery('div#amazing')[0].text")  # Returns the css "text" of the element given

self.execute_script("return jQuery('textarea')[2].value")  # Returns the css "value" of the 3rd textarea element on the page

(Most of the above commands can be done directly with built-in SeleniumBase methods.)

ā— Some websites have a restrictive Content Security Policy to prevent users from loading jQuery and other external libraries onto their websites. If you need to use jQuery or another JS library on those websites, add --disable-csp as a pytest command-line option to load a Chromium extension that bypasses the CSP.

start_page = "https://xkcd.com/465/"
destination_page = "https://github.com/seleniumbase/SeleniumBase"
self.goto(start_page)
referral_link = '''<a class='analytics test' href='%s'>Free-Referral Button!</a>''' % destination_page
self.execute_script('''document.body.innerHTML = \"%s\"''' % referral_link)
self.click("a.analytics")  # Clicks the generated button

(Due to popular demand, this traffic generation example has been included in SeleniumBase with the self.generate_referral(start_page, end_page) and the self.generate_traffic(start_page, end_page, loops) methods.)

from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class DeferredAssertTests(BaseCase):
    def test_deferred_asserts(self):
        self.goto("https://xkcd.com/993/")
        self.wait_for_element("#comic")
        self.deferred_assert_element('img[alt="Brand Identity"]')
        self.deferred_assert_element('img[alt="Rocket Ship"]')  # Will Fail
        self.deferred_assert_element("#comicmap")
        self.deferred_assert_text("Fake Item", "ul.comicNav")  # Will Fail
        self.deferred_assert_text("Random", "ul.comicNav")
        self.deferred_assert_element('a[name="Super Fake !!!"]')  # Will Fail
        self.deferred_assert_exact_text("Brand Identity", "#ctitle")
        self.deferred_assert_exact_text("Fake Food", "#comic")  # Will Fail
        self.process_deferred_asserts()

deferred_assert_element() and deferred_assert_text() will save any exceptions that would be raised. To flush out all the failed deferred asserts into a single exception, make sure to call self.process_deferred_asserts() at the end of your test method. If your test hits multiple pages, you can call self.process_deferred_asserts() before navigating to a new page so that the screenshot from your log files matches the URL where the deferred asserts were made.

self.driver.delete_all_cookies()
capabilities = self.driver.capabilities
self.driver.find_elements("partial link text", "GitHub")

(In general, you'll want to use the SeleniumBase versions of methods when available.)

pytest --reruns=1 --reruns-delay=1

"Catch bugs in QA before deploying code to Production!"


Available Tools

24 tools
assert_conditionAssert ConditionA
Read-onlyIdempotent

Verify a browser condition and report failure as an error.

Use this tool when an expected page state must be explicitly verified. It is a read-only verification operation: it does not click, type, navigate, scroll, or otherwise intentionally modify the page.

Element and text assertions may block while SeleniumBase waits for the condition, up to timeout seconds. Title and URL assertions are checked immediately and ignore timeout. A failed assertion or timeout is handled by handle_sb_errors and returned as a descriptive tool error; it is not reported as a successful result.

Unlike check_if_condition, this tool does not merely return whether a condition is true: a failed expectation is an error. Unlike wait_for_condition, its purpose is to verify an expectation, not merely synchronize with a changing page.

Args: check: - "element_present": Verify that the selector identifies a present element. - "element_visible": Verify that the selector identifies a visible element. - "text_visible": Verify that expected text is visible within selector, or within the whole HTML document if selector is omitted. - "title": Verify the exact current page title immediately. - "url": Verify the exact current URL immediately. - "url_contains": Verify that the current URL contains expected immediately.

selector: CSS or SeleniumBase selector for element and text checks.
    Required for element checks; optional for text_visible.

expected: Expected text, title, or URL value. Required for
    text_visible, title, url, and url_contains.

exact: For text_visible only, require an exact text match instead
    of a substring match.

timeout: Maximum seconds to wait for element/text assertions.
    Must be >= 0. Ignored for title and URL assertions.

Returns: A confirmation message when the assertion passes. If the assertion fails or times out, the error handler returns the resulting error instead of a success message.

Tool selection: - Inspect a condition without failing -> check_if_condition. - Wait for a condition to become true -> wait_for_condition. - Verify that an expected condition is true -> assert_condition.

ParametersJSON Schema
NameRequiredDescriptionDefault
checkNoelement_visible
exactNo
timeoutNo
expectedNo
selectorNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations (readOnlyHint, idempotentHint) by explicitly stating it is read-only and does not modify the page. It also discloses blocking behavior for element/text assertions, immediate checks for title/URL, and how failures are handled via handle_sb_errors. This adds substantial context not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured logically with clear sections (purpose, behavioral notes, args, returns, tool selection). While it is long, every paragraph serves a distinct purpose and the core purpose is front-loaded. There is no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 5 parameters and 6 check types, the description covers every parameter's semantics, the exact return behavior (confirmation or error), and the timeout handling differences. It also addresses how it relates to siblings. An agent has all necessary information to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description's 'Args' section thoroughly explains each parameter: what each check enum means, when selector/expected are required, the exact parameter's effect, and timeout constraints. This fully compensates for the lack of schema descriptions and provides far more meaning than the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Verify a browser condition') and then distinguishes itself from check_if_condition and wait_for_condition, making its purpose unambiguous. The tool selection section further reinforces what this tool does versus alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use it ('when an expected page state must be explicitly verified') and provides a dedicated 'Tool selection' list naming two sibling tools and the conditions under which they should be chosen instead. This gives clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_if_conditionCheck ConditionA
Read-onlyIdempotent

Check the current state of an element or text without waiting for the condition to become true.

Use this tool when you need an immediate boolean observation of the current page state. Use wait_for_condition when the condition may become true later and the workflow should wait for it. Use assert_condition when the condition is an expected requirement and failure should be treated as an assertion error.

Args: check: The element state to inspect when text is not provided: - "present": Return True when at least one matching element exists. - "visible": Return True when the matching element is visible. check is ignored when text is provided.

selector:
    CSS selector or SeleniumBase selector identifying the element.

text:
    Optional text to check for visibility within `selector`. When
    provided, this takes precedence over `check`; the tool checks text
    visibility instead of element presence or visibility. Use this when
    the question is "Is this text currently visible?" rather than
    whether the element itself is present or visible.

Returns: True or False indicating whether the requested condition is currently satisfied. Missing elements return False rather than raising an exception. If there's an error, returns a string with error details.

Tool selection: - Immediate boolean observation -> use check_if_condition. - Wait for a state/content transition -> use wait_for_condition. - Verify an expected condition -> use assert_condition. - Need element details of matching elements -> use find_elements. - Need to read page or element content -> use get_content.

Notes: This tool does not intentionally wait for elements or text to appear. It is intended for checking the current state only. If page timing or asynchronous loading matters, use wait_for_condition instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNo
checkNovisible
selectorNobody

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false. The description adds valuable behavioral detail beyond these annotations: it explicitly states the tool does not wait, missing elements return False instead of raising an exception, and errors return a string with details. This gives the agent a realistic model of the tool's runtime behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: purpose, usage guidance, arguments, returns, and tool selection. The key non-waiting behavior is front-loaded, and the tool selection section is compact and actionable. Each section earns its place without unnecessary repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for an agent to select and invoke the tool correctly. It covers purpose, parameter semantics, return behavior, error handling, non-waiting behavior, and explicit routing to sibling tools. Given the annotations and output schema, nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the burden of explaining parameters, and it does. It defines the 'check' enum values ('present' and 'visible'), clarifies that 'check' is ignored when 'text' is provided, explains 'selector' as a CSS/SeleniumBase selector, and describes 'text' as an optional visibility check that takes precedence. This fully compensates for the schema's lack of descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Check the current state of an element or text without waiting for the condition to become true.' It clearly distinguishes itself from siblings by naming wait_for_condition and assert_condition and describing the difference in behavior. The purpose is unmistakable even before reading the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool versus alternatives: 'Immediate boolean observation -> use check_if_condition', 'Wait for a state/content transition -> use wait_for_condition', 'Verify an expected condition -> use assert_condition'. It also lists other sibling tools such as find_elements and get_content for different needs, giving an agent clear routing rules.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

click_elementClick ElementA

Click element(s) matching a CSS, XPath, or supported text selector.

Use this tool for normal clicks, clicking a specific matching occurrence, clicking all visible matches, conditional clicks, or clicks scoped to a parent element.

Selection behavior and priority: nth is 1-based and takes precedence over every other click mode. Otherwise, all_matches=True clicks every currently visible match. Otherwise, only_if_visible=True clicks only if a match is visible. Otherwise, parent_selector scopes the click to a nested element. If none of the above are set, then a regular click is performed.

Args: selector: CSS selector, XPath selector, or supported SeleniumBase text-matching selector. Text-matching selectors such as a:contains("Sign in") are supported only for single-element clicks; do not use them with all_matches=True.

nth: 1-based occurrence to click when multiple elements match.
    Must be >= 1 if provided. Takes precedence over `all_matches`,
    `only_if_visible`, and `parent_selector`.

all_matches: If True, click every currently visible matching element
    in order of appearance. Ignored when `nth` is provided. Use only
    when multiple clicks are intentionally desired, such as for
    clicking all the checkboxes in a section of a webpage.
    If any of the click actions induces page navigation, then
    subsequent clicks are cancelled without any exceptions raised.

only_if_visible: If True, click only when the target is already
    visible; do not wait for it to become visible.

parent_selector: CSS/XPath selector for the parent/container in which
    to find `selector`. Used only for the nested-click mode.
    Can be used to click an element inside a parent iframe.

timeout: Maximum seconds to wait for a normal click operation.
    Default: 5. Not used by conditional or bulk click modes.

scroll: If True, scroll the target into view before a normal or
    indexed click. Default: True.

Examples: - Click the first button: click_element("button") - Click the 2nd button: click_element("button", nth=2) - Click all checkboxes: click_element('input[type="checkbox"]', all_matches=True) - Click the first visible link: click_element("a", only_if_visible=True) - Click the first button that's inside the first iframe: click_element("button", parent_selector="iframe")

Error behavior: With the exception of using 'only_if_visible=True', if there's no matching element found within the timeout, then @handle_sb_errors returns details from the exception raised.

When not to use: - Do not use this tool if you need to hover an element first before clicking; use hover_action with action="hover_and_click" instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
nthNo
scrollNo
timeoutNo
selectorYes
all_matchesNo
only_if_visibleNo
parent_selectorNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses subtle runtime behavior: the priority order of selection modes, that all_matches cancels subsequent clicks if page navigation occurs, that only_if_visible does not wait for visibility, and the timeout/error handling behavior. This is exactly the kind of context an agent needs beyond readOnly/openWorld flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although substantial, every section contributes: purpose, selection priority, per-argument detail, examples, error behavior, and anti-guidance. It is organized with clear headers and front-loaded with the core action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich parameter set and no parameter documentation in the schema, the description covers selection modes, defaults, exclusions, error behavior, and example calls. The presence of an output schema means return-value documentation is already handled, so nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description carries the full parameter burden and does so thoroughly. It defines selector types, explains nth precedence and 1-based indexing, clarifies all_matches cancellation, notes timeout default and non-use in conditional/bulk modes, and documents parent_selector iframe support.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and resource: 'Click element(s) matching a CSS, XPath, or supported text selector.' It then enumerates the distinct click modes (nth, all matches, conditional, parent-scoped), which clearly separates it from sibling tools like hover_action or focus_element.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'When not to use' section explicitly routes hover-before-click scenarios to hover_action, and the description repeatedly states the intended use cases: normal, indexed, bulk, conditional, and parent-scoped clicks. This gives an agent clear decision rules.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

close_browserClose BrowserA
Idempotent

Close the active browser session and release browser resources.

Call this when the browser automation workflow is finished. Closing the session ends the persistent browser state, including its open tabs, cookies, navigation history, and page state. If browser automation is needed afterward, start a new session with start_browser.

This operation is safe to call when no browser session is active.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses concrete behavioral effects: the session is closed, persistent browser state ends, and resources are released. It lists specific affected state such as open tabs, cookies, navigation history, and page state. It explicitly confirms idempotent behavior, consistent with the idempotentHint annotation, without contradicting any annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it states the core action in the first sentence, then gives usage context and safety confirmation. Every sentence contributes meaningful information without redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with existing output schema, the description is fully sufficient. It covers the operation, the reason to call it, the consequence of closing, the alternative for subsequent sessions, and the no-op safety case. Nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no semantic ambiguity to resolve. Per the baseline guidance for no-parameter tools, a score of 4 is appropriate even though the description adds no parameter-specific details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific verb and resource: 'Close the active browser session and release browser resources.' This immediately differentiates it from sibling tools like start_browser, open_url, and manage_tabs. The scope is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to call it: 'Call this when the browser automation workflow is finished.' It also names the alternative for future work: 'If browser automation is needed afterward, start a new session with start_browser.' It even covers the edge case of calling with no active session.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_elementsFind ElementsA
Read-onlyIdempotent

Find matching elements and return structured element information.

Use this tool when you need to discover how many elements match a selector, inspect their text/tag names, or inspect the HTML of multiple matches.

This tool converts matching elements into ordinary serializable dictionaries. It does not return live SeleniumBase element objects.

Args: selector: A CSS selector, or an XPath selector that SeleniumBase can convert to CSS. In sb.find_elements, SeleniumBase automatically attempts to convert XPath to CSS. Some XPath expressions, such as those using contains(...), cannot be converted to CSS and therefore aren't supported by this tool.

timeout: Maximum number of seconds to wait for at least one matching
    element to appear. If the selector is an XPath selector that
    cannot be converted into a valid CSS selector, then the wait
    might be less than the timeout.

include_html: If True, include each matching element's outer HTML.
    If False, return only tag name and text.

Returns: A dictionary containing: - count: Number of matching elements found. - matches: A list of element dictionaries containing tag_name and text, plus html when include_html=True. If there's an error during search, then "error" is added into the returned dictionary with error details.

Tool selection: - Need structured information about matching elements -> use find_elements. - Need the visible text/HTML of a page or a single element -> use get_content. - Need to click one of several matches -> use click_element with nth. - Need to know whether an element is present/visible -> use check_if_condition.

Notes: Element handles cannot be persisted across MCP calls. If you find elements and then need to act on one, resolve it again with the appropriate interaction tool.

For uncaught errors, @handle_sb_errors returns strings.
ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNo
selectorYes
include_htmlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false. The description adds substantial behavioral context beyond those: it clarifies the tool returns serializable dictionaries rather than live SeleniumBase objects, explains XPath conversion limitations that may reduce timeout effectiveness, and details error handling via @handle_sb_errors returning strings. No contradictions; this is complementary and rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, args, returns, tool selection, notes). It front-loads the core purpose and usage, then provides details. A few sentences could be tightened (e.g., the XPath explanation is slightly verbose), but overall every part earns its place. The length is justified by the need to cover alternatives and caveats.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (3 parameters, 1 required, 1 optional boolean, 1 optional numeric) and the presence of an output schema (mentioned via return structure), the description covers all essentials: return format, error cases, usage boundaries, and operational constraints like handle persistence. An agent can call this tool correctly without further research.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries full responsibility for parameter meaning. It explains selector (CSS or XPath, with conversion caveats), timeout (max wait, behavior when XPath can't be converted), and include_html (what True/False returns). Each parameter gets concrete semantics that the schema itself lacks, fully compensating for the missing descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb and resource: 'Find matching elements and return structured element information.' It goes on to list concrete uses (count matches, inspect text/tag names, inspect HTML) and explicitly distinguishes itself from sibling tools by naming alternatives like get_content, click_element, and check_if_condition. This leaves no ambiguity about what the tool does and how it differs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Tool selection' section gives explicit when-to-use guidance for this tool versus get_content, click_element, and check_if_condition, with conditions for each. It also adds a critical usage note that element handles cannot be persisted across MCP calls, telling the agent to re-resolve elements. This is exemplary routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

focus_elementFocus ElementA

Scroll to, focus, or highlight an element.

This tool does not click, type, select, hover, or otherwise activate the element. Use click_element, type_text, or hover_action for those operations.

Args: selector: CSS selector or SeleniumBase selector identifying the target.

action:
    - "scroll_to_element": Scroll the element into the viewport.
    - "focus": Move keyboard focus to the element.
    - "highlight": Temporarily highlight the element for debugging or
      demonstration by changing the border color. May affect timing
      and/or reduce stealth.

timeout: Maximum seconds to wait for the target element. Default: 5.

If there's no matching element found within the timeout, then @handle_sb_errors returns details from the exception raised.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNoscroll_to_element
timeoutNo
selectorYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses that the tool never activates the element, that highlight may affect timing and reduce stealth, and that timeout failures surface error details via @handle_sb_errors. This adds meaningful behavior context the structured metadata does not.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, followed by exclusions and parameter details. Every sentence earns its place; the length is justified by the need to document three action modes and clarify non-activation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers what the tool does, what it doesn't do, when to use alternatives, all parameter semantics, and error behavior. With an output schema present, no return-value explanation is required, making the definition complete for an agent to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full responsibility for documenting parameters. It explains selector semantics, enumerates each action value with its effect, and defines timeout with its default, fully compensating for the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource statement: 'Scroll to, focus, or highlight an element.' It then explicitly distinguishes itself from click/type/select/hover operations, which clearly separates it from related sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states what the tool does NOT do and names the sibling tools to use for those cases: click_element, type_text, and hover_action. The action enum also gives concrete use cases for each mode, leaving no ambiguity about when to choose this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_attributesGet AttributesA
Read-onlyIdempotent

Get a specific HTML attribute (or all attributes) from the first-matching element. Examples of possible attributes include href, src, value, class, id, name, type, aria-label, etc.

Args: selector: CSS selector or SeleniumBase-supported XPath selector.

attribute: Specific HTML attribute to retrieve. When omitted, return
    all HTML attributes of the first matching element as a dictionary.

timeout: Maximum seconds to wait for the target element. Default: 5.

Tool selection: - Need one or more HTML attribute values from a specific element -> use this tool. - Need to discover multiple matching elements or inspect their text -> use 'find_elements'. - Need visible text or HTML content -> use 'get_content'. - Need to check element presence/visibility -> use 'check_if_condition'.

This is a read-only operation: It finds elements to get the requested data, but it does not make any modifications to those elements.

If there's no matching element found within the timeout, then @handle_sb_errors returns details from the exception raised.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNo
selectorYes
attributeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered externally. The description adds value beyond that by clarifying the first-matching-element behavior and by describing what happens when no element is found within the timeout via @handle_sb_errors. It also restates the read-only nature in a way consistent with the annotations, though this is somewhat redundant.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with 'Args' and 'Tool selection' sections and front-loads the main purpose. The read-only sentence is helpful but largely duplicates the annotations, and the prose could be slightly tightened without losing value. Overall it is appropriately sized and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter read-only tool with an output schema and safety annotations, the description covers all necessary operational context: parameter semantics, first-match behavior, what happens on timeout, and which sibling tools to use instead. No critical gap remains for an agent to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It does so thoroughly: selector includes supported selector syntax, attribute explains the omitted-behavior returning a dictionary, and timeout gives its meaning and default. The examples and default values add meaning the schema does not provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise action: 'Get a specific HTML attribute (or all attributes) from the first-matching element.' This clearly identifies the resource, the verb, and the first-match scoping, and the attribute examples make the domain concrete. It also distinguishes this tool from sibling tools by emphasizing attribute retrieval rather than text, content, or presence checks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Tool selection' section explicitly states when to use this tool versus find_elements, get_content, and check_if_condition. It gives concrete conditions such as 'Need one or more HTML attribute values' and 'Need to discover multiple matching elements or inspect their text,' so an agent is not left to infer the right choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contentGet ContentA
Read-onlyIdempotent

Read visible text, HTML, or discovered URLs from the selected element.

Use this tool when you need to get actual page content or URL information rather than page metadata.

Args: selector: CSS selector or SeleniumBase-supported XPath selector. Default: "body".

output_format:
    - "text": Return visible text from the selected element.
    - "html": Return HTML from the selected element.
    - "urls": Return URLs discovered by SeleniumBase within the
      selected element. Returned URLs are normalized to full URLs
      with their protocol prefixes.

timeout: Maximum seconds to wait for the target element. Default: 5.

Tool selection: - Need URL, title, origin, or User-Agent -> use get_page_info. - Need visible text, html, or URLs on a page -> use get_content. - Need structured information about matching elements -> use find_elements. - Need to check element presence/visibility -> use check_if_condition. - Need to wait for content to appear -> use wait_for_condition.

If there's no matching element found within the timeout, then @handle_sb_errors returns details from the exception raised.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNo
selectorNobody
output_formatNotext

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds valuable behavioral context beyond that: it specifies timeout wait behavior, URL normalization details, and the error-handling fallback via @handle_sb_errors when no element matches. This goes beyond what annotations provide, earning a 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: initial summary, Args, Tool selection, and error note. While a bit long, each sentence earns its place—the tool selection list is genuinely useful, and the argument descriptions are concise. It is front-loaded with the core purpose, and the length is justified by the need to explain three output formats and sibling routing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 3 optional parameters, the description covers everything an agent needs: the exact purpose, all parameter semantics, defaults, output format behaviors, timeout, error handling, and clear guidance on when to use it versus siblings. Even if an output schema exists, the description explains the return types conceptually (visible text, html, urls) and the URL normalization behavior, ensuring complete understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden for parameter explanation. It describes 'selector' with type and default, 'output_format' with each enum value and its meaning, and 'timeout' with default and purpose. This fully compensates for the lack of schema descriptions and adds meaning far beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Read visible text, HTML, or discovered URLs from the selected element.' It specifies the verb (read), the resource (selected element), and the output types. It also explicitly contrasts with get_page_info, distinguishing page content versus metadata, which makes sibling differentiation clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Tool selection' section provides explicit when-to-use guidance with a list mapping needs to specific tools (get_page_info, get_content, find_elements, etc.). It also states when to use this tool over metadata tools, leaving no ambiguity about when to select it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_page_infoGet Page InfoA
Read-onlyIdempotent

Get current browser session and page metadata.

Use this as the primary tool for determining where the browser currently is after navigation, clicks, form submissions, redirects, reloads, or tab switches.

This is a read-only metadata operation: It does not inspect arbitrary page content, find elements, check visibility, wait for conditions, or assert expected values.

Returns: A dictionary containing: - running: True when browser metadata was successfully retrieved. False when no session is available or metadata retrieval failed. - url: The complete current page URL, including path and query string. - title: The current document title. - origin: The current page origin (scheme, host, and port). - user_agent: The browser's current User-Agent string.

Tool selection: - Need URL, title, origin, or User-Agent -> use get_page_info. - Need visible page text or HTML -> use get_content. - Need information about matching elements -> use find_elements. - Need an immediate state check -> use check_if_condition. - Need to wait for a condition -> use wait_for_condition. - Need to verify an expected condition -> use assert_condition.

Unlike a dedicated browser-status tool, get_page_info is the single source of browser/page metadata. If no browser session is active, it returns {"running": False} instead of attempting to access a page.

This operation does not navigate, reload, click, type, or otherwise modify the current page.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false. The description adds critical behavioral context: it explicitly states 'This operation does not navigate, reload, click, type, or otherwise modify the current page' and explains the edge case 'If no browser session is active, it returns {"running": False} instead of attempting to access a page.' This goes beyond the annotation flags and clarifies exact behavior when no session exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: first sentence states purpose, then usage context, then return values, then tool selection, then edge-case behavior. It is front-loaded with the core purpose and each section earns its place. Despite length, it is organized with clear headers (Returns:, Tool selection:) making it easy for an agent to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters, the description fully explains the return dictionary fields (running, url, title, origin, user_agent) and the behavior when no session exists. It also covers the read-only nature and contrasts with siblings. With an output schema present (as indicated by 'Has output schema: true'), the description need not repeat all return details, but it still provides a concise summary. Complete for a metadata-fetching tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has 0 parameters, so schema coverage is trivially 100%. Per rubric, 0 params baseline is 4. The description does not need to explain parameters since there are none. It does implicitly clarify that no arguments are required, but no additional semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get current browser session and page metadata.' It explicitly lists the metadata types (URL, title, origin, user_agent) and contrasts with siblings by stating what it does NOT do (inspect content, find elements, check visibility). This distinguishes it clearly from get_content, find_elements, check_if_condition, etc., with no ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'Tool selection' rules: 'Need URL, title, origin, or User-Agent -> use get_page_info' and contrasts with alternatives like get_content, find_elements, check_if_condition, wait_for_condition, assert_condition. Also states primary use case: 'determining where the browser currently is after navigation, clicks, form submissions, redirects, reloads, or tab switches.' No ambiguity about when to call this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

hover_actionHover / Click / DragA

Hover over an element, optionally click another, or drag-and-drop.

Use this tool for hover interactions, hover-triggered menus, and drag-and-drop operations.

Args: selector: The primary element selector. For action="hover", this is the element to hover over. For action="hover_and_click", this is the element to hover over before clicking 'secondary_selector'. For action="drag_and_drop", this is the draggable source element.

secondary_selector:
    The secondary element selector.
    Required for action="hover_and_click", where it identifies
    the element to click after hovering 'selector'.
    Required for action="drag_and_drop", where it identifies the
    destination/drop target.
    Not used for action="hover".

action:
    - "hover": Hover over 'selector' only.
    - "hover_and_click": Hover over 'selector', then click
      'secondary_selector' after a short moment has passed.
    - "drag_and_drop": Drag 'selector' and drop it onto
      'secondary_selector'.

timeout: Maximum seconds to wait for 'selector'.
    For drag_and_drop, the same timeout applies to secondary_selector.
    For hover_and_click, SeleniumBase uses its own short wait for
    secondary_selector; this parameter does not extend that secondary
    wait.

Returns: A confirmation message describing the performed operation's result.

Error behavior: If a required element cannot be found or interacted with within the applicable wait period, or if an error occurs during the action, the resulting exception message is returned through @handle_sb_errors. Failing actions such as failed hover_and_click will raise exceptions.

When not to use: - Do not use this tool to click if you don't need to hover an element before clicking another; use 'click' instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNohover
timeoutNo
selectorYes
secondary_selectorNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does so thoroughly. It discloses error behavior (exceptions are returned via @handle_sb_errors), timeout semantics for each action, and the fact that hover_and_click uses a separate internal wait not extended by the timeout parameter. These are exactly the behavioral details an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (intro, Args, Returns, Error behavior, When not to use) and every sentence provides necessary information. It is detailed without being redundant—no filler or repeated schema defaults.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (three distinct actions, conditional parameter requirements, timeout nuances), the description covers all operational aspects. It explains return values as a confirmation message, error paths, and explicitly names the sibling alternative. Even with an output schema present, the description is fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate entirely. It fully explains each parameter: selector's role per action, secondary_selector's requirements for hover_and_click and drag_and_drop, the action enum values, and the timeout's conditional behavior. This adds substantial meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource statement: 'Hover over an element, optionally click another, or drag-and-drop.' It clearly distinguishes this tool from the sibling 'click_element' by explicitly stating the hover prerequisite and naming the alternative in the 'When not to use' section.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use the tool ('hover interactions, hover-triggered menus, and drag-and-drop operations') and when not to use it ('Do not use this tool to click if you don't need to hover... use click instead'). This gives the agent clear routing criteria relative to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_cookiesManage CookiesA

Manage cookies for the current browser session.

Use this tool to inspect, clear, save, or restore browser cookies. Cookie management is useful for inspecting session state, preserving login sessions between browser runs, restoring previously saved sessions, or resetting website state during testing.

Args: action: - "get_all": Return all cookies currently available to the browser, including attributes such as name, value, domain, path, expiry, and security flags. - "clear": Delete all cookies from the current browser session. - "save": Save current cookies to filename. The file may be created or overwritten. - "load": Load cookies from filename into the current browser session.

filename: Filesystem path used by save/load.
    Ignored for get_all and clear.

Returns: "get_all": Current browser cookies. "clear": Confirmation that cookies were cleared. "save": Confirmation containing the destination filename. "load": Confirmation containing the source filename.

Security: Cookie data can contain authentication credentials, session identifiers, and other private information. Only inspect, save, load, or share cookies when explicitly authorized.

`filename` is passed to SeleniumBase's cookie persistence methods and
can access the filesystem available to the MCP server. Use only
trusted, authorized paths. The save action may overwrite an existing
file.

Notes: Loading saved cookies does not guarantee restoration of a login. Cookies may be expired, invalidated, domain/path restricted, or dependent on other browser state. Navigate to the relevant site when necessary so the browser has the appropriate origin for the cookies.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNoget_all
filenameNocookies.txt

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It warns about authentication credentials and private data, notes that save may overwrite files, explains that filename can access the MCP server's filesystem, and honestly caveats that loaded cookies may not restore a login. This is unusually transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with headings for Args, Returns, Security, and Notes, with the core purpose front-loaded. The length is justified because each section adds essential behavior not otherwise conveyed, given the minimal schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a 2-parameter tool with no annotations and no output schema. It covers per-action return values, filesystem risks, overwrite behavior, and the practical limitations of loading cookies. An agent has everything needed to invoke the tool correctly and safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description fully compensates by explaining every action value and its effect, and by specifying that filename is only used by save/load and ignored for get_all/clear. The parameter meaning is unambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete resource and action set: 'Manage cookies for the current browser session' and enumerates four specific operations (inspect, clear, save, restore). The cookie focus clearly distinguishes it from sibling tools like manage_history and manage_storage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use cases: inspecting session state, preserving login sessions, restoring saved sessions, and resetting website state. It does not explicitly contrast with alternatives or state when not to use the tool, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_historyManage HistoryA

Manage or inspect the current browser tab's navigation history.

Use "back", "forward", or "reload" actions for history navigation. Use "list" to inspect history. (This one is read-only.) Use 'open_url' for navigation to an arbitrary URL.

Args: action: - "back": Go to the previous history entry, if available. - "forward": Go to the next history entry, if available. - "reload": Reload the current page while ignoring the cache. - "list": Return the current history position and entries.

Navigation actions can trigger page loads or redirects. Use 'get_page_info' afterward to verify the resulting URL or title.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNolist

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It explicitly states that list is read-only, that reload ignores the cache, and that navigation actions can trigger page loads or redirects. It also advises verifying the resulting URL or title afterward, which is practical behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: a one-sentence purpose followed by labeled action semantics and a brief navigation-caveat. Every sentence earns its place, with no filler or repetition of schema facts that are already structural.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a single optional enum parameter, an output schema, and actions fully documented, the description is complete. It covers what the tool operates on, each possible action, the read-only behavior, and cross-tool follow-up guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must explain the parameters, and it does. Every enum value for 'action' is described with its behavioral effect, from back/forward/reload to the read-only list. This fully compensates for the schema's lack of descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Manage or inspect the current browser tab's navigation history.' It clearly distinguishes the tool's scope from siblings like open_url and get_page_info by naming them explicitly, so an agent can tell exactly what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit usage instructions for each action ('Use back, forward, or reload' vs 'Use list'), identifies the read-only variant, and points to alternatives for other needs ('Use open_url for navigation to an arbitrary URL', 'Use get_page_info afterward'). This is strong when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_storageManage StorageA

Get or set a key in localStorage or sessionStorage.

Use this tool when the browser workflow needs to inspect or modify JavaScript Web Storage belonging to the current page origin.

Tool selection: - Need localStorage/sessionStorage -> use this tool. - Need cookies or authentication cookies -> use manage_cookies. - Need arbitrary JavaScript or storage operations not covered here -> use run_javascript. - Need visible page content or HTML -> use get_content. - Need an element's HTML attributes -> use get_attributes.

When not to use: - Do not use this tool for HTTP cookies; use manage_cookies instead. - Do not use this tool for arbitrary page JavaScript; use run_javascript when a higher-level tool is insufficient. - Do not use this tool to inspect values from another origin; storage is scoped to the current page origin.

Args: key: Storage key to read or modify.

value: Value to store when action="set". Required for set.

storage: "local" for localStorage or "session" for sessionStorage.

action: "get" to read the key or "set" to write the key.

Returns: The stored value for get, or a confirmation message for set.

Security: Web storage can contain authentication tokens, session identifiers, and other sensitive application state. Only use this tool with trusted sites and authorized MCP clients.

Notes: Storage belongs to the current page origin. Values from one website are not generally available to another origin.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes
valueNo
actionNoget
storageNolocal

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It explains read vs. write behavior, return values for get and set, origin scoping, and security sensitivity of web storage, which is substantial context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and organized into clear sections: tool selection, exclusions, args, returns, security, and notes. It is relatively long, but every section earns its place by helping an agent select and invoke the tool correctly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given four parameters, no annotations, and no output schema, the description is complete enough for correct invocation. It covers parameter meanings, conditional requirements, return behavior, origin restrictions, and security considerations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description documents all four parameters: key, value, storage, and action. It also clarifies the conditional requirement that value is needed for set and explains the local vs. session storage enum values, going well beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: get or set a key in localStorage or sessionStorage. The tool-selection section explicitly differentiates it from manage_cookies, run_javascript, get_content, and get_attributes, so an agent can immediately tell it apart from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance, a tool-selection list naming exact alternatives, and a when-not-to-use section with clear exclusions. It leaves no ambiguity about when this tool should be chosen over manage_cookies, run_javascript, or get_content.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_tabsManage TabsA

Manage browser tabs, including opening new ones.

Use this for listing, opening, switching, or closing tabs. Use open_url and manage_history for navigation within the active tab.

Args: action: - "list_tabs": Return each tab's index, URL, and title. Use this to find the tab_index for "switch_to_tab". - "open_new_tab": Open a new tab, optionally navigating to url. - "switch_to_tab": Switch to the tab at tab_index from "list_tabs". - "switch_to_newest_tab": Switch to the newest tab. - "close_active_tab": Close the active tab. This action must be followed by a 'manage_tabs' action that switches to a new tab, such as "switch_to_tab" or "switch_to_newest_tab".

url: URL for "open_new_tab". If not provided, "about:blank" is used.

tab_index: Tab index from "list_tabs" that is only used for the
    "switch_to_tab" action.)

switch_to: If using "open_new_tab", switch to the new tab when True.

Notes: Tab indexes are session-relative and may change after tabs are opened or closed. Use "list_tabs" to get current indexes before switching by index.

Error behavior: If there's an error during any of the tab actions, then @handle_sb_errors will propagate the exception as an error message.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNo
actionNolist_tabs
switch_toNo
tab_indexNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full disclosure burden and delivers: tab indexes are session-relative and go stale after open/close, close_active_tab has a mandatory follow-up action, open_new_tab falls back to about:blank, and errors propagate via @handle_sb_errors. These are genuinely non-obvious behavioral traps an agent needs to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The content is grouped into clear sections (Args, Notes, Error behavior) and front-loaded with the purpose statement. Every sentence earns its place given the tool handles five distinct actions with four parameters; the only blemish is a stray closing parenthesis in the tab_index entry.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers action semantics, parameter applicability, defaults, sequencing constraints, index staleness, and error propagation, so an agent can correctly drive every action. It never states a prerequisite such as the browser session needing to be running (start_browser), and edge cases like switching with zero tabs are only handled by the generic error note.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, yet every parameter is semantically documented: action gets per-enum-value behavior, url gets its default behavior, tab_index is scoped to switch_to_tab and sourced from list_tabs, and switch_to is tied to open_new_tab. The Args section fully compensates for the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Manage browser tabs') and enumerates the concrete operations: listing, opening, switching, and closing tabs. It further sharpens scope by carving out in-tab navigation as belonging to open_url and manage_history, so an agent can distinguish it from the 22 siblings without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit boundary: use this tool for tab lifecycle operations and open_url/manage_history for navigation within the active tab. It also provides intra-tool routing ('Use this to find the tab_index for switch_to_tab') and a hard sequencing rule for close_active_tab that must be followed by a switch action.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

manage_windowManage WindowA

Get or change browser window geometry or state.

Args: action: - "get_rect": Return the current window position and size. - "set_rect": Set x, y, width, and height. All four are required. - "maximize": Maximize the browser window. - "minimize": Minimize the browser window.

x: Horizontal screen position for "set_rect".

y: Vertical screen position for "set_rect".

width: Window width for "set_rect".

height: Window height for "set_rect".

Notes: Use this tool for browser-window geometry and state. Use manage_tabs for switching between browser tabs.

ParametersJSON Schema
NameRequiredDescriptionDefault
xNo
yNo
widthNo
actionNoget_rect
heightNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral burden. It discloses the four actions and the requirement for set_rect, but it does not describe side effects, coordinate units, default action behavior, or return semantics beyond what the schema already shows.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with an Args/Notes split, bullet-style action definitions, and no filler. The most important usage guidance is front-loaded, and each line earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and a 0% schema description coverage, the description covers the action matrix, parameter meanings, and the key constraint of set_rect. Minor gaps remain, such as coordinate interpretation and default action, but an output schema exists so return-value details are not necessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description compensates by explaining each parameter and enumerating the action enum. It adds the important rule that set_rect needs x, y, width, and height, though it slightly repeats information already inferable from the parameter names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line, 'Get or change browser window geometry or state,' uses a specific verb and resource and clearly scopes the tool. The action list further enumerates the exact operations, making it easy to distinguish from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The Notes section explicitly directs the agent to use this tool for window geometry and state, and points to manage_tabs for switching tabs, which provides a clear alternative. It also states that set_rect requires all four coordinates, giving an explicit usage constraint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_urlOpen URLA

Navigate the current browser tab to the URL provided.

Use this when the browser needs to visit a new URL rather than move through its existing back/forward history.

If the URL does not include a protocol such as "https://", SeleniumBase automatically prefixes "https://" before navigation. For example, "seleniumbase.io" becomes "https://seleniumbase.io".

Navigation waits for the browser's navigation operation to complete before returning. Dynamic content may still be loading; use wait_for_condition when synchronization is required. If there's an error, that gets propagated through @handle_sb_errors.

Args: url: The destination URL. May be a complete URL such as "https://example.com", or a hostname such as "example.com".

Returns: A confirmation message containing the requested URL if successful.

Tool selection: - Navigate to a new URL -> use open_url. - Return to the previous page -> use manage_history(action="back"). - Go forward in history -> use manage_history(action="forward"). - Refresh the current page -> use manage_history(action="reload").

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses several important behaviors beyond the annotations: automatic https:// prefixing, waiting for navigation to complete, the possibility that dynamic content may still load, and error propagation through @handle_sb_errors. These details materially help an agent predict what will happen during invocation and what to do about incomplete loading.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the primary behavior, then provides examples, return details, and routing guidance in compact sections. Even the longer protocol-defaulting sentence earns its place because it changes how the parameter should be supplied. There is minimal redundancy given the amount of useful context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a single parameter and an output schema already present, the description covers everything an agent needs: parameter format, protocol normalization, navigation completion semantics, synchronization guidance, error behavior, return value, and explicit routing to sibling tools. No important invocation question is left unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides zero description for the url parameter, so the description carries the full burden. It fully compensates by defining the parameter in the Args section, explaining that it accepts either a complete URL or a bare hostname, and noting the automatic protocol prefixing behavior with a concrete example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific, actionable statement: 'Navigate the current browser tab to the URL provided.' It clearly distinguishes open_url from manage_history by explicitly matching 'navigate to a new URL' to this tool and all history-based navigation to manage_history. The verb, resource, and behavioral scope are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Tool selection' section explicitly states when to use open_url versus manage_history for back, forward, and reload actions. It also advises using wait_for_condition when synchronization with dynamic content is required, giving clear context about limitations and alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_javascriptRun JavaScriptA

Evaluate a JavaScript expression in the current page context.

Use this only when the required browser operation cannot be accomplished through the higher-level SeleniumBase tools.

The expression is evaluated through Chrome DevTools Protocol Runtime.evaluate in the currently active page. It executes with access to the page's JavaScript context, including DOM APIs, browser storage, and other same-origin page resources available to JavaScript.

Tool selection: - Prefer click_element, type_text, select_option, hover_action, focus_element, scroll_page, and other higher-level tools for normal browser interactions. - Prefer get_content, get_attributes, and find_elements for reading page content or element information. - Prefer manage_storage for ordinary localStorage/sessionStorage reads and writes. - Prefer manage_cookies for browser cookie operations. - Use this tool when a required operation needs arbitrary JavaScript that the higher-level tools do not expose.

Args: expression: A JavaScript expression or executable JavaScript code evaluated in the current page. It may reference standard browser globals such as document and window and may use DOM APIs.

    Examples:
        - "document.title"
        - "document.querySelector('button')?.textContent"
        - "localStorage.getItem('theme')"
        - "document.body.classList.contains('dark')"
        - "document.querySelector('#slider').value = '50'"

    The expression should produce a value when a result is needed.
    JavaScript that returns a Promise is supported and its resolved
    value is returned.

Returns: The JavaScript evaluation result when it can be serialized and returned across the MCP boundary. Primitive values, arrays, plain objects, and null are generally suitable return values. DOM objects, functions, symbols, and other non-serializable JavaScript values may not be returned directly; extract the needed property or convert the value to a serializable form first.

Security: This provides unrestricted JavaScript execution in the current browser page. It can read or modify page data and interact with the page in ways that bypass the higher-level tool abstractions. Only expose this MCP server to trusted clients.

ParametersJSON Schema
NameRequiredDescriptionDefault
expressionYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and meets it: it states evaluation via CDP Runtime.evaluate in the active page, access to DOM/storage, Promise resolution, serializable return values, and unrestricted page modification. The Security section also warns that execution bypasses higher-level abstractions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well organized with clear headers, bullets, and examples, and the purpose is front-loaded. It is slightly long, and the 'Use this only...' sentence is repeated in stronger form in the Tool selection section, but the extra detail is mostly earned.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a powerful one-parameter tool with no annotations and no output schema, this description covers when to use it, how execution works, parameter semantics, return serializability, and security considerations. Nothing the agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate entirely. It explains what the expression may contain, provides five concrete examples, and clarifies Promise handling and the need to produce a value. This fully documents the only parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Evaluate a JavaScript expression in the current page context.' It clearly frames the tool as an escape hatch for browser operations that higher-level tools do not expose, which distinguishes it from siblings like click_element, type_text, and get_content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit when-to-use rule ('Use this only when...') and a full Tool selection section recommending click_element, get_content, manage_storage, and manage_cookies first. This leaves no ambiguity about when the agent should pick run_javascript versus a sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_pageSave PageA

Save the current browser page to a local filesystem file.

Use this tool when the browser workflow needs a persistent file artifact from the current page: a PNG screenshot, the current page source as HTML, or a PDF representation of the current page.

A browser session must already be running. This tool operates on the currently active browser tab and does not navigate, click, type, or otherwise modify the webpage.

Args: format: - "screenshot": Save a PNG screenshot of the current page. - "html": Save the current page source as an HTML file. - "pdf": Save the current page as a PDF.

filename:
    Optional output filename. If omitted, defaults to:
    - "screenshot.png" for format="screenshot"
    - "page_source.html" for format="html"
    - "page.pdf" for format="pdf"

folder:
    Optional destination folder passed to SeleniumBase.
    If omitted, SeleniumBase uses its default output location.

Side effects and filesystem behavior: This tool writes a file to the filesystem and may overwrite an existing file with the same output name. Only use trusted and authorized filesystem paths. The MCP process must have permission to write to the requested destination.

The tool does not upload, publish, or transmit the saved file by
itself. The resulting file remains in the filesystem available to
the MCP server process.

Error behavior: If the browser session is not running, the tool returns a lifecycle error. Filesystem, browser, or SeleniumBase failures are converted into descriptive MCP error results by the server's error handler.

When not to use: - Do not use this tool merely to read page text or HTML; use get_content instead. - Do not use this tool when you only need page metadata such as the URL or title; use get_page_info instead. - Do not use this tool to manipulate the page; use the appropriate interaction tool such as click_element, type_text, or select_option.

Returns: A confirmation message containing the requested output format and filename after the save operation succeeds.

ParametersJSON Schema
NameRequiredDescriptionDefault
folderNo
formatNoscreenshot
filenameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are sparse (only readOnlyHint=false, openWorldHint=false, idempotentHint=false), so the description carries the full burden. It discloses that the tool writes files, may overwrite, requires filesystem permissions, does not modify the page, does not upload/publish, and details error behavior. It also specifies prerequisites like an active browser session.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with clear sections, bullet lists, and front-loaded purpose. Every sentence adds value—prerequisites, side effects, error handling, and alternatives—without redundancy. It is appropriately sized for the complexity of the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

It covers prerequisites (browser session running), operational scope (does not navigate or modify), side effects (file write/overwrite), error handling, and return value. It also distinguishes from sibling tools. Given the output schema exists, the description needn't detail return structure, but it does anyway.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description is the only source of parameter meaning. It explains each parameter (format with enum values and defaults, filename with format-dependent defaults, folder with default behavior) clearly and completely.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Save the current browser page to a local filesystem file' and enumerates the exact formats (screenshot, html, pdf). It also explicitly contrasts with siblings like get_content and get_page_info, making selection unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states exactly when to use this tool ('when the browser workflow needs a persistent file artifact') and provides a dedicated 'When not to use' section naming three alternative tools with the conditions that route to them. This is explicit and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scroll_pageScroll PageA

Scroll the current page vertically.

Args: direction: - "up": Scroll upward by amount percent of the window height. - "down": Scroll downward by amount percent of the window height. - "top": Scroll directly to the top; amount is ignored. - "bottom": Scroll directly to the bottom; amount is ignored.

amount: Percentage of the current viewport height used for relative
    up/down scrolling. For example, amount=25 scrolls approximately
    one quarter of the viewport height.

Notes: Values greater than 100 for amount are allowed. For example, 200 means approximately two viewport heights.

Tool selection: - Need to reveal a specific element -> use 'focus_element' with action="scroll_to_element". - Need to scroll the page by a relative amount -> use 'scroll_page'.

ParametersJSON Schema
NameRequiredDescriptionDefault
amountNo
directionNodown

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral detail beyond the annotations: amount is a percentage of viewport height, values greater than 100 are allowed, and amount is ignored for 'top' and 'bottom' directions. The annotations are not contradicted, and the added semantics give the agent accurate expectations for how scrolling behaves.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections for arguments, notes, and tool selection. Every sentence adds value, and the most important usage guidance is front-loaded near the bottom but easy to find. There is no filler or repetition of schema defaults.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with an output schema present, the description covers the behavioral semantics, special cases, allowed values, and selection guidance. An agent has everything it needs to invoke the tool correctly and know what to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description fully compensates by documenting each direction value and the exact meaning of amount with examples like amount=25 and amount=200. Even the nuance that top/bottom ignore amount is described, which the schema alone would not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Scroll the current page vertically.' It also names the sibling alternative (focus_element) for the element-revealing case, so an agent can tell which tool fits which task without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Tool selection' section explicitly states when to use scroll_page versus focus_element, including the precise action 'scroll_to_element' for focusing a specific element. It also clarifies that scroll_page is for relative page scrolling. This is clear, actionable guidance with an explicit alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

select_optionSelect OptionA

Select an option from an HTML dropdown.

Args: dropdown_selector: CSS selector identifying the element.

value: The option's visible text, its HTML value attribute, or its
    0-based index, depending on by.

by:
    - "text": Match the option's visible text.
    - "value": Match the option's HTML value attribute.
    - "index": Match the option's 0-based position. Both integer and
      numeric-string values are accepted.

Raises: An error when the dropdown or requested option cannot be found.

This tool is for native elements. For custom JavaScript dropdowns made from div/button/list elements, use click_element or other element-interaction tools instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
byNotext
valueYes
dropdown_selectorYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=false, but the description adds valuable context: it mentions that an error is raised when the dropdown or option cannot be found, and it explains the flexibility of the 'value' parameter. While it doesn't detail side effects like triggering change events, it provides enough behavioral transparency beyond the annotations. No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and concise. It starts with a clear purpose, then lists parameters in a readable format, followed by error behavior and a usage note. Every sentence serves a purpose, no fluff, and the information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema (though not shown, context signals indicate it exists), and the description covers all essential aspects: what the tool does, how to use each parameter, error behavior, and when to use alternatives. Nothing critical is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, so the description carries the full burden of parameter explanation. It thoroughly defines 'dropdown_selector', 'value' (including accepted types), and 'by' (with all three modes: text, value, index). This substantially adds meaning beyond the bare schema, fully compensating for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Select an option from an HTML <select> dropdown.' It specifies the resource (native <select> elements) and explicitly distinguishes it from custom JavaScript dropdowns, naming the alternative (click_element). This makes the tool's purpose unambiguous and differentiates it from sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: 'This tool is for native <select> elements. For custom JavaScript dropdowns made from div/button/list elements, use click_element or other element-interaction tools instead.' This directly tells the agent when to use this tool and when not, referencing a specific alternative, which is exemplary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

solve_captchaSolve CAPTCHAA

Attempt a SeleniumBase CDP-based CAPTCHA interaction, such as clicking a CAPTCHA checkbox, or performing a drag/drop action on a slider CAPTCHA.

This tool attempts to interact with CAPTCHA controls such as Cloudflare Turnstile, reCAPTCHA, hCaptcha, DataDome Slider, or FriendlyCaptcha via the Chrome DevTools Protocol (CDP), which is usually stealthier than JavaScript because CDP actions can avoid triggering isTrusted: false.

This tool automatically detects the coordinates of CAPTCHA checkboxes for determining the correct location to perform the click. If no CAPTCHA is detected on the current page, then no click action is attempted.

The tool does not guarantee that the CAPTCHA was solved. Some CAPTCHA controls are embedded inside shadow DOM or otherwise do not expose an easy success signal. A successful attempt may result in changes to page state or browser cookies.

Tool workflow: 1. Inspect the webpage with get_content when you need to determine whether CAPTCHA-related controls are present. 2. Call 'solve_captcha' to attempt the CAPTCHA interaction. 3. Use 'get_page_info', 'get_content', 'check_if_condition', or 'manage_cookies' to inspect resulting page/session state.

Returns: A message confirming that the CAPTCHA interaction was attempted. The message is the same for both successful and failed attempts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond annotations by disclosing that success is not guaranteed, that the return message is identical for success and failure, that no click is attempted if no CAPTCHA is detected, and that page state or cookies may change. It also explains CDP stealth and shadow-DOM limitations. This is consistent with readOnlyHint=false and destructiveHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with a numbered workflow, provider list, limitation paragraph, and return note. However, the opening two sentences are somewhat redundant: both say the tool 'attempts' a CAPTCHA interaction. Slight trimming would make it tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool, the description supplies all essential context: target controls, mechanism, no-op behavior, success ambiguity, side effects, and post-inspection workflow. The return message caveat covers what the output schema would otherwise need to explain. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so schema coverage is effectively 100% and the baseline is 4. The description adds that CAPTCHA coordinates are auto-detected and no user input is required. There is no parameter documentation gap to compensate for.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and scope: 'Attempt a SeleniumBase CDP-based CAPTCHA interaction' and names concrete interaction types and providers. It also explains automatic coordinate detection, making the tool's role distinct from generic click_element or run_javascript. The purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear workflow: inspect with get_content first, call solve_captcha, then verify with get_page_info, get_content, check_if_condition, or manage_cookies. It does not explicitly state when not to use the tool or name a non-CAPTCHA alternative, so it stops short of full when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_browserStart BrowserA
Idempotent

Launch a persistent SeleniumBase Pure CDP Mode browser session.

Call this before using browser interaction tools such as open_url, get_content, click_element, type_text, or find_elements. The same browser session remains active across subsequent MCP tool calls until close_browser is called or the server process exits.

Pure CDP Mode controls the browser through the Chrome DevTools Protocol (CDP), not WebDriver.

Args: url: Optional URL to navigate to during browser startup. When provided, the tool waits for the browser launch/navigation operation to complete before returning. If omitted, the browser starts without navigating to a specified URL.

headless: Controls whether the browser runs without a visible window.
    True forces headless mode; False forces headed mode. If None, this
    tool defaults to headless on Linux and headed on Windows/macOS.

use_chromium: Use Chromium instead of Google Chrome. This is useful
    when Google Chrome is not installed. SeleniumBase can manage the
    Chromium browser when this option is enabled.

browser_executable_path: Optional path to the browser executable.
    Use this when the desired browser is installed at a non-standard
    location. Mutually exclusive with use_chromium.

incognito: Launch Chrome/Chromium in incognito mode.

guest: Launch Chrome/Chromium in guest mode.
    Do not combine this with incognito=True.

ad_block: Enable SeleniumBase's basic ad-blocking functionality.

proxy: Optional proxy server.
    Examples include "SERVER:PORT" or "USER:PASS@SERVER:PORT".

Returns: A confirmation message when the browser starts successfully, or a descriptive error if the browser startup fails.

Startup behavior: If the initial launch fails, the tool automatically retries once.

Lifecycle: Call start_browser once at the beginning of a browser automation workflow. Reusing the existing session preserves cookies, tabs, navigation history, localStorage/sessionStorage, and other browser state between tool calls. Call close_browser when finished. If a browser session is already running, this tool does not launch another browser and instead returns a message indicating that the existing session is active.

Environment requirements: The MCP runtime must have a compatible Chrome or Chromium browser available. If the browser executable cannot be discovered, use use_chromium=True or provide browser_executable_path explicitly.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNo
guestNo
proxyNo
ad_blockNo
headlessNo
incognitoNo
use_chromiumNo
browser_executable_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses persistence across calls, CDP mode, automatic one retry on startup failure, reuse of cookies/tabs/history/localStorage/sessionStorage, and the fact that no second browser is launched if a session already exists. It also documents environment requirements. Nothing contradicts the annotations; idempotentHint is consistent with the already-running behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but organized into labeled sections (Args, Returns, Startup behavior, Lifecycle, Environment requirements), with purpose and usage front-loaded before parameter details. Given 8 parameters and the need to explain lifecycle and session reuse, the length is warranted and every block adds information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The definition covers return values, startup retry behavior, lifecycle/session reuse, environment prerequisites, and all parameters, while the output schema handles the exact confirmation/error shape. For a complex setup tool with 8 optional parameters, this is complete and self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the Args block carries the full burden and succeeds: all 8 parameters are explained semantically, with defaults, examples, and a mutual-exclusion warning. It adds platform-specific headless defaults, use_chromium guidance for when Chrome is not installed, and proxy format examples. This fully compensates for the empty schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific action (launch) and a specific resource (persistent SeleniumBase Pure CDP Mode browser session), and the lifecycle note distinguishes it from sibling interaction tools by stating it must be called before them. The CDP-versus-WebDriver note removes ambiguity about what kind of browser session is created. This is clearly differentiated from the other browser tools in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to call this before browser interaction tools such as open_url, get_content, click_element, type_text, and find_elements, and to call close_browser when finished. It also tells the agent what happens if a session is already running, covering the when-not-to-repeat case. No alternative startup tool exists among the siblings, so no further exclusion is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

type_textType TextA

Enter, append, directly set, or clear a value on a page element.

Use this tool to modify text/value fields such as inputs, textareas, contenteditable elements, and supported input sliders. It changes the target element's value or content; it does not submit a form or click other elements.

Choose the mode based on the desired interaction:

  • "fill_input": Normal user-like entry; clears the existing value first.

  • "append": Preserves the existing value and adds text via keystrokes.

  • "fast_type": Clears the existing value and types without typing pauses.

  • "set_value": Sets the value directly without simulating key events; prefer this for fast programmatic value changes when keyboard events are not required.

  • "clear_only": Clears the existing value; text is ignored.

The tool waits up to timeout seconds for the target element. If the target cannot be used successfully, the underlying SeleniumBase error is handled by handle_sb_errors rather than returning a success message.

Args: selector: CSS or SeleniumBase selector identifying the target element.

text: Text/value to enter or set. Ignored for "clear_only".

mode: Interaction mode. See the mode descriptions above.

timeout: Maximum seconds to wait for the target element.
    Must be appropriate for the page's expected load/interaction time.

Returns: A confirmation message after the operation succeeds; otherwise the error handler returns the resulting failure.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNofill_input
textNo
timeoutNo
selectorYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly=false and destructiveHint=false, but the description adds meaningful behavior beyond that: it waits up to timeout seconds, it clears existing values in some modes, it preserves in another, and it routes failures through handle_sb_errors. These details inform the agent about timing, side effects, and error flow, which annotations do not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average but earned: five mutually exclusive modes require enumeration and disambiguation. It front-loads the core purpose, then logically progresses through behavior, mode selection, and arguments. Each bullet and sentence delivers distinct information with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with four parameters, five modes, an output schema, and zero schema-level descriptions, the description covers all essential dimensions: what it does, which element types it supports, what it avoids doing, mode selection, error handling, and parameter semantics. It also states the return contract ('confirmation message... otherwise the error handler returns the resulting failure'), so an agent can interpret the response correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full explanatory burden. It explains selector ('CSS or SeleniumBase selector'), text ('Ignored for

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with specific verbs ('Enter, append, directly set, or clear') tied to a clear resource ('value on a page element'), and goes on to enumerate target element types ('inputs, textareas, contenteditable elements'). It explicitly states what the tool does not do ('does not submit a form or click other elements'), which differentiates it from siblings like click_element or select_option without opening their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use the tool ('modify text/value fields'), and breaks down mode selection with expected interaction semantics. It also gives an exclusion ('does not submit or click'), strongly implying click_element is for clicking. It stops short of naming alternative sibling tools explicitly, but the context and exclusions are clear enough for an agent to decide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wait_for_conditionWait For ConditionA
Read-onlyIdempotent

Wait for a page condition or for a specified duration.

Use this for synchronization when a dynamic page may need time to reach a condition before the next automation step. The tool blocks until the condition is met or the timeout expires. It does not intentionally scroll, click, or otherwise modify the page while waiting.

Use check_if_condition to inspect the current state without waiting. Use assert_condition to verify an expected condition rather than synchronize with a changing page.

When the condition is not reached before timeout, the underlying SeleniumBase wait failure is handled by the tool's error handler rather than returning a success confirmation.

If state="seconds_passed", selector and text are ignored and the tool blocks for the full timeout seconds.

If text is supplied, present/visible wait for the text to appear, while absent/not_visible wait for the text to disappear. If no selector is supplied, text is searched within the page body.

Args: state: - "present": Wait until the matching element exists. - "visible": Wait until the matching element is visible. - "not_visible": Wait until the matching element is not visible. - "absent": Wait until the matching element no longer exists. - "seconds_passed": Wait for the full timeout duration.

selector: CSS or SeleniumBase selector for the element.
    Required unless `text` is supplied or `state="seconds_passed"`.

text: Optional text to wait for or wait to disappear.
    With text, `present` and `visible` are equivalent,
    as are `absent` and `not_visible`.

timeout: Maximum seconds to wait for the condition;
    for `seconds_passed`, the exact duration to wait. Must be >= 0.

Returns: A success message when the requested condition is reached. If the condition times out or the underlying wait fails, the tool returns the error produced by its error handler.

Tool selection: - Inspect current state immediately -> check_if_condition. - Wait for a state change -> wait_for_condition. - Verify an expectation -> assert_condition.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNo
stateNovisible
timeoutNo
selectorNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior, and the description adds meaningful detail: the tool blocks, does not scroll/click/modify, handles timeouts through an error handler, and treats seconds_passed as a pure delay. This goes well beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-organized into purpose, behavioral notes, parameter semantics, returns, and tool selection. It is front-loaded with the core purpose, and every section contributes needed information for correct invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 4 parameters, 5 enum states, no schema descriptions, and an output schema, the description covers all required cases: state meanings, argument dependencies, timeout behavior, error handling, and return values. Nothing needed for correct use is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full responsibility for parameters. It thoroughly explains each state value, the selector requirement rule, text-search behavior, timeout semantics including the >= 0 constraint, and the equivalence of present/visible and absent/not_visible when text is supplied.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Wait for a page condition or for a specified duration.' It then explicitly differentiates itself from check_if_condition and assert_condition, so an agent can select it correctly without inspecting siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is an explicit 'Tool selection' section mapping immediate inspection to check_if_condition, synchronization to wait_for_condition, and verification to assert_condition. It also clarifies when selector/text are required or ignored, leaving no ambiguity about when to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev4.54.5
    • Changedmanage_tabs2 fields changed
      • changedInput schema / properties / action / default
        Previous value: -"list"New value: +"list_tabs"
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "open",
        -  "switch",
        -  "switch_newest",
        -  "close_active"
        -]New value: +[
        +  "list_tabs",
        +  "open_new_tab",
        +  "switch_to_tab",
        +  "switch_to_newest_tab",
        +  "close_active_tab"
        +]
  2. 7 tool updatesv4.54.4
    • Removedcheck_condition
    • Addedcheck_if_condition
    • Removedgoto_url
    • Changedhover_action6 fields changed
      • addedInput schema / properties / secondary_selector
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Secondary Selector"
        +}
      • addedInput schema / properties / selector
        Added value: +{
        +  "title": "Selector",
        +  "type": "string"
        +}
      • removedInput schema / properties / selector1
        Removed value: -{
        -  "title": "Selector1",
        -  "type": "string"
        -}
      • removedInput schema / properties / selector2
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Selector2"
        -}
      • addedInput schema / properties / timeout
        Added value: +{
        +  "default": 5,
        +  "title": "Timeout",
        +  "type": "number"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "selector1"
        -]New value: +[
        +  "selector"
        +]
    • Addedopen_url
    • Removedwait_for
    • Addedwait_for_condition
  3. 11 tool updatesv4.54.3
    • Removedclick
    • Addedclick_element
    • Removedfocus
    • Addedfocus_element
    • Addedgoto_url
    • Changedhover_action2 fields changed
      • changedInput schema / properties / action / default
        Previous value: -"none"New value: +"hover"
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "none",
        -  "click",
        -  "drag_and_drop"
        -]New value: +[
        +  "hover",
        +  "hover_and_click",
        +  "drag_and_drop"
        +]
    • Removednavigate
    • Removedsave_output
    • Addedsave_page
    • Removedscroll
    • Addedscroll_page
  4. 3 tool updatesv4.54.2
    • Changedfocus1 field changed
      • addedInput schema / properties / timeout
        Added value: +{
        +  "default": 5,
        +  "title": "Timeout",
        +  "type": "number"
        +}
    • Changedget_attributes2 fields changed
      • addedInput schema / properties / timeout
        Added value: +{
        +  "default": 5,
        +  "title": "Timeout",
        +  "type": "number"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "result": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "additionalProperties": true,
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "title": "Result"
        +    }
        +  },
        +  "required": [
        +    "result"
        +  ],
        +  "title": "get_attributesOutput",
        +  "type": "object"
        +}
    • Changedget_content5 fields changed
      • removedInput schema / properties / include_shadow_dom
        Removed value: -{
        -  "default": true,
        -  "title": "Include Shadow Dom",
        -  "type": "boolean"
        -}
      • removedInput schema / properties / selector / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • changedInput schema / properties / selector / default
        Previous value: -nullNew value: +"body"
      • addedInput schema / properties / selector / type
        Added value: +"string"
      • addedInput schema / properties / timeout
        Added value: +{
        +  "default": 5,
        +  "title": "Timeout",
        +  "type": "number"
        +}
  5. 1 tool updatev4.54.1
    • Changedstart_browser2 fields changed
      • removedInput schema / properties / headless / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / headless / enum
        Added value: +[
        +  false,
        +  true,
        +  null
        +]
  6. 8 tool updatesv4.54.0
    • Changedassert_condition1 field changed
      • changedInput schema / properties / timeout / default
        Previous value: -7New value: +5
    • Changedclick1 field changed
      • changedInput schema / properties / timeout / default
        Previous value: -7New value: +5
    • Changedget_page_info1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "title": "get_page_infoDictOutput",
        +  "type": "object"
        +}
    • Changedmanage_tabs1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "result": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "items": {
        +            "additionalProperties": true,
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      ],
        +      "title": "Result"
        +    }
        +  },
        +  "required": [
        +    "result"
        +  ],
        +  "title": "manage_tabsOutput",
        +  "type": "object"
        +}
    • Changedmanage_window1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "result": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "additionalProperties": true,
        +          "type": "object"
        +        }
        +      ],
        +      "title": "Result"
        +    }
        +  },
        +  "required": [
        +    "result"
        +  ],
        +  "title": "manage_windowOutput",
        +  "type": "object"
        +}
    • Changedtype_text1 field changed
      • changedInput schema / properties / timeout / default
        Previous value: -7New value: +5
    • Changedwait_for2 fields changed
      • changedInput schema / properties / state / enum
        Previous value: -[
        -  "present",
        -  "visible",
        -  "not_visible",
        -  "absent"
        -]New value: +[
        +  "present",
        +  "visible",
        +  "not_visible",
        +  "absent",
        +  "seconds_passed"
        +]
      • changedInput schema / properties / timeout / default
        Previous value: -7New value: +5
    • Removedwait_seconds
  7. 6 tool updatesv4.53.8
    • Changedcheck_condition1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "result": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "type": "string"
        +        }
        +      ],
        +      "title": "Result"
        +    }
        +  },
        +  "required": [
        +    "result"
        +  ],
        +  "title": "check_conditionOutput",
        +  "type": "object"
        +}
    • Addedfocus
    • Removedfocus_on
    • Changedget_page_info1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "properties": {
        -    "result": {
        -      "anyOf": [
        -        {
        -          "additionalProperties": true,
        -          "type": "object"
        -        },
        -        {
        -          "type": "string"
        -        }
        -      ],
        -      "title": "Result"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "get_page_infoOutput",
        -  "type": "object"
        -}New value: +null
    • Addedhover_action
    • Removedhover_with_action
  8. 10 tool updatesv4.53.7
    • Changedassert_condition2 fields changed
      • removedInput schema / properties / timeout / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / timeout / type
        Added value: +"number"
    • Addedcheck_condition
    • Removedcheck_for_condition
    • Changedclick2 fields changed
      • removedInput schema / properties / timeout / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / timeout / type
        Added value: +"number"
    • Changedfind_elements3 fields changed
      • removedInput schema / properties / timeout / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • changedInput schema / properties / timeout / default
        Previous value: -7New value: +0.5
      • addedInput schema / properties / timeout / type
        Added value: +"number"
    • Addedmanage_history
    • Removednavigate_history
    • Changedtype_text2 fields changed
      • removedInput schema / properties / timeout / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / timeout / type
        Added value: +"number"
    • Changedwait_for2 fields changed
      • removedInput schema / properties / timeout / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / timeout / type
        Added value: +"number"
    • Changedwait_seconds2 fields changed
      • removedInput schema / properties / seconds / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "number"
        -  }
        -]
      • addedInput schema / properties / seconds / type
        Added value: +"number"
  9. 2 tool updatesv4.53.6
    • Addedcheck_for_condition
    • Removedcheck_state
  10. 4 tool updatesv4.53.5
    • Addedassert_condition
    • Removedassert_that
    • Removedfill_input
    • Addedtype_text
  11. 5 tool updatesv4.53.4
    • Removedact_on_element
    • Removeddrag_and_drop
    • Addedfocus_on
    • Removedhover
    • Addedhover_with_action
  12. 8 tool updatesv4.53.3
    • Addedact_on_element
    • Removedbrowser_status
    • Removedelement_action
    • Removedget_all_urls
    • Addedget_content
    • Removedget_page_content
    • Removedget_user_agent
    • Changedstart_browser3 fields changed
      • addedInput schema / properties / headless / anyOf
        Added value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / headless / default
        Previous value: -falseNew value: +null
      • removedInput schema / properties / headless / type
        Removed value: -"boolean"
  13. 7 tool updatesv4.53.2
    • Changedassert_that1 field changed
      • changedInput schema / properties / timeout / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedclick1 field changed
      • changedInput schema / properties / timeout / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedfill_input1 field changed
      • changedInput schema / properties / timeout / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedfind_elements1 field changed
      • changedInput schema / properties / timeout / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedget_all_urls1 field changed
      • removedInput schema / properties / absolute
        Removed value: -{
        -  "default": true,
        -  "title": "Absolute",
        -  "type": "boolean"
        -}
    • Changedwait_for1 field changed
      • changedInput schema / properties / timeout / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedwait_seconds2 fields changed
      • addedInput schema / properties / seconds / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "number"
        +  }
        +]
      • removedInput schema / properties / seconds / type
        Removed value: -"number"
  14. 96 tool updatesv1.0.1
    • Removedassert_element
    • Removedassert_element_visible
    • Removedassert_exact_text
    • Removedassert_text
    • Addedassert_that
    • Removedassert_title
    • Removedassert_url
    • Removedassert_url_contains
    • Addedbrowser_status
    • Addedcheck_state
    • Removedclear_cookies
    • Removedclear_input
    • Changedclick5 fields changed
      • addedInput schema / properties / all_matches
        Added value: +{
        +  "default": false,
        +  "title": "All Matches",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / nth
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Nth"
        +}
      • addedInput schema / properties / only_if_visible
        Added value: +{
        +  "default": false,
        +  "title": "Only If Visible",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / parent_selector
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Parent Selector"
        +}
      • changedInput schema / properties / timeout / default
        Previous value: -nullNew value: +7
    • Removedclick_if_visible
    • Removedclick_link
    • Removedclick_nth_element
    • Removedclick_visible_elements
    • Removedclose_active_tab
    • Addeddrag_and_drop
    • Addedelement_action
    • Removedevaluate
    • Addedfill_input
    • Removedfind_all_info
    • Removedfind_element_info
    • Addedfind_elements
    • Removedfind_elements_count
    • Removedfocus
    • Removedget_all_cookies
    • Addedget_attributes
    • Removedget_current_url
    • Removedget_element_attribute
    • Removedget_element_attributes
    • Removedget_element_html
    • Removedget_html_source
    • Removedget_local_storage_item
    • Removedget_navigation_history
    • Removedget_origin
    • Addedget_page_content
    • Addedget_page_info
    • Removedget_session_storage_item
    • Removedget_tabs_count
    • Removedget_text
    • Removedget_title
    • Removedget_window_rect
    • Removedgo_back
    • Removedgo_forward
    • Removedhighlight
    • Addedhover
    • Removedis_element_present
    • Removedis_element_visible
    • Removedis_text_visible
    • Removedload_cookies
    • Addedmanage_cookies
    • Addedmanage_storage
    • Addedmanage_tabs
    • Addedmanage_window
    • Removedmaximize
    • Removedminimize
    • Addednavigate_history
    • Removednested_click
    • Removedopen_new_tab
    • Removedreload_page
    • Addedrun_javascript
    • Removedsave_as_pdf
    • Removedsave_cookies
    • Addedsave_output
    • Removedsave_page_source
    • Removedsave_screenshot
    • Addedscroll
    • Removedscroll_down
    • Removedscroll_into_view
    • Removedscroll_to_bottom
    • Removedscroll_to_top
    • Removedscroll_up
    • Addedselect_option
    • Removedselect_option_by_index
    • Removedselect_option_by_text
    • Removedselect_option_by_value
    • Removedsend_keys
    • Removedset_local_storage_item
    • Removedset_session_storage_item
    • Removedset_value
    • Removedset_window_rect
    • Removedsleep
    • Changedstart_browser2 fields changed
      • addedInput schema / properties / browser_executable_path
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Browser Executable Path"
        +}
      • addedInput schema / properties / use_chromium
        Added value: +{
        +  "default": false,
        +  "title": "Use Chromium",
        +  "type": "boolean"
        +}
    • Removedsubmit
    • Removedswitch_to_newest_tab
    • Removedswitch_to_tab
    • Removedtype_text
    • Addedwait_for
    • Removedwait_for_element_absent
    • Removedwait_for_element_not_visible
    • Removedwait_for_element_present
    • Removedwait_for_element_visible
    • Removedwait_for_text
    • Addedwait_seconds
  15. 79 tool updatesv1.0.0
    • First observedassert_element
    • First observedassert_element_visible
    • First observedassert_exact_text
    • First observedassert_text
    • First observedassert_title
    • First observedassert_url
    • First observedassert_url_contains
    • First observedclear_cookies
    • First observedclear_input
    • First observedclick
    • First observedclick_if_visible
    • First observedclick_link
    • First observedclick_nth_element
    • First observedclick_visible_elements
    • First observedclose_active_tab
    • First observedclose_browser
    • First observedevaluate
    • First observedfind_all_info
    • First observedfind_element_info
    • First observedfind_elements_count
    • First observedfocus
    • First observedget_all_cookies
    • First observedget_all_urls
    • First observedget_current_url
    • First observedget_element_attribute
    • First observedget_element_attributes
    • First observedget_element_html
    • First observedget_html_source
    • First observedget_local_storage_item
    • First observedget_navigation_history
    • First observedget_origin
    • First observedget_session_storage_item
    • First observedget_tabs_count
    • First observedget_text
    • First observedget_title
    • First observedget_user_agent
    • First observedget_window_rect
    • First observedgo_back
    • First observedgo_forward
    • First observedhighlight
    • First observedis_element_present
    • First observedis_element_visible
    • First observedis_text_visible
    • First observedload_cookies
    • First observedmaximize
    • First observedminimize
    • First observednavigate
    • First observednested_click
    • First observedopen_new_tab
    • First observedreload_page
    • First observedsave_as_pdf
    • First observedsave_cookies
    • First observedsave_page_source
    • First observedsave_screenshot
    • First observedscroll_down
    • First observedscroll_into_view
    • First observedscroll_to_bottom
    • First observedscroll_to_top
    • First observedscroll_up
    • First observedselect_option_by_index
    • First observedselect_option_by_text
    • First observedselect_option_by_value
    • First observedsend_keys
    • First observedset_local_storage_item
    • First observedset_session_storage_item
    • First observedset_value
    • First observedset_window_rect
    • First observedsleep
    • First observedsolve_captcha
    • First observedstart_browser
    • First observedsubmit
    • First observedswitch_to_newest_tab
    • First observedswitch_to_tab
    • First observedtype_text
    • First observedwait_for_element_absent
    • First observedwait_for_element_not_visible
    • First observedwait_for_element_present
    • First observedwait_for_element_visible
    • First observedwait_for_text

TDQS

A4.7/5.0

Scored across 24 tools

Disambiguation5/5

Every tool targets a distinct browser operation or resource, and even the three state-checking tools (check_if_condition, wait_for_condition, assert_condition) are explicitly differentiated with tool-selection guidance. Read tools like get_content, find_elements, get_attributes, and get_page_info are clearly scoped to content, elements, attributes, and metadata respectively.

Naming Consistency5/5

All tool names follow a consistent lower_snake_case verb_noun pattern. Grouped verbs like get_*, manage_*, and action-specific verbs like click_element, type_text, and scroll_page make the surface predictable and easy to navigate.

Tool Count4/5

At 24 tools, the surface is on the high side, but the broad browser-automation scope justifies the count—each tool corresponds to a distinct browser capability. It feels slightly heavy but not bloated, and the actions are sensibly consolidated where possible.

Completeness5/5

The set covers the full browser-automation lifecycle: session start/close, navigation and history, reading content, element interactions, synchronization, assertions, cookies/storage, tabs/windows, scrolling, page saving, captcha handling, and a JavaScript escape hatch. There are no obvious dead ends for typical automation workflows.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server for stealth browser automation that uses human-like interaction patterns to bypass bot detection via the Chrome DevTools Protocol. It enables users to navigate, interact with elements, and capture data from websites using undetectable behaviors like Bezier mouse movements and Gaussian typing delays.
    107 npm
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Stealth browser automation for AI agents, using source-patched Chromium to bypass bot detection systems like Cloudflare, reCAPTCHA, and FingerprintJS.
    28
    Apache 2.0