From 8261b7c605b08c8b431c1c4ad243a76df27d848f Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 19:30:32 -0400
Subject: [PATCH 01/11] Update CDP Mode
---
seleniumbase/core/browser_launcher.py | 9 +++
seleniumbase/core/sb_cdp.py | 32 +++++-----
seleniumbase/core/sb_driver.py | 18 ++++++
seleniumbase/fixtures/base_case.py | 61 ++++++++++++++++++-
seleniumbase/undetected/cdp_driver/browser.py | 2 +
seleniumbase/undetected/cdp_driver/tab.py | 7 +++
6 files changed, 112 insertions(+), 17 deletions(-)
diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py
index e4b6d58d56b..fb7bb4c9c0c 100644
--- a/seleniumbase/core/browser_launcher.py
+++ b/seleniumbase/core/browser_launcher.py
@@ -176,8 +176,11 @@ def extend_driver(
driver.forward = DM.forward
driver.refresh = DM.refresh
driver.locator = DM.locator
+ driver.select = DM.select
+ driver.select_all = DM.select_all
page = types.SimpleNamespace()
page.open = DM.open_url
+ page.goto = DM.open_url
page.click = DM.click
page.click_link = DM.click_link
page.click_if_visible = DM.click_if_visible
@@ -210,6 +213,8 @@ def extend_driver(
page.find_element = DM.find_element
page.find_elements = DM.find_elements
page.locator = DM.locator
+ page.select = DM.select
+ page.select_all = DM.select_all
page.get_current_url = DM.get_current_url
page.get_page_source = DM.get_page_source
page.get_title = DM.get_title
@@ -231,6 +236,7 @@ def extend_driver(
js.highlight = DM.highlight
driver.js = js
driver.open = DM.open_url
+ driver.goto = DM.open_url
driver.click = DM.click
driver.click_link = DM.click_link
driver.click_if_visible = DM.click_if_visible
@@ -291,6 +297,7 @@ def extend_driver(
driver.switch_to_default_window = DM.switch_to_default_window
driver.switch_to_newest_window = DM.switch_to_newest_window
driver.open_new_window = DM.open_new_window
+ driver.switch_to_newest_tab = DM.switch_to_newest_tab
driver.open_new_tab = DM.open_new_tab
driver.switch_to_window = DM.switch_to_window
driver.switch_to_tab = DM.switch_to_tab
@@ -759,6 +766,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
CDPM = sb_cdp.CDPMethods(loop, page, driver)
cdp.get = CDPM.get
cdp.open = CDPM.open
+ cdp.goto = CDPM.goto
cdp.reload = CDPM.reload
cdp.refresh = CDPM.refresh
cdp.add_handler = CDPM.add_handler
@@ -972,6 +980,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
driver.solve_captcha = CDPM.solve_captcha
driver.click_captcha = CDPM.click_captcha
driver.find_element_by_text = CDPM.find_element_by_text
+ driver.flash = CDPM.flash
driver._is_using_cdp = True
if (
getattr(sb_config, "_cdp_proxy", None)
diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py
index 3a03c1afc7f..a3d547426b4 100644
--- a/seleniumbase/core/sb_cdp.py
+++ b/seleniumbase/core/sb_cdp.py
@@ -155,6 +155,9 @@ def get(self, url, **kwargs):
def open(self, url, **kwargs):
self.get(url, **kwargs)
+ def goto(self, url, **kwargs):
+ self.get(url, **kwargs)
+
def reload(self, ignore_cache=True, script_to_evaluate_on_load=None):
self.loop.run_until_complete(
self.page.reload(
@@ -2033,6 +2036,13 @@ def click_with_offset(self, selector, x, y, center=False, scroll=True):
self.__slow_mode_pause_if_set()
self.loop.run_until_complete(self.page.wait(0.2))
+ def quit(self):
+ """Quit the browser in the Pure CDP Mode Sync format."""
+ driver = self.driver
+ if hasattr(driver, "cdp_base"):
+ driver = driver.cdp_base
+ driver.quit()
+
def _on_a_cf_turnstile_page(self, source=None):
if not source or len(source) < 400:
time.sleep(0.2)
@@ -2325,28 +2335,22 @@ def __click_captcha(self, use_cdp=False):
'form div:not([class]):has(input[name*="cf-turn"])'
):
selector = 'form div:not([class]):has(input[name*="cf-turn"])'
- elif self.is_element_present("form div:not(:has(*))"):
- selector = "form div:not(:has(*))"
elif self.is_element_present("body > div#check > div:not([class])"):
selector = "body > div#check > div:not([class])"
elif self.is_element_present(".cf-turnstile-wrapper"):
selector = ".cf-turnstile-wrapper"
- elif self.is_element_present(
- '[id*="turnstile"] div:not([class])'
- ):
+ elif self.is_element_present('[id*="turnstile"] div:not([class])'):
selector = '[id*="turnstile"] div:not([class])'
- elif self.is_element_present(
- '[class*="turnstile"] div:not([class])'
- ):
+ elif self.is_element_present('[class*="turnstile"] div:not([class])'):
selector = '[class*="turnstile"] div:not([class])'
- elif self.is_element_present(
- "iframe[data-hcaptcha-widget-id]"
- ):
+ elif self.is_element_present("iframe[data-hcaptcha-widget-id]"):
selector = "iframe[data-hcaptcha-widget-id]"
- elif self.is_element_present(
- '[data-callback="onCaptchaSuccess"]'
- ):
+ elif self.is_element_present('[data-callback="onCaptchaSuccess"]'):
selector = '[data-callback="onCaptchaSuccess"]'
+ elif self.is_element_present('[class*="captcha"] div:not([class])'):
+ selector = '[class*="captcha"] div:not([class])'
+ elif self.is_element_present("form div:not(:has(*))"):
+ selector = "form div:not(:has(*))"
elif self.is_element_present(
"div:not([class]):not([id]):not([aria-label]) > "
"div:not([class]):not([id]):not([aria-label])"
diff --git a/seleniumbase/core/sb_driver.py b/seleniumbase/core/sb_driver.py
index edf34713656..383b9b5aef2 100644
--- a/seleniumbase/core/sb_driver.py
+++ b/seleniumbase/core/sb_driver.py
@@ -41,6 +41,18 @@ def find_elements(self, by=None, value=None):
value, by = page_utils.swap_selector_and_by_if_reversed(value, by)
return self.driver.default_find_elements(by=by, value=value)
+ def select(self, *args, **kwargs):
+ if self.__is_cdp_swap_needed():
+ return self.driver.cdp.select(*args, **kwargs)
+ else:
+ return self.find_element(*args, **kwargs)
+
+ def select_all(self, *args, **kwargs):
+ if self.__is_cdp_swap_needed():
+ return self.driver.cdp.select_all(*args, **kwargs)
+ else:
+ return self.find_elements(*args, **kwargs)
+
def add_cookie(self, *args, **kwargs):
page_actions._reconnect_if_disconnected(self.driver)
self.driver.default_add_cookie(*args, **kwargs)
@@ -372,6 +384,12 @@ def open_new_tab(self, switch_to=True):
def switch_to_window(self, *args, **kwargs):
page_actions.switch_to_window(self.driver, *args, **kwargs)
+ def switch_to_newest_tab(self):
+ if self.__is_cdp_swap_needed():
+ self.driver.cdp.switch_to_newest_tab()
+ return
+ self.switch_to_newest_window()
+
def switch_to_tab(self, *args, **kwargs):
self.switch_to_window(*args, **kwargs)
diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py
index 044986ead7d..2e9519d9516 100644
--- a/seleniumbase/fixtures/base_case.py
+++ b/seleniumbase/fixtures/base_case.py
@@ -5096,8 +5096,32 @@ def activate_cdp_mode(self, url=None, **kwargs):
self.solve_captcha = self.cdp.solve_captcha
if hasattr(self.cdp, "click_captcha"):
self.click_captcha = self.cdp.click_captcha
+ if hasattr(self.cdp, "add_handler"):
+ self.add_handler = self.cdp.add_handler
+ if hasattr(self.cdp, "close_active_tab"):
+ self.close_active_tab = self.cdp.close_active_tab
if hasattr(self.cdp, "find_element_by_text"):
self.find_element_by_text = self.cdp.find_element_by_text
+ if hasattr(self.cdp, "flash"):
+ self.flash = self.cdp.flash
+ if hasattr(self.cdp, "get_active_tab"):
+ self.get_active_tab = self.cdp.get_active_tab
+ if hasattr(self.cdp, "get_endpoint_url"):
+ self.get_endpoint_url = self.cdp.get_endpoint_url
+ if hasattr(self.cdp, "get_event_loop"):
+ self.get_event_loop = self.cdp.get_event_loop
+ if hasattr(self.cdp, "get_tabs"):
+ self.get_tabs = self.cdp.get_tabs
+ if hasattr(self.cdp, "gui_click_and_hold"):
+ self.gui_click_and_hold = self.cdp.gui_click_and_hold
+ if hasattr(self.cdp, "gui_click_element"):
+ self.gui_click_element = self.cdp.gui_click_element
+ if hasattr(self.cdp, "gui_drag_and_drop"):
+ self.gui_drag_and_drop = self.cdp.gui_drag_and_drop
+ if hasattr(self.cdp, "gui_drag_drop_points"):
+ self.gui_drag_drop_points = self.cdp.gui_drag_drop_points
+ if hasattr(self.cdp, "highlight_overlay"):
+ self.highlight_overlay = self.cdp.highlight_overlay
if getattr(self.driver, "_is_using_auth", None):
with suppress(Exception):
self.cdp.loop.run_until_complete(self.cdp.page.wait(0.25))
@@ -8861,9 +8885,22 @@ def set_text_content(
element = page_actions.wait_for_element_present(
self.driver, selector, by, timeout
)
- if element.tag_name.lower() in ["input", "textarea"]:
- self.js_update_text(selector, text, by=by, timeout=timeout)
- return
+ try:
+ if element.tag_name.lower() in ["input", "textarea"]:
+ self.js_update_text(selector, text, by=by, timeout=timeout)
+ return
+ except (Stale_Exception, ENI_Exception):
+ time.sleep(0.16)
+ if self.__is_cdp_swap_needed():
+ element = self.cdp.select(selector, timeout=timeout)
+ else:
+ self.wait_for_ready_state_complete()
+ element = page_actions.wait_for_element_present(
+ self.driver, selector, by, timeout
+ )
+ if element.tag_name.lower() in ["input", "textarea"]:
+ self.js_update_text(selector, text, by=by, timeout=timeout)
+ return
original_selector = selector
css_selector = self.convert_to_css_selector(selector, by=by)
if scroll:
@@ -9340,6 +9377,9 @@ def switch_to_default_tab(self):
def switch_to_newest_tab(self):
"""Same as self.switch_to_newest_window()"""
+ if self.__is_cdp_swap_needed():
+ self.cdp.switch_to_newest_tab()
+ return
self.switch_to_newest_window()
def save_as_html(self, name, folder=None):
@@ -9976,6 +10016,8 @@ def wait_for_element_present(
self, selector, by="css selector", timeout=None
):
"""Waits for an element to appear in the HTML of a page.
+ Returns the element once it exists in the HTML.
+ Raises an exception if the element doesn't come in time.
The element does not need be visible (it may be hidden)."""
self.__check_scope()
if not timeout:
@@ -10022,6 +10064,19 @@ def wait_for_element(self, selector, by="css selector", timeout=None):
self.driver, selector, by, timeout
)
+ def select(self, selector, by="css selector", timeout=None):
+ """Returns the element once it appears in the HTML.
+ Raises an exception if the element doesn't come in time.
+ The element does not need be visible (it may be hidden).
+ If CDP Mode has been activated: Calls self.cdp.select().
+ Otherwise: Same as self.wait_for_element_present()."""
+ if self.__is_cdp_swap_needed():
+ return self.cdp.select(selector, timeout=timeout)
+ else:
+ return self.wait_for_element_present(
+ selector, by=by, timeout=timeout
+ )
+
def get_element(self, selector, by="css selector", timeout=None):
"""Same as wait_for_element_present() - returns the element.
The element does not need be visible (it may be hidden)."""
diff --git a/seleniumbase/undetected/cdp_driver/browser.py b/seleniumbase/undetected/cdp_driver/browser.py
index 2f25edb65be..a11900ccc15 100644
--- a/seleniumbase/undetected/cdp_driver/browser.py
+++ b/seleniumbase/undetected/cdp_driver/browser.py
@@ -455,11 +455,13 @@ async def get(
"*.google-analytics.com*",
"*.amazon-adsystem.com*",
"*.adsafeprotected.com*",
+ "*.m.media-amazon.com*",
"*.ads.linkedin.com*",
"*.casalemedia.com*",
"*.doubleclick.net*",
"*.admanmedia.com*",
"*.quantserve.com*",
+ "*.ads.simpli.fi*",
"*.fastclick.net*",
"*.snigelweb.com*",
"*.bidswitch.net*",
diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py
index 788b8ac4495..64c47128d28 100644
--- a/seleniumbase/undetected/cdp_driver/tab.py
+++ b/seleniumbase/undetected/cdp_driver/tab.py
@@ -378,6 +378,9 @@ async def get(
async def open(self, url="about:blank"):
return await self.get(url=url)
+ async def goto(self, url="about:blank"):
+ return await self.get(url=url)
+
async def query_selector_all(
self,
selector: str,
@@ -1745,6 +1748,10 @@ async def solve_captcha(self):
'[data-callback="onCaptchaSuccess"]'
):
selector = '[data-callback="onCaptchaSuccess"]'
+ elif await self.is_element_present(
+ '[class*="captcha"] div:not([class])'
+ ):
+ selector = '[class*="captcha"] div:not([class])'
elif await self.is_element_present(
"div:not([class]):not([id]):not([aria-label]) > "
"div:not([class]):not([id]):not([aria-label])"
From c80c2fb2ce97d6c83acd8a580cdc57c1f0c58225 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 19:31:42 -0400
Subject: [PATCH 02/11] Refresh Python dependencies
---
requirements.txt | 2 +-
setup.py | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/requirements.txt b/requirements.txt
index b31aab1a32d..78b4ca4e175 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@ setuptools~=70.2;python_version<"3.10"
setuptools>=82.0.1;python_version>="3.10"
wheel>=0.47.0
attrs>=26.1.0
-certifi>=2026.4.22
+certifi>=2026.5.20
exceptiongroup>=1.3.1
websockets~=15.0.1;python_version<"3.10"
websockets>=16.0;python_version>="3.10"
diff --git a/setup.py b/setup.py
index f725f42615a..8b2a812d886 100755
--- a/setup.py
+++ b/setup.py
@@ -168,7 +168,7 @@
'setuptools>=82.0.1;python_version>="3.10"',
'wheel>=0.47.0',
'attrs>=26.1.0',
- 'certifi>=2026.4.22',
+ 'certifi>=2026.5.20',
'exceptiongroup>=1.3.1',
'websockets~=15.0.1;python_version<"3.10"',
'websockets>=16.0;python_version>="3.10"',
@@ -304,7 +304,9 @@
# pip install -e .[playwright]
# (For the Playwright integration.)
"playwright": [
- "playwright>=1.60.0",
+ 'playwright>=1.60.0',
+ 'greenlet>=3.2.5;python_version<"3.10"',
+ 'greenlet>=3.5.1;python_version>="3.10"',
],
# pip install -e .[pyautogui]
# (Already a required dependency on Linux now.)
From 16ae5cb3cbaeddc6c8bcd83035364b425aa62a43 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 19:35:38 -0400
Subject: [PATCH 03/11] Update Tour examples
---
examples/tour_examples/ReadMe.md | 92 +++++++++++++++++--
.../tour_examples/bootstrap_google_tour.py | 4 +-
examples/tour_examples/driverjs_maps_tour.py | 4 +-
examples/tour_examples/google_tour.py | 4 +-
.../tour_examples/hopscotch_google_tour.py | 4 +-
examples/tour_examples/introjs_google_tour.py | 4 +-
examples/tour_examples/maps_introjs_tour.py | 4 +-
.../tour_examples/shepherd_google_tour.py | 4 +-
8 files changed, 97 insertions(+), 23 deletions(-)
diff --git a/examples/tour_examples/ReadMe.md b/examples/tour_examples/ReadMe.md
index 9ab0f0e9a5d..b81f0c3b70a 100644
--- a/examples/tour_examples/ReadMe.md
+++ b/examples/tour_examples/ReadMe.md
@@ -1,12 +1,8 @@
-
-
π Interactive Product Tours π
-Increase SaaS Product Adoption by 10x or more.
-
-* SeleniumBase Tours utilize 5 JavaScript libraries for creating interactive walkthroughs on **any website**:
+SeleniumBase Tours utilize 5 JavaScript libraries for creating interactive walkthroughs on **any website**:
> **[IntroJS](https://introjs.com/)**, **[Bootstrap Tour](http://bootstraptour.com/)**, **[DriverJS](https://kamranahmed.info/driver.js/)**, **[Shepherd](https://shepherdjs.dev/)**, and **[Hopscotch](https://linkedinattic.github.io/hopscotch/)**.
@@ -105,28 +101,106 @@ All methods have the optional ``name`` argument, which is only needed if you're
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__, "--uc")
-class MyTourClass(BaseCase):
+class MyTourClass(BaseCase):
def test_google_tour(self):
if not self.undetectable:
self.get_new_driver(undetectable=True)
- self.open('https://google.com/ncr')
+ self.open("https://google.com/ncr")
self.click_if_visible('button:contains("Accept all")')
- self.wait_for_element('input[title="Search"]')
+ self.wait_for_element('[title="Search"]')
self.hide_elements("iframe")
+ # Create a website tour using the ShepherdJS library with "dark" theme
+ # Same as: self.create_shepherd_tour(theme="dark")
self.create_tour(theme="dark")
self.add_tour_step("Welcome to Google!", title="SeleniumBase Tours")
self.add_tour_step("Type in your query here.", '[title="Search"]')
self.play_tour()
- self.highlight_type('input[title="Search"]', "Google")
+ self.highlight_type('[title="Search"]', "Google")
self.wait_for_element('[role="listbox"]') # Wait for autocomplete
+ # Create a website tour using the ShepherdJS library with "light" theme
+ # Same as: self.create_shepherd_tour(theme="light")
self.create_tour(theme="light")
self.add_tour_step("Then click to search.", '[value="Google Search"]')
self.add_tour_step("Or press [ENTER] after entry.", '[title="Search"]')
self.play_tour()
+
+ self.highlight_type('[title="Search"]', "GitHub\n")
+ self.ad_block()
+ self.wait_for_element("#search")
+
+ # Create a website tour using the Bootstrap Tour JS library
+ # Same as: self.create_bootstrap_tour()
+ self.create_tour(theme="bootstrap")
+ self.add_tour_step("3-second autoplay...")
+ self.add_tour_step("Here's the next tour:")
+ self.play_tour(interval=3) # Tour automatically continues after 3 sec
+
+ self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z")
+ self.wait_for_element('[name="q"]', timeout=20)
+ self.wait_for_element('[aria-label="Interactive map"]', timeout=20)
+ self.wait_for_element('[aria-label="Zoom in"]', timeout=20)
+ self.wait_for_element('[aria-label="Zoom out"]')
+ self.wait_for_element('[jsaction*="minimap.main;"]')
+ self.sleep(0.5)
+
+ # Create a website tour using the IntroJS library
+ # Same as: self.create_introjs_tour()
+ self.create_tour(theme="introjs")
+ self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
+ self.add_tour_step(
+ "The location goes here.", '[name="q"]', title="Search Box"
+ )
+ self.add_tour_step(
+ "Then click here to show it on the map.",
+ '[aria-label="Search"]',
+ alignment="bottom",
+ )
+ self.add_tour_step(
+ "Or click here to get driving directions.",
+ 'button[aria-label="Directions"]',
+ alignment="bottom",
+ )
+ self.add_tour_step(
+ "Use this button to switch to Satellite view.",
+ 'button[jsaction*="minimap.main;"]',
+ alignment="right",
+ )
+ self.add_tour_step(
+ "Click here to zoom in.",
+ '[aria-label="Zoom in"]',
+ alignment="left",
+ )
+ self.add_tour_step(
+ "Or click here to zoom out.",
+ '[aria-label="Zoom out"]',
+ alignment="left",
+ )
+ if self.is_element_visible('button[jsaction*="settings.open;"]'):
+ self.add_tour_step(
+ "Use the Menu button to see more options.",
+ 'button[jsaction*="settings.open;"]',
+ alignment="right",
+ )
+ elif self.is_element_visible('button[jsaction="navigationrail.more"]'):
+ self.add_tour_step(
+ "Use the Menu button to see more options.",
+ 'button[jsaction="navigationrail.more"]',
+ alignment="right",
+ )
+ self.add_tour_step(
+ "Or click here to see more Google apps.",
+ '[aria-label="Google apps"]',
+ alignment="left",
+ )
+ self.add_tour_step(
+ "Thanks for using SeleniumBase Tours!", title="End of Guided Tour"
+ )
+ self.export_tour() # The default name for exports is "my_tour.js"
+ self.play_tour()
```
#### That code is from [google_tour.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/google_tour.py), which you can run from the ``tour_examples/`` folder with the following command:
diff --git a/examples/tour_examples/bootstrap_google_tour.py b/examples/tour_examples/bootstrap_google_tour.py
index b1c80b07e96..888e6d6e769 100644
--- a/examples/tour_examples/bootstrap_google_tour.py
+++ b/examples/tour_examples/bootstrap_google_tour.py
@@ -44,11 +44,11 @@ def test_google_tour(self):
self.create_bootstrap_tour()
self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/driverjs_maps_tour.py b/examples/tour_examples/driverjs_maps_tour.py
index 847fc8abc17..22d13454d5a 100644
--- a/examples/tour_examples/driverjs_maps_tour.py
+++ b/examples/tour_examples/driverjs_maps_tour.py
@@ -17,11 +17,11 @@ def test_create_tour(self):
self.create_tour(theme="driverjs")
self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/google_tour.py b/examples/tour_examples/google_tour.py
index c68a1539a53..8f5b88b2a49 100644
--- a/examples/tour_examples/google_tour.py
+++ b/examples/tour_examples/google_tour.py
@@ -52,11 +52,11 @@ def test_google_tour(self):
self.create_tour(theme="introjs")
self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/hopscotch_google_tour.py b/examples/tour_examples/hopscotch_google_tour.py
index 7bbdc1747d8..24bcdd5fe0b 100644
--- a/examples/tour_examples/hopscotch_google_tour.py
+++ b/examples/tour_examples/hopscotch_google_tour.py
@@ -44,11 +44,11 @@ def test_google_tour(self):
self.create_hopscotch_tour()
self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/introjs_google_tour.py b/examples/tour_examples/introjs_google_tour.py
index a07cfc73e70..d3ee87dafbc 100644
--- a/examples/tour_examples/introjs_google_tour.py
+++ b/examples/tour_examples/introjs_google_tour.py
@@ -45,11 +45,11 @@ def test_google_tour(self):
self.create_introjs_tour()
self.add_tour_step("Welcome to Google Maps", title="SeleniumBase Tour")
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/maps_introjs_tour.py b/examples/tour_examples/maps_introjs_tour.py
index e3035435949..d898dfd1b30 100644
--- a/examples/tour_examples/maps_introjs_tour.py
+++ b/examples/tour_examples/maps_introjs_tour.py
@@ -17,11 +17,11 @@ def test_google_maps_tour(self):
"Welcome to Google Maps", title="β
SeleniumBase Tours π"
)
self.add_tour_step(
- "The location goes here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
diff --git a/examples/tour_examples/shepherd_google_tour.py b/examples/tour_examples/shepherd_google_tour.py
index e2d0eee18cb..7d82133ce9a 100644
--- a/examples/tour_examples/shepherd_google_tour.py
+++ b/examples/tour_examples/shepherd_google_tour.py
@@ -44,11 +44,11 @@ def test_google_tour(self):
self.create_shepherd_tour(theme="dark")
self.add_tour_step("Welcome to Google Maps!")
self.add_tour_step(
- "Type in a location here.", "#searchboxinput", title="Search Box"
+ "The location goes here.", '[name="q"]', title="Search Box"
)
self.add_tour_step(
"Then click here to show it on the map.",
- "#searchbox-searchbutton",
+ '[aria-label="Search"]',
alignment="bottom",
)
self.add_tour_step(
From 3ec9d4a81d0d5ce790b4167efd069f7149009115 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:29:24 -0400
Subject: [PATCH 04/11] Update Stealthy Playwright examples
---
examples/cdp_mode/playwright/ReadMe.md | 2 +-
examples/cdp_mode/playwright/raw_basic_nested.py | 2 +-
examples/cdp_mode/playwright/raw_bing_cap_nested.py | 2 +-
examples/cdp_mode/playwright/raw_browserscan_nested.py | 8 ++++----
examples/cdp_mode/playwright/raw_browserscan_sync.py | 6 +++---
examples/cdp_mode/playwright/raw_copilot_nested.py | 2 +-
examples/cdp_mode/playwright/raw_fingerprint_nested.py | 6 +++---
examples/cdp_mode/playwright/raw_gitlab_nested.py | 2 +-
examples/cdp_mode/playwright/raw_idealista_nested.py | 2 +-
9 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/examples/cdp_mode/playwright/ReadMe.md b/examples/cdp_mode/playwright/ReadMe.md
index 5ddab416360..8038a3a236f 100644
--- a/examples/cdp_mode/playwright/ReadMe.md
+++ b/examples/cdp_mode/playwright/ReadMe.md
@@ -55,7 +55,7 @@ from seleniumbase import SB
with SB(uc=True) as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
diff --git a/examples/cdp_mode/playwright/raw_basic_nested.py b/examples/cdp_mode/playwright/raw_basic_nested.py
index 77f1d23f94d..99ce8e96a18 100644
--- a/examples/cdp_mode/playwright/raw_basic_nested.py
+++ b/examples/cdp_mode/playwright/raw_basic_nested.py
@@ -3,7 +3,7 @@
with SB(uc=True) as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
diff --git a/examples/cdp_mode/playwright/raw_bing_cap_nested.py b/examples/cdp_mode/playwright/raw_bing_cap_nested.py
index fe3264ddc98..6f752a06ccb 100644
--- a/examples/cdp_mode/playwright/raw_bing_cap_nested.py
+++ b/examples/cdp_mode/playwright/raw_bing_cap_nested.py
@@ -3,7 +3,7 @@
with SB(uc=True, locale="en") as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
diff --git a/examples/cdp_mode/playwright/raw_browserscan_nested.py b/examples/cdp_mode/playwright/raw_browserscan_nested.py
index cb7b17b81d5..58ee5e53202 100644
--- a/examples/cdp_mode/playwright/raw_browserscan_nested.py
+++ b/examples/cdp_mode/playwright/raw_browserscan_nested.py
@@ -3,14 +3,14 @@
with SB(uc=True, locale="en", ad_block=True) as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ 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://www.browserscan.net/bot-detection")
+ page.goto("https://browserscan.net/bot-detection")
page.wait_for_timeout(500)
- sb.cdp.flash("Test Results", duration=3, pause=1)
+ sb.flash("Test Results", duration=1.5, pause=0.5)
sb.assert_element('strong:contains("Normal")')
print("Bot Not Detected")
- sb.cdp.flash('strong:contains("Normal")', duration=3, pause=2)
+ sb.flash('strong:contains("Normal")', pause=1)
diff --git a/examples/cdp_mode/playwright/raw_browserscan_sync.py b/examples/cdp_mode/playwright/raw_browserscan_sync.py
index 7c685bcec03..8cc6fbb5ed2 100644
--- a/examples/cdp_mode/playwright/raw_browserscan_sync.py
+++ b/examples/cdp_mode/playwright/raw_browserscan_sync.py
@@ -7,9 +7,9 @@
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
page = browser.contexts[0].pages[0]
- page.goto("https://www.browserscan.net/bot-detection")
+ page.goto("https://browserscan.net/bot-detection")
page.wait_for_timeout(500)
- sb.flash("Test Results", duration=3, pause=1)
+ 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")', duration=3, pause=2)
+ sb.flash('strong:contains("Normal")', pause=1)
diff --git a/examples/cdp_mode/playwright/raw_copilot_nested.py b/examples/cdp_mode/playwright/raw_copilot_nested.py
index 5e3141ded52..9b3bb52f2e5 100644
--- a/examples/cdp_mode/playwright/raw_copilot_nested.py
+++ b/examples/cdp_mode/playwright/raw_copilot_nested.py
@@ -3,7 +3,7 @@
with SB(uc=True) as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
diff --git a/examples/cdp_mode/playwright/raw_fingerprint_nested.py b/examples/cdp_mode/playwright/raw_fingerprint_nested.py
index 18411853d82..391ff7ed6e2 100644
--- a/examples/cdp_mode/playwright/raw_fingerprint_nested.py
+++ b/examples/cdp_mode/playwright/raw_fingerprint_nested.py
@@ -3,15 +3,15 @@
with SB(uc=True, locale="en") as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ 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://demo.fingerprint.com/playground")
page.wait_for_timeout(500)
- sb.cdp.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
+ sb.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
bot_row_selector = 'table:contains("Bot") tr:nth-of-type(3)'
print(sb.get_text(bot_row_selector))
sb.assert_text("Bot Not detected", bot_row_selector)
- sb.cdp.flash(bot_row_selector, duration=3, pause=2)
+ sb.flash(bot_row_selector, duration=3, pause=2)
diff --git a/examples/cdp_mode/playwright/raw_gitlab_nested.py b/examples/cdp_mode/playwright/raw_gitlab_nested.py
index 7d83b26c63c..03ebe32b3e4 100644
--- a/examples/cdp_mode/playwright/raw_gitlab_nested.py
+++ b/examples/cdp_mode/playwright/raw_gitlab_nested.py
@@ -3,7 +3,7 @@
with SB(uc=True, locale="en") as sb:
sb.activate_cdp_mode()
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
diff --git a/examples/cdp_mode/playwright/raw_idealista_nested.py b/examples/cdp_mode/playwright/raw_idealista_nested.py
index 0fb68dfbe5b..3ddbdcb2d57 100644
--- a/examples/cdp_mode/playwright/raw_idealista_nested.py
+++ b/examples/cdp_mode/playwright/raw_idealista_nested.py
@@ -8,7 +8,7 @@
sb.sleep(1)
sb.solve_captcha()
sb.sleep(2)
- endpoint_url = sb.cdp.get_endpoint_url()
+ endpoint_url = sb.get_endpoint_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(endpoint_url)
From a7808d0335b6748d8aae20d84357496db0aa6595 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:33:11 -0400
Subject: [PATCH 05/11] Update CDP Mode examples
---
examples/cdp_mode/ReadMe.md | 8 ++++----
examples/cdp_mode/raw_amazon.py | 2 +-
examples/cdp_mode/raw_browserscan.py | 6 +++---
examples/cdp_mode/raw_canvas.py | 4 ++--
examples/cdp_mode/raw_cdp_browserscan.py | 8 ++++----
examples/cdp_mode/raw_cdp_fingerprint.py | 4 ++--
examples/cdp_mode/raw_cdp_hyatt.py | 6 +++++-
examples/cdp_mode/raw_cdp_patent.py | 9 +++++++++
examples/cdp_mode/raw_cdp_pixelscan.py | 15 +++++++--------
examples/cdp_mode/raw_cdp_timezone.py | 16 ++++++++++++++++
examples/cdp_mode/raw_cdp_with_sb.py | 6 ++++--
examples/cdp_mode/raw_demo_site.py | 2 +-
examples/cdp_mode/raw_drag_and_drop.py | 8 ++++----
examples/cdp_mode/raw_facebook.py | 2 +-
examples/cdp_mode/raw_fingerprint.py | 4 ++--
examples/cdp_mode/raw_gitlab.py | 1 -
examples/cdp_mode/raw_hyatt.py | 8 ++++----
examples/cdp_mode/raw_linkedin.py | 2 +-
examples/cdp_mode/raw_mobile_gitlab.py | 4 ++--
examples/cdp_mode/raw_mobile_roblox.py | 4 ++--
examples/cdp_mode/raw_mycdp_cookies.py | 4 ++--
examples/cdp_mode/raw_patent.py | 10 ++++++++++
examples/cdp_mode/raw_pixelscan.py | 11 +++++------
examples/cdp_mode/raw_pokemon.py | 8 ++++----
examples/cdp_mode/raw_priceline.py | 6 +++---
examples/cdp_mode/raw_publication.py | 2 +-
examples/cdp_mode/raw_req_sb.py | 4 ++--
examples/cdp_mode/raw_res_nike.py | 5 ++---
examples/cdp_mode/raw_seatgeek.py | 4 ++--
examples/cdp_mode/raw_southwest.py | 24 ++++++++++++------------
examples/cdp_mode/raw_timezone_sb.py | 2 +-
examples/cdp_mode/raw_trails.py | 8 ++++----
examples/cdp_mode/raw_walmart.py | 6 +++---
examples/cdp_mode/raw_xhr_sb.py | 6 +++---
34 files changed, 128 insertions(+), 91 deletions(-)
create mode 100644 examples/cdp_mode/raw_cdp_patent.py
create mode 100644 examples/cdp_mode/raw_cdp_timezone.py
create mode 100644 examples/cdp_mode/raw_patent.py
diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md
index e7da2947e17..d92d723b8bf 100644
--- a/examples/cdp_mode/ReadMe.md
+++ b/examples/cdp_mode/ReadMe.md
@@ -154,14 +154,14 @@ with SB(uc=True, test=True, locale="en", ad_block=True) as sb:
sb.assert_element('img[alt="Pikachu"]')
sb.scroll_into_view("div.pokemon-ability-info")
sb.sleep(1.2)
- sb.cdp.flash('div[class*="title"]')
- sb.cdp.flash('img[alt="Pikachu"]')
- sb.cdp.flash("div.pokemon-ability-info")
+ sb.flash('div[class*="title"]')
+ sb.flash('img[alt="Pikachu"]')
+ sb.flash("div.pokemon-ability-info")
name = sb.get_text("label.styled-select")
info = sb.get_text("div.version-descriptions p.active")
print("*** %s: ***\n* %s" % (name, info))
sb.sleep(2)
- sb.cdp.highlight_overlay("div.pokemon-ability-info")
+ sb.highlight_overlay("div.pokemon-ability-info")
sb.sleep(2)
sb.open("https://events.pokemon.com/EventLocator/")
sb.sleep(2)
diff --git a/examples/cdp_mode/raw_amazon.py b/examples/cdp_mode/raw_amazon.py
index 8b8f226a691..4ededdff735 100644
--- a/examples/cdp_mode/raw_amazon.py
+++ b/examples/cdp_mode/raw_amazon.py
@@ -9,7 +9,7 @@
sb.press_keys('input[role="searchbox"]', "TI-89\n")
sb.sleep(3)
for i in range(16):
- sb.cdp.scroll_down(16)
+ sb.scroll_down(16)
print(sb.get_page_title())
sb.save_as_pdf_to_logs()
sb.save_page_source_to_logs()
diff --git a/examples/cdp_mode/raw_browserscan.py b/examples/cdp_mode/raw_browserscan.py
index b653635669c..037dd8f5264 100644
--- a/examples/cdp_mode/raw_browserscan.py
+++ b/examples/cdp_mode/raw_browserscan.py
@@ -1,9 +1,9 @@
from seleniumbase import SB
with SB(uc=True, test=True, locale="en", ad_block=True) as sb:
- url = "https://www.browserscan.net/bot-detection"
+ url = "https://browserscan.net/bot-detection"
sb.activate_cdp_mode(url)
- sb.cdp.flash("Test Results", duration=3, pause=1)
+ sb.flash("Test Results", duration=1.5, pause=0.5)
sb.assert_element('strong:contains("Normal")')
print("Bot Not Detected")
- sb.cdp.flash('strong:contains("Normal")', duration=3, pause=2)
+ sb.flash('strong:contains("Normal")', pause=1)
diff --git a/examples/cdp_mode/raw_canvas.py b/examples/cdp_mode/raw_canvas.py
index 7ec4380de6e..9cd23f7854e 100644
--- a/examples/cdp_mode/raw_canvas.py
+++ b/examples/cdp_mode/raw_canvas.py
@@ -12,7 +12,7 @@ def get_canvas_pixel_colors_at_top_left(sb):
with SB(uc=True, test=True) as sb:
- # Testing sb.cdp.click_with_offset()
+ # Testing click_with_offset()
url = "https://seleniumbase.io/canvas/"
sb.activate_cdp_mode(url)
sb.assert_title_contains("Canvas")
@@ -25,7 +25,7 @@ def get_canvas_pixel_colors_at_top_left(sb):
sb.assert_equal(rgb, [39, 43, 56]) # Blue by hamburger
with SB(uc=True, test=True) as sb:
- # Testing sb.cdp.gui_click_with_offset()
+ # Testing gui_click_with_offset()
url = "https://seleniumbase.io/other/canvas"
sb.activate_cdp_mode(url)
sb.assert_title_contains("Canvas")
diff --git a/examples/cdp_mode/raw_cdp_browserscan.py b/examples/cdp_mode/raw_cdp_browserscan.py
index 30ece9c0785..223db2ccfb2 100644
--- a/examples/cdp_mode/raw_cdp_browserscan.py
+++ b/examples/cdp_mode/raw_cdp_browserscan.py
@@ -1,8 +1,8 @@
from seleniumbase import sb_cdp
-url = "https://www.browserscan.net/bot-detection"
-sb = sb_cdp.Chrome(url, locale="en", ad_block=True)
-sb.flash("Test Results", duration=3, pause=1)
+sb = sb_cdp.Chrome(locale="en", ad_block=True)
+sb.open("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")', duration=3, pause=2)
+sb.flash('strong:contains("Normal")', pause=1)
diff --git a/examples/cdp_mode/raw_cdp_fingerprint.py b/examples/cdp_mode/raw_cdp_fingerprint.py
index 96a56739ae6..8e36d99e38f 100644
--- a/examples/cdp_mode/raw_cdp_fingerprint.py
+++ b/examples/cdp_mode/raw_cdp_fingerprint.py
@@ -1,7 +1,7 @@
from seleniumbase import sb_cdp
-url = "https://demo.fingerprint.com/playground"
-sb = sb_cdp.Chrome(url)
+sb = sb_cdp.Chrome()
+sb.open("https://demo.fingerprint.com/playground")
sb.wait_for_element('a[href*="browser-bot-detection"]')
sb.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
bot_row_selector = 'table:contains("Bot") tr:nth-of-type(3)'
diff --git a/examples/cdp_mode/raw_cdp_hyatt.py b/examples/cdp_mode/raw_cdp_hyatt.py
index 6bf9fd27128..0d719d4feea 100644
--- a/examples/cdp_mode/raw_cdp_hyatt.py
+++ b/examples/cdp_mode/raw_cdp_hyatt.py
@@ -11,8 +11,12 @@
sb.type('input[id="search-term"]', location)
sb.sleep(1.2)
sb.click('li[data-js="suggestion"]')
-sb.sleep(1.2)
+sb.sleep(0.6)
+sb.click_if_visible('button[aria-label="Close"]')
+sb.sleep(0.8)
sb.click("button.be-button-shop")
+sb.sleep(1)
+sb.click_if_visible('[label="Find Hotels"]')
sb.sleep(6)
card_info = 'div[data-booking-status="BOOKABLE"] [class*="HotelCard_info"]'
hotels = sb.select_all(card_info)
diff --git a/examples/cdp_mode/raw_cdp_patent.py b/examples/cdp_mode/raw_cdp_patent.py
new file mode 100644
index 00000000000..ee5f18a1f52
--- /dev/null
+++ b/examples/cdp_mode/raw_cdp_patent.py
@@ -0,0 +1,9 @@
+from seleniumbase import sb_cdp
+
+url = "https://www.lens.org/lens/patent/135-034-272-112-366/frontpage"
+sb = sb_cdp.Chrome(url)
+sb.sleep(3.5)
+sb.solve_captcha()
+sb.flash('[ng-if*="patent.title"]', duration=3, pause=2)
+print("* " + sb.get_text('[ng-if*="patent.title"]') + " *")
+print(sb.get_text("ol.claims"))
diff --git a/examples/cdp_mode/raw_cdp_pixelscan.py b/examples/cdp_mode/raw_cdp_pixelscan.py
index 5cd21eab576..0a73349c161 100644
--- a/examples/cdp_mode/raw_cdp_pixelscan.py
+++ b/examples/cdp_mode/raw_cdp_pixelscan.py
@@ -1,16 +1,15 @@
from seleniumbase import sb_cdp
-url = "https://pixelscan.net/fingerprint-check"
-sb = sb_cdp.Chrome(url, incognito=True)
+sb = sb_cdp.Chrome(incognito=True)
+sb.open("https://pixelscan.net/fingerprint-check")
+sb.sleep(1)
sb.wait_for_element("pxlscn-dynamic-ad")
sb.sleep(0.5)
sb.remove_elements("pxlscn-dynamic-ad")
-sb.sleep(2)
-sb.assert_text("No masking detected", "pxlscn-fingerprint-masking")
-sb.assert_text("No automated behavior", "pxlscn-bot-detection")
-sb.highlight('span.status-success')
sb.sleep(1)
+sb.assert_text("No automated behavior", "pxlscn-bot-detection")
+sb.wait_for_element("span.status-success")
+sb.assert_text("No masking detected", "pxlscn-fingerprint-masking")
+sb.highlight("span.status-success")
sb.highlight("pxlscn-fingerprint-masking p")
-sb.sleep(1)
sb.highlight("pxlscn-bot-detection p")
-sb.sleep(2)
diff --git a/examples/cdp_mode/raw_cdp_timezone.py b/examples/cdp_mode/raw_cdp_timezone.py
new file mode 100644
index 00000000000..ed02ee80c92
--- /dev/null
+++ b/examples/cdp_mode/raw_cdp_timezone.py
@@ -0,0 +1,16 @@
+from seleniumbase import sb_cdp
+
+sb = sb_cdp.Chrome(ad_block=True, incognito=True)
+url = "https://www.randymajors.org/what-time-zone-am-i-in"
+sb.open(url, tzone="Asia/Kolkata", geoloc=(26.863, 80.94))
+sb.remove_elements("#right-sidebar")
+sb.sleep(2.5)
+sb.remove_elements('[data-google-query-id]')
+sb.remove_elements("iframe:not(#embedMapFrame)")
+sb.sleep(2.5)
+sb.open(url, tzone="Asia/Tokyo", geoloc=(35.050681, 136.844728))
+sb.remove_elements("#right-sidebar")
+sb.sleep(2.5)
+sb.remove_elements('[data-google-query-id]')
+sb.remove_elements("iframe:not(#embedMapFrame)")
+sb.sleep(2.5)
diff --git a/examples/cdp_mode/raw_cdp_with_sb.py b/examples/cdp_mode/raw_cdp_with_sb.py
index 621308afb63..a9b3c782af6 100644
--- a/examples/cdp_mode/raw_cdp_with_sb.py
+++ b/examples/cdp_mode/raw_cdp_with_sb.py
@@ -7,6 +7,8 @@
sb.activate_cdp_mode(url)
sb.sleep(2.5)
sb.internalize_links() # Don't open links in a new tab
+ sb.click_if_visible('[aria-label="Close Modal"]')
+ sb.sleep(0.2)
sb.click("#link_header_nav_experiences")
sb.sleep(3.5)
sb.remove_elements("msm-cookie-banner")
@@ -15,10 +17,10 @@
where_to = 'div[data-automation*="experiences"] input'
button = 'button[data-automation*="experiences-search"]'
sb.wait_for_text("Where to?")
- sb.cdp.gui_click_element(where_to)
+ sb.gui_click_element(where_to)
sb.press_keys(where_to, location)
sb.sleep(1)
- sb.cdp.gui_click_element(button)
+ sb.gui_click_element(button)
sb.sleep(3)
print(sb.get_title())
print("************")
diff --git a/examples/cdp_mode/raw_demo_site.py b/examples/cdp_mode/raw_demo_site.py
index 5864d66540a..d2ad2329a36 100644
--- a/examples/cdp_mode/raw_demo_site.py
+++ b/examples/cdp_mode/raw_demo_site.py
@@ -1,4 +1,4 @@
-"""Example of using various CDP Mode commands"""
+"""Example of using various CDP Mode commands via sb.cdp"""
from seleniumbase import SB
with SB(uc=True, test=True) as sb:
diff --git a/examples/cdp_mode/raw_drag_and_drop.py b/examples/cdp_mode/raw_drag_and_drop.py
index 993793653c2..e5057f32da7 100644
--- a/examples/cdp_mode/raw_drag_and_drop.py
+++ b/examples/cdp_mode/raw_drag_and_drop.py
@@ -4,7 +4,7 @@
url = "https://seleniumbase.io/other/drag_and_drop"
sb.activate_cdp_mode(url)
sb.assert_element_not_visible("#div1 img#drag1")
- sb.cdp.gui_drag_and_drop("#drag1", "#div1")
+ sb.gui_drag_and_drop("#drag1", "#div1")
sb.assert_element("#div1 img#drag1")
sb.sleep(1)
@@ -15,7 +15,7 @@
x, y = sb.get_gui_element_center("#draggable")
sb.switch_to_default_content()
sb.scroll_to_top()
- sb.cdp.gui_drag_drop_points(x, y, x + 180, y + 90)
- sb.cdp.gui_drag_drop_points(x + 180, y + 90, x + 60, y + 120)
- sb.cdp.gui_drag_drop_points(x + 60, y + 120, x + 40, y + 40)
+ sb.gui_drag_drop_points(x, y, x + 180, y + 90)
+ sb.gui_drag_drop_points(x + 180, y + 90, x + 60, y + 120)
+ sb.gui_drag_drop_points(x + 60, y + 120, x + 40, y + 40)
sb.sleep(1)
diff --git a/examples/cdp_mode/raw_facebook.py b/examples/cdp_mode/raw_facebook.py
index d6766c60b26..3abb6588f17 100644
--- a/examples/cdp_mode/raw_facebook.py
+++ b/examples/cdp_mode/raw_facebook.py
@@ -7,7 +7,7 @@
sb.click_if_visible('[aria-label="Close"] i')
sb.sleep(1)
for i in range(16):
- sb.cdp.scroll_down(16)
+ sb.scroll_down(16)
print(sb.get_page_title())
sb.save_as_pdf_to_logs()
sb.save_page_source_to_logs()
diff --git a/examples/cdp_mode/raw_fingerprint.py b/examples/cdp_mode/raw_fingerprint.py
index 2092432d4e5..016c459f536 100644
--- a/examples/cdp_mode/raw_fingerprint.py
+++ b/examples/cdp_mode/raw_fingerprint.py
@@ -3,8 +3,8 @@
with SB(uc=True, test=True) as sb:
url = "https://demo.fingerprint.com/playground"
sb.activate_cdp_mode(url)
- sb.cdp.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
+ sb.flash('a[href*="browser-bot-detection"]', duration=3, pause=1)
bot_row_selector = 'table:contains("Bot") tr:nth-of-type(3)'
print(sb.get_text(bot_row_selector))
sb.assert_text("Bot Not detected", bot_row_selector)
- sb.cdp.flash(bot_row_selector, duration=3, pause=2)
+ sb.flash(bot_row_selector, duration=3, pause=2)
diff --git a/examples/cdp_mode/raw_gitlab.py b/examples/cdp_mode/raw_gitlab.py
index 0d9b6a1018d..ddc8cd8f92d 100644
--- a/examples/cdp_mode/raw_gitlab.py
+++ b/examples/cdp_mode/raw_gitlab.py
@@ -10,4 +10,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)
diff --git a/examples/cdp_mode/raw_hyatt.py b/examples/cdp_mode/raw_hyatt.py
index 54d6095e312..72990eb8687 100644
--- a/examples/cdp_mode/raw_hyatt.py
+++ b/examples/cdp_mode/raw_hyatt.py
@@ -1,9 +1,9 @@
from seleniumbase import SB
-with SB(uc=True, test=True, locale="en") as sb:
+with SB(uc=True, test=True, locale="en", guest=True) as sb:
url = "https://www.hyatt.com/"
sb.activate_cdp_mode(url)
- sb.sleep(3.2)
+ sb.sleep(3.4)
sb.click_if_visible('button[aria-label="Close"]')
sb.sleep(0.1)
sb.click_if_visible("#onetrust-reject-all-handler")
@@ -14,11 +14,11 @@
sb.click('li[data-js="suggestion"]')
sb.sleep(0.6)
sb.click_if_visible('button[aria-label="Close"]')
- sb.sleep(0.6)
+ sb.sleep(0.8)
sb.click("button.be-button-shop")
sb.sleep(1)
sb.click_if_visible('[label="Find Hotels"]')
- sb.sleep(5)
+ sb.sleep(5.5)
card_info = 'div[data-booking-status="BOOKABLE"] [class*="HotelCard_info"]'
hotels = sb.select_all(card_info)
print("Hyatt Hotels in %s:" % location)
diff --git a/examples/cdp_mode/raw_linkedin.py b/examples/cdp_mode/raw_linkedin.py
index 83ec20e34e4..a76adb08314 100644
--- a/examples/cdp_mode/raw_linkedin.py
+++ b/examples/cdp_mode/raw_linkedin.py
@@ -7,7 +7,7 @@
sb.click_if_visible('button[aria-label="Dismiss"]')
sb.sleep(1)
for i in range(42):
- sb.cdp.scroll_down(16)
+ sb.scroll_down(16)
print(sb.get_page_title())
sb.save_as_pdf_to_logs()
sb.save_page_source_to_logs()
diff --git a/examples/cdp_mode/raw_mobile_gitlab.py b/examples/cdp_mode/raw_mobile_gitlab.py
index cccf9917ed0..b9853c39161 100644
--- a/examples/cdp_mode/raw_mobile_gitlab.py
+++ b/examples/cdp_mode/raw_mobile_gitlab.py
@@ -4,8 +4,8 @@
with SB(uc=True, test=True) as sb:
url = "https://gitlab.com/users/sign_in"
sb.activate_cdp_mode()
- tab = sb.cdp.get_active_tab()
- loop = sb.cdp.get_event_loop()
+ tab = sb.get_active_tab()
+ loop = sb.get_event_loop()
loop.run_until_complete(
tab.send(
mycdp.emulation.set_device_metrics_override(
diff --git a/examples/cdp_mode/raw_mobile_roblox.py b/examples/cdp_mode/raw_mobile_roblox.py
index 02c2d8aef6b..eee8c146a2e 100644
--- a/examples/cdp_mode/raw_mobile_roblox.py
+++ b/examples/cdp_mode/raw_mobile_roblox.py
@@ -8,8 +8,8 @@
"(KHTML, like Gecko) Mobile Safari/537.36"
)
sb.activate_cdp_mode(agent=agent)
- tab = sb.cdp.get_active_tab()
- loop = sb.cdp.get_event_loop()
+ tab = sb.get_active_tab()
+ loop = sb.get_event_loop()
loop.run_until_complete(
tab.send(
mycdp.emulation.set_device_metrics_override(
diff --git a/examples/cdp_mode/raw_mycdp_cookies.py b/examples/cdp_mode/raw_mycdp_cookies.py
index fe8983c7168..1625a7a0d97 100644
--- a/examples/cdp_mode/raw_mycdp_cookies.py
+++ b/examples/cdp_mode/raw_mycdp_cookies.py
@@ -3,6 +3,6 @@
with SB(uc=True, test=True) as sb:
sb.activate_cdp_mode("https://learn.microsoft.com/en-us/")
- tab = sb.cdp.get_active_tab()
- loop = sb.cdp.get_event_loop()
+ tab = sb.get_active_tab()
+ loop = sb.get_event_loop()
print(loop.run_until_complete(tab.send(mycdp.storage.get_cookies())))
diff --git a/examples/cdp_mode/raw_patent.py b/examples/cdp_mode/raw_patent.py
new file mode 100644
index 00000000000..faa62807b72
--- /dev/null
+++ b/examples/cdp_mode/raw_patent.py
@@ -0,0 +1,10 @@
+from seleniumbase import SB
+
+with SB(uc=True, test=True) as sb:
+ url = "https://www.lens.org/lens/patent/135-034-272-112-366/frontpage"
+ sb.activate_cdp_mode(url)
+ sb.sleep(3)
+ sb.solve_captcha()
+ sb.flash('[ng-if*="patent.title"]', duration=3, pause=2)
+ print("* " + sb.get_text('[ng-if*="patent.title"]') + " *")
+ print(sb.get_text("ol.claims"))
diff --git a/examples/cdp_mode/raw_pixelscan.py b/examples/cdp_mode/raw_pixelscan.py
index cc3658161b8..8976f222fc7 100644
--- a/examples/cdp_mode/raw_pixelscan.py
+++ b/examples/cdp_mode/raw_pixelscan.py
@@ -3,15 +3,14 @@
with SB(uc=True, test=True, incognito=True, ad_block=True) as sb:
url = "https://pixelscan.net/fingerprint-check"
sb.activate_cdp_mode(url)
+ sb.sleep(1)
sb.wait_for_element("pxlscn-dynamic-ad")
sb.sleep(0.5)
sb.remove_elements("pxlscn-dynamic-ad")
- sb.sleep(2)
- sb.assert_text("No masking detected", "pxlscn-fingerprint-masking")
- sb.assert_text("No automated behavior", "pxlscn-bot-detection")
- sb.cdp.highlight('span.status-success')
sb.sleep(1)
+ sb.assert_text("No automated behavior", "pxlscn-bot-detection")
+ sb.wait_for_element("span.status-success")
+ sb.assert_text("No masking detected", "pxlscn-fingerprint-masking")
+ sb.cdp.highlight("span.status-success")
sb.cdp.highlight("pxlscn-fingerprint-masking p")
- sb.sleep(1)
sb.cdp.highlight("pxlscn-bot-detection p")
- sb.sleep(2)
diff --git a/examples/cdp_mode/raw_pokemon.py b/examples/cdp_mode/raw_pokemon.py
index 38227c06153..5a1c6ba1315 100644
--- a/examples/cdp_mode/raw_pokemon.py
+++ b/examples/cdp_mode/raw_pokemon.py
@@ -21,14 +21,14 @@
sb.assert_element('img[alt="Pikachu"]')
sb.scroll_into_view("div.pokemon-ability-info")
sb.sleep(1.2)
- sb.cdp.flash('div[class*="title"]')
- sb.cdp.flash('img[alt="Pikachu"]')
- sb.cdp.flash("div.pokemon-ability-info")
+ sb.flash('div[class*="title"]')
+ sb.flash('img[alt="Pikachu"]')
+ sb.flash("div.pokemon-ability-info")
name = sb.get_text("label.styled-select")
info = sb.get_text("div.version-descriptions p.active")
print("*** %s: ***\n* %s" % (name, info))
sb.sleep(2)
- sb.cdp.highlight_overlay("div.pokemon-ability-info")
+ sb.highlight_overlay("div.pokemon-ability-info")
sb.sleep(2)
sb.open("https://events.pokemon.com/EventLocator/")
sb.sleep(2)
diff --git a/examples/cdp_mode/raw_priceline.py b/examples/cdp_mode/raw_priceline.py
index 063c41a4a86..fe85ddfca93 100644
--- a/examples/cdp_mode/raw_priceline.py
+++ b/examples/cdp_mode/raw_priceline.py
@@ -25,9 +25,9 @@
sb.sleep(0.6)
sb.click('form button[type="submit"]')
sb.sleep(4.8)
- if len(sb.cdp.get_tabs()) > 1:
- sb.cdp.close_active_tab()
- sb.cdp.switch_to_newest_tab()
+ if len(sb.get_tabs()) > 1:
+ sb.close_active_tab()
+ sb.switch_to_newest_tab()
sb.sleep(0.6)
sb.sleep(0.8)
for y in range(1, 9):
diff --git a/examples/cdp_mode/raw_publication.py b/examples/cdp_mode/raw_publication.py
index 882ffb9683a..088798f3fc1 100644
--- a/examples/cdp_mode/raw_publication.py
+++ b/examples/cdp_mode/raw_publication.py
@@ -6,7 +6,7 @@
sb.sleep(2.2)
shadow_head = "div.main-content div"
if sb.is_element_present(shadow_head):
- sb.cdp.gui_click_element(shadow_head)
+ sb.gui_click_element(shadow_head)
sb.sleep(1.5)
sb.assert_text("Discover the world's scientific knowledge")
sb.click_if_visible('button[aria-label="Close"]')
diff --git a/examples/cdp_mode/raw_req_sb.py b/examples/cdp_mode/raw_req_sb.py
index aab553f6bd2..a8e2b30f1cd 100644
--- a/examples/cdp_mode/raw_req_sb.py
+++ b/examples/cdp_mode/raw_req_sb.py
@@ -25,7 +25,7 @@ async def request_paused_handler(event, tab):
with SB(uc=True, test=True, locale="en") as sb:
sb.activate_cdp_mode("about:blank")
- sb.cdp.add_handler(mycdp.fetch.RequestPaused, request_paused_handler)
+ sb.add_handler(mycdp.fetch.RequestPaused, request_paused_handler)
url = "https://gettyimages.com/photos/firefly-2003-nathan"
sb.open(url)
- sb.sleep(5)
+ sb.sleep(4)
diff --git a/examples/cdp_mode/raw_res_nike.py b/examples/cdp_mode/raw_res_nike.py
index a984d05f20d..0aaa8edc700 100644
--- a/examples/cdp_mode/raw_res_nike.py
+++ b/examples/cdp_mode/raw_res_nike.py
@@ -28,8 +28,8 @@ async def receive_handler(event: mycdp.network.ResponseReceived):
with SB(uc=True, test=True, locale="en", pls="none") as sb:
url = "https://www.nike.com/"
sb.activate_cdp_mode(url)
- sb.cdp.add_handler(mycdp.network.RequestWillBeSent, send_handler)
- sb.cdp.add_handler(mycdp.network.ResponseReceived, receive_handler)
+ sb.add_handler(mycdp.network.RequestWillBeSent, send_handler)
+ sb.add_handler(mycdp.network.ResponseReceived, receive_handler)
sb.sleep(2.5)
sb.click('[data-testid="user-tools-container"] search')
sb.sleep(1.5)
@@ -41,4 +41,3 @@ async def receive_handler(event: mycdp.network.ResponseReceived):
print('**** Found results for "%s": ****' % search)
for element in elements:
print("* " + element.text)
- sb.sleep(2)
diff --git a/examples/cdp_mode/raw_seatgeek.py b/examples/cdp_mode/raw_seatgeek.py
index 892d988c78f..5059ab1d8da 100644
--- a/examples/cdp_mode/raw_seatgeek.py
+++ b/examples/cdp_mode/raw_seatgeek.py
@@ -8,9 +8,9 @@
sb.sleep(1.6)
query = "Jerry Seinfeld"
sb.press_keys(input_field, query)
- sb.sleep(1.6)
+ sb.sleep(1.8)
sb.click("li#active-result-item")
- sb.sleep(4.2)
+ sb.sleep(4.4)
print('*** SeatGeek Search for "%s":' % query)
item_selector = '[data-testid="listing-item"]'
for item in sb.find_elements(item_selector):
diff --git a/examples/cdp_mode/raw_southwest.py b/examples/cdp_mode/raw_southwest.py
index 7a2537f6c77..ef0d99e85c2 100644
--- a/examples/cdp_mode/raw_southwest.py
+++ b/examples/cdp_mode/raw_southwest.py
@@ -6,35 +6,35 @@
sb.sleep(2.8)
origin = "BOS"
destination = "MDW"
- sb.cdp.click_if_visible("button#onetrust-accept-btn-handler")
+ sb.click_if_visible("button#onetrust-accept-btn-handler")
sb.sleep(0.5)
- sb.cdp.gui_click_element("input#originationAirportCode")
+ sb.gui_click_element("input#originationAirportCode")
sb.sleep(0.2)
- sb.cdp.select("input#originationAirportCode").clear_input()
+ sb.select("input#originationAirportCode").clear_input()
sb.sleep(0.2)
sb.uc_gui_press_keys(" " + "\n")
sb.sleep(0.5)
- sb.cdp.gui_click_element("input#originationAirportCode")
+ sb.gui_click_element("input#originationAirportCode")
sb.sleep(0.4)
sb.uc_gui_press_keys(origin + "\n")
sb.sleep(0.4)
- sb.cdp.gui_click_element("h1")
+ sb.gui_click_element("h1")
sb.sleep(0.3)
- sb.cdp.gui_click_element("input#destinationAirportCode")
+ sb.gui_click_element("input#destinationAirportCode")
sb.sleep(0.2)
- sb.cdp.select("input#destinationAirportCode").clear_input()
+ sb.select("input#destinationAirportCode").clear_input()
sb.sleep(0.2)
sb.uc_gui_press_keys(destination + "\n")
sb.sleep(0.4)
- sb.cdp.gui_click_element("h1")
+ sb.gui_click_element("h1")
sb.sleep(0.2)
- sb.cdp.click_if_visible("button#onetrust-accept-btn-handler")
+ sb.click_if_visible("button#onetrust-accept-btn-handler")
sb.sleep(0.1)
- sb.cdp.click('form button[data-test="submitField"]')
+ sb.click('form button[data-test="submitField"]')
sb.sleep(2.5)
- sb.cdp.click('button[aria-labelledby*="nearby-airport-drawer-"]')
+ sb.click('button[aria-labelledby*="nearby-airport-drawer-"]')
sb.sleep(4)
- day = sb.cdp.get_text('[aria-current="true"] span[class*="cal"]')
+ day = sb.get_text('[aria-current="true"] span[class*="cal"]')
print("**** Flights from %s to %s ****" % (origin, destination))
flights = sb.find_elements("li.air-booking-select-detail")
for flight in flights:
diff --git a/examples/cdp_mode/raw_timezone_sb.py b/examples/cdp_mode/raw_timezone_sb.py
index c9d3cbb93d2..57d6d0e983d 100644
--- a/examples/cdp_mode/raw_timezone_sb.py
+++ b/examples/cdp_mode/raw_timezone_sb.py
@@ -6,6 +6,6 @@
sb.activate_cdp_mode(url, tzone="Asia/Kolkata", geoloc=(26.863, 80.94))
sb.remove_elements("#right-sidebar")
sb.sleep(5)
- sb.cdp.open(url, tzone="Asia/Tokyo", geoloc=(35.050681, 136.844728))
+ sb.open(url, tzone="Asia/Tokyo", geoloc=(35.050681, 136.844728))
sb.remove_elements("#right-sidebar")
sb.sleep(5)
diff --git a/examples/cdp_mode/raw_trails.py b/examples/cdp_mode/raw_trails.py
index b43bc3d4510..8c8f87e1fd0 100644
--- a/examples/cdp_mode/raw_trails.py
+++ b/examples/cdp_mode/raw_trails.py
@@ -16,15 +16,13 @@
sb.sleep(3.5)
sb.click('button:contains("more")')
sb.sleep(0.7)
- sb.click_if_visible('button[data-testid="modal-close"]')
- sb.sleep(0.7)
print("Description: (%s)\n" % sb.get_text("h1"))
print(sb.get_text('div[class*="Description_description"]'))
sb.scroll_to_bottom()
sb.sleep(1.5)
- sb.click_if_visible('button[data-testid="modal-close"]')
+ sb.click_if_visible('[aria-label="Close"]')
sb.sleep(1.2)
- summary = '[class*="ReviewSummary_summary"] span'
+ summary = '[class*="ReviewSummary"] span'
print("\nReview Summary:\n\n%s" % sb.get_text(summary))
reviews = sb.select_all('p[class*="styles_reviewText"]')
print("\nReviews:")
@@ -33,6 +31,8 @@
folder = "images_exported"
file_name = "thundering_brook_falls.png"
sb.scroll_to_top()
+ sb.sleep(0.3)
+ sb.click_if_visible('[aria-label="Close"]')
sb.sleep(1.2)
sb.save_screenshot(file_name, folder, selector="body")
print('\n"./%s/%s" was saved!' % (folder, file_name))
diff --git a/examples/cdp_mode/raw_walmart.py b/examples/cdp_mode/raw_walmart.py
index 39eeb09bdc1..1fccb4071fb 100644
--- a/examples/cdp_mode/raw_walmart.py
+++ b/examples/cdp_mode/raw_walmart.py
@@ -6,7 +6,7 @@
sb.sleep(1.8)
continue_button = 'button:contains("Continue shopping")'
if sb.is_element_visible(continue_button):
- sb.cdp.gui_click_element(continue_button)
+ sb.gui_click_element(continue_button)
sb.sleep(0.6)
sb.click('input[aria-label="Search"]')
sb.sleep(1.2)
@@ -15,10 +15,10 @@
sb.press_keys('input[aria-label="Search"]', search + "\n")
sb.sleep(3.8)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 7.2)
+ sb.gui_click_and_hold("#px-captcha", 7.2)
sb.sleep(4.2)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 4.2)
+ sb.gui_click_and_hold("#px-captcha", 4.2)
sb.sleep(3.2)
sb.remove_elements('[data-testid="skyline-ad"]')
sb.remove_elements('[data-testid="sba-container"]')
diff --git a/examples/cdp_mode/raw_xhr_sb.py b/examples/cdp_mode/raw_xhr_sb.py
index 093d188978a..229cd65fbfd 100644
--- a/examples/cdp_mode/raw_xhr_sb.py
+++ b/examples/cdp_mode/raw_xhr_sb.py
@@ -62,12 +62,12 @@ async def receiveXHR(page, requests):
listenXHR(tab)
# Change url to something that makes ajax requests
- sb.cdp.open("https://learn.microsoft.com/en-us/")
+ sb.open("https://learn.microsoft.com/en-us/")
time.sleep(1)
for i in range(9):
- sb.cdp.scroll_down(6)
+ sb.scroll_down(6)
- loop = sb.cdp.get_event_loop()
+ loop = sb.get_event_loop()
xhr_responses = loop.run_until_complete(receiveXHR(tab, xhr_requests))
for response in xhr_responses:
print(c1 + "*** ==> XHR Request URL <== ***" + cr)
From 986ee70062550b06ceb3e96a51dfcf06950a7460 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:34:24 -0400
Subject: [PATCH 06/11] Update examples
---
examples/hack_the_planet.py | 24 ++------
examples/presenter/uc_presentation_4.py | 80 +++++++++++--------------
examples/presenter/uc_presentation_5.py | 2 +-
examples/raw_recaptcha.py | 4 +-
examples/raw_turnstile.py | 4 +-
5 files changed, 47 insertions(+), 67 deletions(-)
diff --git a/examples/hack_the_planet.py b/examples/hack_the_planet.py
index d33c2697a51..f9d77322094 100644
--- a/examples/hack_the_planet.py
+++ b/examples/hack_the_planet.py
@@ -85,7 +85,7 @@ def test_all_your_base_are_belong_to_us(self):
self.highlight('a[href*="google.com/img"]', loops=3)
self.highlight('form[role="search"]', loops=8)
- self.open("https://github.com/features/actions")
+ self.open("https://github.com/solutions/use-case/devops")
self.set_text_content("#hero-section-brand-heading", aybabtu)
self.highlight("#hero-section-brand-heading", loops=14, scroll=False)
@@ -172,23 +172,12 @@ def test_all_your_base_are_belong_to_us(self):
self.highlight("div.intro-title", loops=8, scroll=False)
self.highlight("h4", loops=8, scroll=False)
- self.open("https://slack.com/help/articles/204714258-Giphy-for-Slack")
+ self.open(
+ "https://slack.com/help/articles/204379773-Upload-a-Slack-icon"
+ )
self.set_text_content("h1", aybabtu)
- self.set_text_content('a[prettyslug="getting-started"]', "ALL")
- self.set_text_content('a[prettyslug="using-slack"]', "YOUR")
- self.set_text_content('a[prettyslug="your-profile"]', "BASE")
- self.set_text_content('a[prettyslug="connect-tools"]', "ARE")
- self.set_text_content('a[prettyslug="administration"]', "BELONG")
- self.set_text_content('a[prettyslug*="tutorials"]', "TO US")
self.set_text_content("h1.article_title", aybabtu)
self.highlight("h1", loops=4, scroll=False)
- self.highlight("div#global_menu", loops=2, scroll=False)
- self.highlight('a[prettyslug*="g-started"]', loops=1, scroll=False)
- self.highlight('a[prettyslug="using-slack"]', loops=1, scroll=False)
- self.highlight('a[prettyslug="your-profile"]', loops=2, scroll=False)
- self.highlight('a[prettyslug="connect-tools"]', loops=1, scroll=False)
- self.highlight('a[prettyslug="administration"]', loops=1, scroll=False)
- self.highlight('a[prettyslug*="tutorials"]', loops=2, scroll=False)
self.highlight("h1.article_title", loops=5, scroll=False)
self.open("https://kubernetes.io/")
@@ -198,8 +187,7 @@ def test_all_your_base_are_belong_to_us(self):
self.set_text_content('nav a[href="/careers/"]', "ARE")
self.set_text_content('nav a[href="/partners/"]', "BELONG")
self.set_text_content('nav a[href="/community/"]', "TO")
- self.set_text_content("nav #navbarDropdown", "US")
- self.set_text_content("nav #navbarDropdownMenuLink", ".")
+ self.set_text_content("nav a.dropdown-toggle", "US")
if self.is_element_visible("h1"):
self.set_text_content("h1", aybabtu)
self.highlight("nav ul.navbar-nav", loops=3, scroll=False)
@@ -209,7 +197,7 @@ def test_all_your_base_are_belong_to_us(self):
self.highlight('nav a[href="/careers/"]', loops=1, scroll=False)
self.highlight('nav a[href="/partners/"]', loops=1, scroll=False)
self.highlight('nav a[href="/community/"]', loops=1, scroll=False)
- self.highlight("nav #navbarDropdown", loops=2, scroll=False)
+ self.highlight("nav a.dropdown-toggle", loops=2, scroll=False)
if self.is_element_visible("h1"):
self.highlight("h1", loops=6, scroll=False)
diff --git a/examples/presenter/uc_presentation_4.py b/examples/presenter/uc_presentation_4.py
index 09bc30ee89a..e7ff50083ba 100644
--- a/examples/presenter/uc_presentation_4.py
+++ b/examples/presenter/uc_presentation_4.py
@@ -475,28 +475,26 @@ def test_presentation_4(self):
sb.scroll_into_view("a#advSearch")
sb.sleep(0.7)
sb.click("a#advSearch")
- sb.sleep(0.5)
- sb.cdp.click("a#advSearch")
sb.sleep(1.2)
- sb.cdp.click('img[src*="img/pokedex/detail/025.png"]')
- sb.cdp.assert_text("Pikachu", 'div[class*="title"]')
- sb.cdp.assert_element('img[alt="Pikachu"]')
- sb.cdp.scroll_into_view("div.pokemon-ability-info")
+ sb.click('img[src*="img/pokedex/detail/025.png"]')
+ sb.assert_text("Pikachu", 'div[class*="title"]')
+ sb.assert_element('img[alt="Pikachu"]')
+ sb.scroll_into_view("div.pokemon-ability-info")
sb.sleep(1.2)
- sb.cdp.flash('div[class*="title"]')
- sb.cdp.flash('img[alt="Pikachu"]')
- sb.cdp.flash("div.pokemon-ability-info")
- name = sb.cdp.get_text("label.styled-select")
- info = sb.cdp.get_text("div.version-descriptions p.active")
+ sb.flash('div[class*="title"]')
+ sb.flash('img[alt="Pikachu"]')
+ sb.flash("div.pokemon-ability-info")
+ name = sb.get_text("label.styled-select")
+ info = sb.get_text("div.version-descriptions p.active")
print("*** %s: ***\n* %s" % (name, info))
sb.sleep(2)
- sb.cdp.highlight_overlay("div.pokemon-ability-info")
+ sb.highlight_overlay("div.pokemon-ability-info")
sb.sleep(2)
- sb.cdp.open("https://events.pokemon.com/EventLocator/")
+ sb.open("https://events.pokemon.com/EventLocator/")
sb.sleep(2)
- sb.cdp.click('span:contains("Championship")')
+ sb.click('span:contains("Championship")')
sb.sleep(2)
- events = sb.cdp.select_all("div.event-info__title")
+ events = sb.select_all("div.event-info__title")
print("*** PokΓ©mon Championship Events: ***")
for event in events:
print("* " + event.text)
@@ -518,7 +516,7 @@ def test_presentation_4(self):
sb.sleep(1.8)
continue_button = 'button:contains("Continue shopping")'
if sb.is_element_visible(continue_button):
- sb.cdp.gui_click_element(continue_button)
+ sb.gui_click_element(continue_button)
sb.sleep(0.6)
sb.click('input[aria-label="Search"]')
sb.sleep(1.2)
@@ -527,10 +525,10 @@ def test_presentation_4(self):
sb.press_keys('input[aria-label="Search"]', search + "\n")
sb.sleep(3.8)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 7.2)
+ sb.gui_click_and_hold("#px-captcha", 7.2)
sb.sleep(3.2)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 4.2)
+ sb.gui_click_and_hold("#px-captcha", 4.2)
sb.sleep(3.2)
sb.remove_elements('[data-testid="skyline-ad"]')
sb.remove_elements('[data-testid="sba-container"]')
@@ -617,37 +615,33 @@ def test_presentation_4(self):
with SB(uc=True, test=True, locale="en", ad_block=True) as sb:
url = "https://www.easyjet.com/en/"
sb.activate_cdp_mode(url)
- sb.sleep(2)
- sb.click_if_visible("button#ensCloseBanner")
- sb.sleep(1.2)
+ sb.sleep(1.5)
+ sb.click_if_visible("button#ensRejectAds", timeout=2)
+ sb.sleep(1)
sb.click('input[name="from"]')
- sb.sleep(1.2)
+ sb.sleep(1)
sb.type('input[name="from"]', "London Gatwick")
- sb.sleep(0.6)
- sb.click_if_visible("button#ensCloseBanner")
- sb.sleep(0.6)
+ sb.sleep(1)
sb.click('span[data-testid="airport-name"]')
- sb.sleep(1.2)
+ sb.sleep(1)
sb.type('input[name="to"]', "Paris")
- sb.sleep(1.2)
+ sb.sleep(1)
sb.click('span[data-testid="airport-name"]')
- sb.sleep(1.2)
+ sb.sleep(1)
sb.click('input[name="when"]')
- sb.sleep(1.2)
- sb.cdp.click(
- '[data-testid="month"]:last-of-type'
- ' [aria-disabled="false"]'
+ sb.sleep(1)
+ sb.click(
+ '[data-testid="month"]:last-of-type [aria-disabled="false"]'
)
- sb.sleep(1.2)
+ sb.sleep(1)
sb.click(
- '[data-testid="month"]:last-of-type'
- ' [aria-disabled="false"]'
+ '[data-testid="month"]:last-of-type [aria-disabled="false"]'
)
- sb.sleep(1.2)
+ sb.sleep(1)
sb.click('button[data-testid="submit"]')
- sb.sleep(3.5)
+ sb.sleep(4)
sb.connect()
- sb.sleep(4.2)
+ sb.sleep(1)
for window in sb.driver.window_handles:
sb.switch_to_window(window)
if "/buy/flights" in sb.get_current_url():
@@ -657,9 +651,7 @@ def test_presentation_4(self):
for day in days:
if not day.text.strip():
continue
- print(
- "\n\n**** " + " ".join(day.text.split("\n")[0:2]) + " ****"
- )
+ print("**** " + " ".join(day.text.split("\n")[0:2]) + " ****")
fares = day.find_elements(
"css selector", 'button[class*="flightDet"]'
)
@@ -793,9 +785,9 @@ def test_presentation_4(self):
sb.sleep(0.6)
sb.click('form button[type="submit"]')
sb.sleep(4.8)
- if len(sb.cdp.get_tabs()) > 1:
- sb.cdp.close_active_tab()
- sb.cdp.switch_to_newest_tab()
+ if len(sb.get_tabs()) > 1:
+ sb.close_active_tab()
+ sb.switch_to_newest_tab()
sb.sleep(0.6)
sb.sleep(0.8)
for y in range(1, 9):
diff --git a/examples/presenter/uc_presentation_5.py b/examples/presenter/uc_presentation_5.py
index 6fd08a40d1b..e9b150876ab 100644
--- a/examples/presenter/uc_presentation_5.py
+++ b/examples/presenter/uc_presentation_5.py
@@ -522,7 +522,7 @@ def test_presentation_5(self):
' sb.sleep(3)'
'\n'
' for i in range(16):\n'
- ' sb.cdp.scroll_down(16)\n'
+ ' sb.scroll_down(16)\n'
' print(sb.get_page_title())\n'
' sb.save_as_pdf_to_logs()\n'
' sb.save_page_source_to_logs()\n'
diff --git a/examples/raw_recaptcha.py b/examples/raw_recaptcha.py
index 86cb4c1a6d1..2ae7f9939dd 100644
--- a/examples/raw_recaptcha.py
+++ b/examples/raw_recaptcha.py
@@ -1,9 +1,9 @@
from seleniumbase import SB
-with SB(uc=True, test=True, incognito=True) as sb:
+with SB(uc=True, test=True) as sb:
url = "https://seleniumbase.io/apps/recaptcha"
sb.activate_cdp_mode(url)
- sb.uc_gui_click_captcha('iframe[src*="/recaptcha/"]')
+ sb.solve_captcha()
sb.assert_element("img#captcha-success", timeout=3)
sb.set_messenger_theme(location="top_left")
sb.post_message("SeleniumBase wasn't detected", duration=3)
diff --git a/examples/raw_turnstile.py b/examples/raw_turnstile.py
index 9b907ae4397..e811c8ceb32 100644
--- a/examples/raw_turnstile.py
+++ b/examples/raw_turnstile.py
@@ -2,8 +2,8 @@
with SB(uc=True, test=True) as sb:
url = "https://seleniumbase.io/apps/turnstile"
- sb.uc_open_with_reconnect(url)
- sb.uc_gui_click_captcha()
+ sb.activate_cdp_mode(url)
+ sb.solve_captcha()
sb.assert_element("img#captcha-success", timeout=3)
sb.set_messenger_theme(location="top_left")
sb.post_message("SeleniumBase wasn't detected", duration=3)
From c78890a265e1e81a32c71c89c5d9f0d9de2b563e Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:41:03 -0400
Subject: [PATCH 07/11] Refresh Python dependencies
---
requirements.txt | 2 +-
setup.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/requirements.txt b/requirements.txt
index 78b4ca4e175..95f16b14b5f 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -30,7 +30,7 @@ pygments>=2.20.0
pyreadline3>=3.5.4;platform_system=="Windows"
tabcompleter>=1.4.1
pdbp>=1.8.2
-idna>=3.15
+idna>=3.16
charset-normalizer>=3.4.7,<4
urllib3>=1.26.20,<2;python_version<"3.10"
urllib3>=2.7.0,<3;python_version>="3.10"
diff --git a/setup.py b/setup.py
index 8b2a812d886..6b9fa500cec 100755
--- a/setup.py
+++ b/setup.py
@@ -193,7 +193,7 @@
'pyreadline3>=3.5.4;platform_system=="Windows"',
'tabcompleter>=1.4.1',
'pdbp>=1.8.2',
- 'idna>=3.15',
+ 'idna>=3.16',
'charset-normalizer>=3.4.7,<4',
'urllib3>=1.26.20,<2;python_version<"3.10"',
'urllib3>=2.7.0,<3;python_version>="3.10"',
From 13b0121d5ef56a4f24863688d916e2e9e5c395d8 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:41:48 -0400
Subject: [PATCH 08/11] Update mkdocs.yml
---
mkdocs.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mkdocs.yml b/mkdocs.yml
index 77e7b27d757..04e5465ade6 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -96,20 +96,20 @@ nav:
- π Stealthy Playwright: examples/cdp_mode/playwright/ReadMe.md
- π Running Example Tests: examples/ReadMe.md
- ποΈ Command Line Options: help_docs/customizing_test_runs.md
- - πͺ Console Scripts: seleniumbase/console_scripts/ReadMe.md
+ - π» Console Scripts: seleniumbase/console_scripts/ReadMe.md
- π Dashboard / Reports: examples/example_logs/ReadMe.md
- π Syntax Formats: help_docs/syntax_formats.md
- ποΈ GUI / Commander: help_docs/commander.md
- π΄ Recorder Mode: help_docs/recorder_mode.md
- - π API Reference: help_docs/method_summary.md
- - π CDP Mode APIs: help_docs/cdp_mode_methods.md
+ - π API Reference: help_docs/method_summary.md
+ - π CDP Mode APIs: help_docs/cdp_mode_methods.md
- Python Setup / Install:
- π Get Python, pip, & git: help_docs/install_python_pip_git.md
- βοΈ Virtualenv Instructions: help_docs/virtualenv_instructions.md
- π Install SeleniumBase: help_docs/install.md
- ποΈ How it Works: help_docs/how_it_works.md
- JS Manager / JS Tools:
- - βοΈ JS Package Manager: help_docs/js_package_manager.md
+ - π¨ JS Package Manager: help_docs/js_package_manager.md
- π¦ Demo Mode: help_docs/demo_mode.md
- π Tour Maker: examples/tour_examples/ReadMe.md
- π Dialog Boxes: examples/dialog_boxes/ReadMe.md
From b0c00f3ca01def3c77540a10d259730b0616b922 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:44:21 -0400
Subject: [PATCH 09/11] Update the docs
---
README.md | 52 +++++++++++++++++++++++++++++------
help_docs/cdp_mode_methods.md | 10 +++----
help_docs/method_summary.md | 7 +++--
3 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index a27abd4eb35..746f539c16d 100755
--- a/README.md
+++ b/README.md
@@ -50,9 +50,40 @@
-π CDP Mode bypasses bot-detection and handles CAPTCHAs by driving the browser directly through the Chrome DevTools Protocol. Includes Stealthy Playwright Mode, which extends these advanced anti-detection patches to Playwright scripts.
+π CDP Mode bypasses bot-detection and handles CAPTCHAs with the Chrome DevTools Protocol. Includes Stealthy Playwright Mode, which extends CDP Mode's anti-detection to Playwright scripts. sb.solve_captcha() handles CAPTCHAs that aren't bypassed automatically.
-π The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder includes over 100 ready-to-run examples of E2E testing. Examples that start with `test_` or end with `_test.py`/`_tests.py` are specifically designed to run with `pytest`. Other examples run directly with raw `python` (those files generally start with `raw_` to avoid confusion).
+Python sync version of SeleniumBase's CDP Mode: (sb_cdp)
+
+```python
+from seleniumbase import sb_cdp
+
+sb = sb_cdp.Chrome()
+sb.open("https://demo.fingerprint.com/playground")
+sb.sleep(3)
+sb.driver.quit()
+```
+
+Playwright can use SeleniumBase's stealth browser:
+
+```python
+from playwright.sync_api import sync_playwright
+from seleniumbase import sb_cdp
+
+sb = sb_cdp.Chrome()
+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://browserscan.net/bot-detection")
+
+sb.sleep(3)
+sb.driver.quit()
+```
+
+--------
+
+π The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/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).
π₯· Stealthy CDP Mode examples are located in [./examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
@@ -73,12 +104,12 @@
```python
from seleniumbase import sb_cdp
-url = "https://www.browserscan.net/bot-detection"
-sb = sb_cdp.Chrome(url, locale="en", ad_block=True)
-sb.flash("Test Results", duration=3, pause=1)
+sb = sb_cdp.Chrome(locale="en", ad_block=True)
+sb.open("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")', duration=3, pause=2)
+sb.flash('strong:contains("Normal")', pause=1)
```
@@ -95,15 +126,18 @@ 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://www.browserscan.net/bot-detection")
+ page.goto("https://browserscan.net/bot-detection")
page.wait_for_timeout(500)
- sb.flash("Test Results", duration=3, pause=1)
+ sb.flash("Test Results", duration=1.5, pause=0.5)
sb.assert_element('strong:contains("Normal")')
- sb.flash('strong:contains("Normal")', duration=3, pause=2)
+ print("Bot Not Detected")
+ sb.flash('strong:contains("Normal")', pause=1)
```
--------
+π CLI Options for Supported Chromium Browsers
+
π‘ You can set which Chromium browser to use via command-line options:
```zsh
diff --git a/help_docs/cdp_mode_methods.md b/help_docs/cdp_mode_methods.md
index 273e6441540..ed2a65bec96 100644
--- a/help_docs/cdp_mode_methods.md
+++ b/help_docs/cdp_mode_methods.md
@@ -9,6 +9,7 @@ Here's a list of SeleniumBase CDP Mode method definitions, which are defined in
```python
sb.cdp.get(url, **kwargs)
sb.cdp.open(url, **kwargs) # Same as sb.cdp.get(url, **kwargs)
+sb.cdp.goto(url, **kwargs) # Same as sb.cdp.get(url, **kwargs)
sb.cdp.reload(ignore_cache=True, script_to_evaluate_on_load=None)
sb.cdp.refresh(*args, **kwargs)
sb.cdp.get_event_loop()
@@ -276,7 +277,8 @@ Methods: (Sometimes `tab` is named `page` in examples)
```python
await tab.get(url="about:blank")
-await tab.open(url="about:blank")
+await tab.open(url="about:blank") # Same as tab.open()
+await tab.goto(url="about:blank") # Same as tab.open()
await tab.find(text, best_match=False, timeout=10) # text can be selector
await tab.find_all(text, timeout=10) # text can be selector
await tab.select(selector, timeout=10)
@@ -300,8 +302,7 @@ await tab.set_window_size(left=0, top=0, width=1280, height=1024)
await tab.set_window_rect(left=0, top=0, width=1280, height=1024)
await tab.activate()
await tab.bring_to_front()
-await tab.set_window_state(
- left=0, top=0, width=1280, height=720, state="normal")
+await tab.set_window_state(left=0, top=0, width=1280, height=720, state="normal")
await tab.get_navigation_history()
await tab.get_user_agent()
await tab.get_cookie_string()
@@ -315,8 +316,7 @@ await tab.wait_for(selector="", text="", timeout=10)
await tab.set_attributes(selector, attribute, value)
await tab.internalize_links()
await tab.download_file(url, filename=None)
-await tab.save_screenshot(
- filename="auto", format="png", full_page=False)
+await tab.save_screenshot(filename="auto", format="png", full_page=False)
await tab.print_to_pdf(filename="auto")
await tab.set_download_path(path)
await tab.get_all_linked_sources()
diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md
index fc3894bda9f..39e5828074d 100644
--- a/help_docs/method_summary.md
+++ b/help_docs/method_summary.md
@@ -521,6 +521,7 @@ self.generate_traffic_chain(pages, loops=1)
############
+self.select(selector, by="css selector", timeout=None)
self.get_element(selector, by="css selector", timeout=None)
# Duplicates:
# self.wait_for_selector(selector, by="css selector", timeout=None)
@@ -707,6 +708,7 @@ self.uc_gui_handle_captcha(frame="iframe")
driver.default_get(url) # Because driver.get(url) works differently in UC Mode
driver.open(url) # Like driver.get(), but allows partial URLs without protocol
+driver.goto(url) # Same as driver.open(url)
driver.click(selector)
driver.click_link(link_text)
driver.click_if_visible(selector)
@@ -722,6 +724,8 @@ driver.assert_text(text, selector)
driver.assert_exact_text(text, selector)
driver.find_element(selector)
driver.find_elements(selector)
+driver.select(selector)
+driver.select_all(selector)
driver.wait_for_element(selector)
driver.wait_for_element_visible(selector)
driver.wait_for_element_present(selector)
@@ -751,12 +755,11 @@ driver.get_parent(element)
driver.get_current_url()
driver.get_page_source()
driver.get_title()
+driver.switch_to_newest_tab()
driver.switch_to_frame(frame="iframe")
driver.is_cdp_mode_active()
driver.is_connected() # UC / CDP Mode can disconnect WebDriver
-############
-
# "driver"-specific methods added (or modified) by SeleniumBase for UC Mode:
driver.get(url) # If UC Mode and site detects bots, then uc_open_with_tab(url)
From ad78005b2a13d1dd2df9dcb7ef3201cab58c0b5c Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 20:44:50 -0400
Subject: [PATCH 10/11] Version 4.49.2
---
seleniumbase/__version__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py
index 4c0c2d16a1f..4a61993721b 100755
--- a/seleniumbase/__version__.py
+++ b/seleniumbase/__version__.py
@@ -1,2 +1,2 @@
# seleniumbase package
-__version__ = "4.49.1"
+__version__ = "4.49.2"
From d253cc033f37c9c05eed5472ec79377ed704dc5d Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 21 May 2026 21:10:25 -0400
Subject: [PATCH 11/11] Update examples
---
examples/cdp_mode/ReadMe.md | 14 +++++++-------
examples/cdp_mode/raw_req_mod.py | 6 +++---
examples/cdp_mode/raw_res_sb.py | 4 ++--
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md
index d92d723b8bf..711ee34d27e 100644
--- a/examples/cdp_mode/ReadMe.md
+++ b/examples/cdp_mode/ReadMe.md
@@ -186,10 +186,10 @@ with SB(uc=True, test=True, locale="en", ad_block=True) as sb:
```python
from seleniumbase import SB
-with SB(uc=True, test=True, locale="en") as sb:
+with SB(uc=True, test=True, locale="en", guest=True) as sb:
url = "https://www.hyatt.com/"
sb.activate_cdp_mode(url)
- sb.sleep(3.2)
+ sb.sleep(3.4)
sb.click_if_visible('button[aria-label="Close"]')
sb.sleep(0.1)
sb.click_if_visible("#onetrust-reject-all-handler")
@@ -200,11 +200,11 @@ with SB(uc=True, test=True, locale="en") as sb:
sb.click('li[data-js="suggestion"]')
sb.sleep(0.6)
sb.click_if_visible('button[aria-label="Close"]')
- sb.sleep(0.6)
+ sb.sleep(0.8)
sb.click("button.be-button-shop")
sb.sleep(1)
sb.click_if_visible('[label="Find Hotels"]')
- sb.sleep(5)
+ sb.sleep(5.5)
card_info = 'div[data-booking-status="BOOKABLE"] [class*="HotelCard_info"]'
hotels = sb.select_all(card_info)
print("Hyatt Hotels in %s:" % location)
@@ -285,7 +285,7 @@ with SB(uc=True, test=True, ad_block=True) as sb:
sb.sleep(1.8)
continue_button = 'button:contains("Continue shopping")'
if sb.is_element_visible(continue_button):
- sb.cdp.gui_click_element(continue_button)
+ sb.gui_click_element(continue_button)
sb.sleep(0.6)
sb.click('input[aria-label="Search"]')
sb.sleep(1.2)
@@ -294,10 +294,10 @@ with SB(uc=True, test=True, ad_block=True) as sb:
sb.press_keys('input[aria-label="Search"]', search + "\n")
sb.sleep(3.8)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 7.2)
+ sb.gui_click_and_hold("#px-captcha", 7.2)
sb.sleep(4.2)
if sb.is_element_visible("#px-captcha"):
- sb.cdp.gui_click_and_hold("#px-captcha", 4.2)
+ sb.gui_click_and_hold("#px-captcha", 4.2)
sb.sleep(3.2)
sb.remove_elements('[data-testid="skyline-ad"]')
sb.remove_elements('[data-testid="sba-container"]')
diff --git a/examples/cdp_mode/raw_req_mod.py b/examples/cdp_mode/raw_req_mod.py
index 1609f1e0c63..cc4bb0bdf6e 100644
--- a/examples/cdp_mode/raw_req_mod.py
+++ b/examples/cdp_mode/raw_req_mod.py
@@ -16,8 +16,8 @@ async def request_paused_handler(event, tab):
with SB(uc=True, test=True, locale="en", pls="none") as sb:
sb.activate_cdp_mode("about:blank")
- sb.cdp.add_handler(mycdp.fetch.RequestPaused, request_paused_handler)
- sb.cdp.open("https://gettyimages.com/photos/jonathan-frakes-cast-2022")
+ sb.add_handler(mycdp.fetch.RequestPaused, request_paused_handler)
+ sb.open("https://gettyimages.com/photos/jonathan-frakes-cast-2022")
new_size = "--width:100;--height:100;"
- sb.cdp.set_attributes('[style*="--width:"]', "style", new_size)
+ sb.set_attributes('[style*="--width:"]', "style", new_size)
sb.sleep(6)
diff --git a/examples/cdp_mode/raw_res_sb.py b/examples/cdp_mode/raw_res_sb.py
index 9bf17d1a327..da2e29f67b0 100644
--- a/examples/cdp_mode/raw_res_sb.py
+++ b/examples/cdp_mode/raw_res_sb.py
@@ -27,8 +27,8 @@ async def receive_handler(event: mycdp.network.ResponseReceived):
with SB(uc=True, test=True, locale="en") as sb:
sb.activate_cdp_mode("about:blank")
- sb.cdp.add_handler(mycdp.network.RequestWillBeSent, send_handler)
- sb.cdp.add_handler(mycdp.network.ResponseReceived, receive_handler)
+ sb.add_handler(mycdp.network.RequestWillBeSent, send_handler)
+ sb.add_handler(mycdp.network.ResponseReceived, receive_handler)
url = "https://seleniumbase.io/apps/calculator"
sb.open(url)
sb.sleep(1)