From 8c53566d845100501d0c96515101644eb4d19db8 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 11 Nov 2025 00:25:45 -0500 Subject: [PATCH 1/5] Update CDP Mode --- seleniumbase/core/browser_launcher.py | 13 +- seleniumbase/core/sb_cdp.py | 83 +++++------- seleniumbase/fixtures/base_case.py | 39 +++++- seleniumbase/undetected/cdp_driver/browser.py | 120 ++++++++++++------ .../undetected/cdp_driver/cdp_util.py | 3 +- .../undetected/cdp_driver/connection.py | 34 +---- seleniumbase/undetected/cdp_driver/tab.py | 32 ----- 7 files changed, 170 insertions(+), 154 deletions(-) diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 4802f0d21ba..bef9d0c2abf 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -938,6 +938,14 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs): driver.solve_captcha = CDPM.solve_captcha driver.find_element_by_text = CDPM.find_element_by_text driver._is_using_cdp = True + if ( + hasattr(sb_config, "_cdp_proxy") + and sb_config._cdp_proxy + and "@" in sb_config._cdp_proxy + ): + time.sleep(0.077) + loop.run_until_complete(page.wait(0.25)) + time.sleep(0.022) def uc_activate_cdp_mode(driver, url=None, **kwargs): @@ -2746,7 +2754,7 @@ def _set_chrome_options( d_f_string = ",".join(included_disabled_features) chrome_options.add_argument("--disable-features=%s" % d_f_string) chrome_options.add_argument("--enable-unsafe-extension-debugging") - if proxy_auth: + if proxy_string: chrome_options.add_argument("--test-type") if proxy_auth or sb_config._ext_dirs: if not is_using_uc(undetectable, browser_name): @@ -2770,7 +2778,7 @@ def _set_chrome_options( chrome_options.add_argument("--disable-popup-blocking") # Skip remaining options that trigger anti-bot services return chrome_options - if not proxy_auth: + if not proxy_string: chrome_options.add_argument("--test-type") chrome_options.add_argument("--log-level=3") chrome_options.add_argument("--no-first-run") @@ -5812,6 +5820,7 @@ def get_local_driver( driver, *args, **kwargs ) ) + driver.activate_cdp_mode = driver.uc_activate_cdp_mode driver.uc_open_with_cdp_mode = ( lambda *args, **kwargs: uc_open_with_cdp_mode( driver, *args, **kwargs diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py index 7041df57b08..c1b7078991b 100644 --- a/seleniumbase/core/sb_cdp.py +++ b/seleniumbase/core/sb_cdp.py @@ -1823,7 +1823,11 @@ def _on_a_cf_turnstile_page(self, source=None): time.sleep(0.2) source = self.get_page_source() if ( - 'data-callback="onCaptchaSuccess"' in source + ( + 'data-callback="onCaptchaSuccess"' in source + and not 'title="reCAPTCHA"' in source + and not 'id="recaptcha-token" in source' + ) or "/challenge-platform/scripts/" in source or 'id="challenge-widget-' in source or "challenges.cloudf" in source @@ -1836,13 +1840,19 @@ def _on_a_g_recaptcha_page(self, source=None): if not source or len(source) < 400: time.sleep(0.2) source = self.get_page_source() + self.loop.run_until_complete(self.page.wait(0.1)) if ( - 'id="recaptcha-token"' in source - or 'title="reCAPTCHA"' in source + ( + 'id="recaptcha-token"' in source + or 'title="reCAPTCHA"' in source + ) + and self.is_element_visible('iframe[title="reCAPTCHA"]') ): + self.loop.run_until_complete(self.page.wait(0.1)) return True elif "/recaptcha/api.js" in source: time.sleep(1.6) # Still loading + self.loop.run_until_complete(self.page.wait(0.1)) return True return False @@ -1852,8 +1862,10 @@ def __gui_click_recaptcha(self, use_cdp=False): selector = 'iframe[title="reCAPTCHA"]' else: return + time.sleep(0.25) + self.loop.run_until_complete(self.page.wait()) + time.sleep(0.25) with suppress(Exception): - time.sleep(0.08) element_rect = self.get_gui_element_rect(selector, timeout=1) e_x = element_rect["x"] e_y = element_rect["y"] @@ -1884,7 +1896,9 @@ def gui_click_captcha(self): def __click_captcha(self, use_cdp=False): """Uses PyAutoGUI unless use_cdp == True""" - self.sleep(0.056) + self.sleep(0.075) + self.loop.run_until_complete(self.page.wait()) + self.sleep(0.025) source = self.get_page_source() if self._on_a_cf_turnstile_page(source): pass @@ -1894,38 +1908,19 @@ def __click_captcha(self, use_cdp=False): else: return selector = None - if ( - self.is_element_present('[name*="cf-turnstile-"]') - and self.is_element_present("#challenge-form div > div") - ): + if self.is_element_present('[class="cf-turnstile"]'): + selector = '[class="cf-turnstile"]' + elif self.is_element_present("#challenge-form div > div"): selector = "#challenge-form div > div" - elif ( - self.is_element_present('[name*="cf-turnstile-"]') - and self.is_element_present( - '[style="display: grid;"] div div' - ) - ): + elif self.is_element_present('[style="display: grid;"] div div'): selector = '[style="display: grid;"] div div' - elif ( - self.is_element_present('[name*="cf-turnstile-"]') - and self.is_element_present("[class*=spacer] + div div") - ): + elif self.is_element_present("[class*=spacer] + div div"): selector = '[class*=spacer] + div div' - elif ( - self.is_element_present('[name*="cf-turnstile-"]') - and self.is_element_present(".spacer div:not([class])") - ): + elif self.is_element_present(".spacer div:not([class])"): selector = ".spacer div:not([class])" - elif ( - self.is_element_present('script[src*="challenges.c"]') - and self.is_element_present( - '[data-testid*="challenge-"] div' - ) - ): + elif self.is_element_present('[data-testid*="challenge-"] div'): selector = '[data-testid*="challenge-"] div' - elif self.is_element_present( - "div#turnstile-widget div:not([class])" - ): + elif self.is_element_present("div#turnstile-widget div:not([class])"): selector = "div#turnstile-widget div:not([class])" elif self.is_element_present("ngx-turnstile div:not([class])"): selector = "ngx-turnstile div:not([class])" @@ -1933,22 +1928,12 @@ 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('[src*="/turnstile/"]') - and self.is_element_present("form div:not(:has(*))") - ): + elif self.is_element_present("form div:not(:has(*))"): selector = "form div:not(:has(*))" - elif ( - self.is_element_present('[src*="/turnstile/"]') - and self.is_element_present( - "body > div#check > div:not([class])" - ) - ): + 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('[class="cf-turnstile"]'): - selector = '[class="cf-turnstile"]' elif self.is_element_present( '[id*="turnstile"] div:not([class])' ): @@ -2048,7 +2033,7 @@ def __click_captcha(self, use_cdp=False): self.loop.run_until_complete(self.page.evaluate(script)) self.loop.run_until_complete(self.page.wait()) with suppress(Exception): - time.sleep(0.08) + time.sleep(0.05) element_rect = self.get_gui_element_rect(selector, timeout=1) e_x = element_rect["x"] e_y = element_rect["y"] @@ -2059,15 +2044,17 @@ def __click_captcha(self, use_cdp=False): x = e_x + x_offset y = e_y + y_offset sb_config._saved_cf_x_y = (x, y) - time.sleep(0.08) + time.sleep(0.05) + if hasattr(sb_config, "_cdp_proxy") and sb_config._cdp_proxy: + time.sleep(0.22) # CAPTCHA may load slower with proxy if use_cdp: self.sleep(0.03) gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK) with gui_lock: # Prevent issues with multiple processes self.bring_active_window_to_front() - time.sleep(0.056) + time.sleep(0.05) self.click_with_offset(selector, x_offset, y_offset) - time.sleep(0.056) + time.sleep(0.05) else: self.gui_click_x_y(x, y) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 0c15b9f1460..4f6cbc36df2 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -227,6 +227,28 @@ def open(self, url): if self.__is_cdp_swap_needed(): self.cdp.open(url) return + elif ( + hasattr(self.driver, "_is_using_uc") + and self.driver._is_using_uc + and "@" in self.proxy_string + and ( + not hasattr(self.driver, "_is_using_cdp") + or not self.driver._is_using_cdp + ) + ): + # Auth in UC Mode requires CDP Mode + logging.info("UC Mode requires CDP Mode for auth. Activating now.") + self.activate_cdp_mode(url) + return + elif ( + hasattr(self.driver, "_is_using_uc") + and self.driver._is_using_uc + and hasattr(self.driver, "_is_using_cdp") + and self.driver._is_using_cdp + ): + self.disconnect() + self.cdp.open(url) + return self._check_browser() if self.__needs_minimum_wait(): time.sleep(0.04) @@ -5005,7 +5027,7 @@ def activate_cdp_mode(self, url=None, **kwargs): self.driver.connect() current_url = self.get_current_url() if not current_url.startswith(("about", "data", "chrome")): - self.open("about:blank") + self.driver.get("about:blank") self.driver.uc_open_with_cdp_mode(url, **kwargs) else: self.get_new_driver(undetectable=True) @@ -5015,6 +5037,13 @@ def activate_cdp_mode(self, url=None, **kwargs): self.solve_captcha = self.cdp.solve_captcha if hasattr(self.cdp, "find_element_by_text"): self.find_element_by_text = self.cdp.find_element_by_text + if ( + hasattr(sb_config, "_cdp_proxy") + and sb_config._cdp_proxy + and "@" in sb_config._cdp_proxy + ): + with suppress(Exception): + self.cdp.loop.run_until_complete(self.cdp.page.wait(0.25)) self.undetectable = True def activate_recorder(self): @@ -14527,7 +14556,8 @@ def __activate_virtual_display(self): sb_config._virtual_display = self._xvfb_display if "DISPLAY" not in os.environ.keys(): print( - "\nX11 display failed! Will use regular xvfb!" + "\n X11 display failed! Is Xvfb installed? " + "\n Try this: `sudo apt install -y xvfb`" ) self.__activate_standard_virtual_display() else: @@ -14540,7 +14570,10 @@ def __activate_virtual_display(self): print("\n" + str(e.msg)) else: print(e) - print("\nX11 display failed! Will use regular xvfb!") + print( + "\n X11 display failed! Is Xvfb installed? " + "\n Try this: `sudo apt install -y xvfb`" + ) self.__activate_standard_virtual_display() return pyautogui_is_installed = False diff --git a/seleniumbase/undetected/cdp_driver/browser.py b/seleniumbase/undetected/cdp_driver/browser.py index 12dbfd2a078..ad613edab0f 100644 --- a/seleniumbase/undetected/cdp_driver/browser.py +++ b/seleniumbase/undetected/cdp_driver/browser.py @@ -251,6 +251,36 @@ async def _handle_target_update( ) self.targets.remove(current_tab) + async def set_auth(self, username, password, tab): + async def auth_challenge_handler(event: cdp.fetch.AuthRequired): + await tab.send( + cdp.fetch.continue_with_auth( + request_id=event.request_id, + auth_challenge_response=cdp.fetch.AuthChallengeResponse( + response="ProvideCredentials", + username=username, + password=password, + ), + ) + ) + + async def req_paused(event: cdp.fetch.RequestPaused): + await tab.send( + cdp.fetch.continue_request(request_id=event.request_id) + ) + + tab.add_handler( + cdp.fetch.RequestPaused, + lambda event: asyncio.create_task(req_paused(event)), + ) + + tab.add_handler( + cdp.fetch.AuthRequired, + lambda event: asyncio.create_task(auth_challenge_handler(event)), + ) + + await tab.send(cdp.fetch.enable(handle_auth_requests=True)) + async def get( self, url="about:blank", @@ -341,66 +371,74 @@ async def get( _cdp_geolocation = kwargs["geoloc"] if "recorder" in kwargs: _cdp_recorder = kwargs["recorder"] + await connection.send(cdp.network.enable()) if _cdp_timezone: - await connection.send(cdp.page.navigate("about:blank")) await connection.set_timezone(_cdp_timezone) if _cdp_locale: await connection.set_locale(_cdp_locale) if _cdp_user_agent or _cdp_locale or _cdp_platform: - await connection.send(cdp.page.navigate("about:blank")) await connection.set_user_agent( user_agent=_cdp_user_agent, accept_language=_cdp_locale, platform=_cdp_platform, ) if _cdp_ad_block: - await connection.send(cdp.page.navigate("about:blank")) - await connection.send(cdp.network.enable()) await connection.send(cdp.network.set_blocked_urls( urls=[ - "*cloudflareinsights.com*", - "*googlesyndication.com*", - "*googletagmanager.com*", - "*google-analytics.com*", - "*amazon-adsystem.com*", - "*adsafeprotected.com*", - "*casalemedia.com*", - "*doubleclick.net*", - "*admanmedia.com*", - "*fastclick.net*", - "*snigelweb.com*", - "*bidswitch.net*", - "*pubmatic.com*", - "*ad.turn.com*", - "*adnxs.com*", - "*openx.net*", - "*tapad.com*", - "*3lift.com*", - "*2mdn.net*", + "*.cloudflareinsights.com*", + "*.googlesyndication.com*", + "*.googletagmanager.com*", + "*.google-analytics.com*", + "*.amazon-adsystem.com*", + "*.adsafeprotected.com*", + "*.ads.linkedin.com*", + "*.casalemedia.com*", + "*.doubleclick.net*", + "*.admanmedia.com*", + "*.quantserve.com*", + "*.fastclick.net*", + "*.snigelweb.com*", + "*.bidswitch.net*", + "*.360yield.com*", + "*.adthrive.com*", + "*.pubmatic.com*", + "*.id5-sync.com*", + "*.dotomi.com*", + "*.adsrvr.org*", + "*.atmtd.com*", + "*.liadm.com*", + "*.loopme.me*", + "*.adnxs.com*", + "*.openx.net*", + "*.tapad.com*", + "*.3lift.com*", + "*.turn.com*", + "*.2mdn.net*", + "*.cpx.to*", + "*.ad.gt*", ] )) if _cdp_geolocation: - await connection.send(cdp.page.navigate("about:blank")) await connection.set_geolocation(_cdp_geolocation) # (The code below is for the Chrome 142 extension fix) if ( hasattr(sb_config, "_cdp_proxy") - and "@" in sb_config._cdp_proxy and sb_config._cdp_proxy + and "@" in sb_config._cdp_proxy and "auth" not in kwargs ): username_and_password = sb_config._cdp_proxy.split("@")[0] proxy_user = username_and_password.split(":")[0] proxy_pass = username_and_password.split(":")[1] - await connection.set_auth(proxy_user, proxy_pass, self.tabs[0]) + await self.set_auth(proxy_user, proxy_pass, self.tabs[0]) time.sleep(0.25) if "auth" in kwargs and kwargs["auth"] and ":" in kwargs["auth"]: username_and_password = kwargs["auth"] proxy_user = username_and_password.split(":")[0] proxy_pass = username_and_password.split(":")[1] - await connection.set_auth(proxy_user, proxy_pass, self.tabs[0]) - time.sleep(0.22) - await connection.sleep(0.05) + await self.set_auth(proxy_user, proxy_pass, self.tabs[0]) + time.sleep(0.25) + await connection.sleep(0.15) frame_id, loader_id, *_ = await connection.send( cdp.page.navigate(url) ) @@ -415,6 +453,7 @@ async def get( connection.frame_id = frame_id connection.browser = self await connection.sleep(0.25) + await self.wait(0.05) return connection async def start(self=None) -> Browser: @@ -500,14 +539,23 @@ async def start(self=None) -> Browser: else: break if not self.info: - raise Exception( - ( - """ - -------------------------------- - Failed to connect to the browser - -------------------------------- - """ + chromium = "Chromium" + if hasattr(sb_config, "_cdp_browser") and sb_config._cdp_browser: + chromium = sb_config._cdp_browser + chromium = chromium[0].upper() + chromium[1:] + message = "Failed to connect to the browser" + if not exe or not os.path.exists(exe): + message = ( + "%s executable not found. Is it installed?" % chromium ) + dash_len = len(message) + dashes = "-" * dash_len + raise Exception( + """ + %s + %s + %s + """ % (dashes, message, dashes) ) self.connection = Connection( self.info.webSocketDebuggerUrl, _owner=self diff --git a/seleniumbase/undetected/cdp_driver/cdp_util.py b/seleniumbase/undetected/cdp_driver/cdp_util.py index 1d9894a7238..48bf6f2efbf 100644 --- a/seleniumbase/undetected/cdp_driver/cdp_util.py +++ b/seleniumbase/undetected/cdp_driver/cdp_util.py @@ -102,7 +102,8 @@ def __activate_virtual_display_as_needed( _xvfb_display.start() if "DISPLAY" not in os.environ.keys(): print( - "\nX11 display failed! Will use regular xvfb!" + "\n X11 display failed! Is Xvfb installed? " + "\n Try this: `sudo apt install -y xvfb`" ) __activate_standard_virtual_display() else: diff --git a/seleniumbase/undetected/cdp_driver/connection.py b/seleniumbase/undetected/cdp_driver/connection.py index 75c53adf969..35c83c22efb 100644 --- a/seleniumbase/undetected/cdp_driver/connection.py +++ b/seleniumbase/undetected/cdp_driver/connection.py @@ -370,8 +370,8 @@ async def set_user_agent( async def set_geolocation(self, geolocation: Optional[tuple] = None): """Sets the User Agent via set_geolocation_override.""" - await self.send(cdp.browser.grant_permissions( - permissions=["geolocation"], + await self.send(cdp.browser.set_permission( + permission={"name": "geolocation"}, setting="granted" )) await self.send(cdp.emulation.set_geolocation_override( latitude=geolocation[0], @@ -379,36 +379,6 @@ async def set_geolocation(self, geolocation: Optional[tuple] = None): accuracy=100, )) - async def set_auth(self, username, password, tab): - async def auth_challenge_handler(event: cdp.fetch.AuthRequired): - await tab.send( - cdp.fetch.continue_with_auth( - request_id=event.request_id, - auth_challenge_response=cdp.fetch.AuthChallengeResponse( - response="ProvideCredentials", - username=username, - password=password, - ), - ) - ) - - async def req_paused(event: cdp.fetch.RequestPaused): - await tab.send( - cdp.fetch.continue_request(request_id=event.request_id) - ) - - tab.add_handler( - cdp.fetch.RequestPaused, - lambda event: asyncio.create_task(req_paused(event)), - ) - - tab.add_handler( - cdp.fetch.AuthRequired, - lambda event: asyncio.create_task(auth_challenge_handler(event)), - ) - - await tab.send(cdp.fetch.enable(handle_auth_requests=True)) - def __getattr__(self, item): """:meta private:""" try: diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py index 3bef17d6055..948053baea5 100644 --- a/seleniumbase/undetected/cdp_driver/tab.py +++ b/seleniumbase/undetected/cdp_driver/tab.py @@ -317,33 +317,6 @@ async def select_all( await self.sleep(0.5) return items - async def ad_block(self): - await self.send(cdp.page.navigate("about:blank")) - await self.send(cdp.network.enable()) - await self.send(cdp.network.set_blocked_urls( - urls=[ - "*cloudflareinsights.com*", - "*googlesyndication.com*", - "*googletagmanager.com*", - "*google-analytics.com*", - "*amazon-adsystem.com*", - "*adsafeprotected.com*", - "*casalemedia.com*", - "*doubleclick.net*", - "*admanmedia.com*", - "*fastclick.net*", - "*snigelweb.com*", - "*bidswitch.net*", - "*pubmatic.com*", - "*ad.turn.com*", - "*adnxs.com*", - "*openx.net*", - "*tapad.com*", - "*3lift.com*", - "*2mdn.net*", - ] - )) - async def get( self, url="about:blank", @@ -361,9 +334,6 @@ async def get( :param new_window: open new window :return: Page """ - _cdp_ad_block = None - if hasattr(sb_config, "ad_block_on") and sb_config.ad_block_on: - _cdp_ad_block = sb_config.ad_block_on if not self.browser: raise AttributeError( "This page/tab has no browser attribute, " @@ -371,8 +341,6 @@ async def get( ) if new_window and not new_tab: new_tab = True - if _cdp_ad_block: - await self.ad_block() if new_tab: if hasattr(sb_config, "incognito") and sb_config.incognito: return await self.browser.get( From ab88595dc1e5c83e4a034c90c775f3b048ec5b58 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 11 Nov 2025 00:46:58 -0500 Subject: [PATCH 2/5] Fix previous commit --- seleniumbase/core/sb_cdp.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py index c1b7078991b..9ced97d5494 100644 --- a/seleniumbase/core/sb_cdp.py +++ b/seleniumbase/core/sb_cdp.py @@ -1825,8 +1825,8 @@ def _on_a_cf_turnstile_page(self, source=None): if ( ( 'data-callback="onCaptchaSuccess"' in source - and not 'title="reCAPTCHA"' in source - and not 'id="recaptcha-token" in source' + and 'title="reCAPTCHA"' not in source + and 'id="recaptcha-token"' not in source ) or "/challenge-platform/scripts/" in source or 'id="challenge-widget-' in source @@ -1837,10 +1837,9 @@ def _on_a_cf_turnstile_page(self, source=None): return False def _on_a_g_recaptcha_page(self, source=None): - if not source or len(source) < 400: - time.sleep(0.2) - source = self.get_page_source() - self.loop.run_until_complete(self.page.wait(0.1)) + time.sleep(0.25) + self.loop.run_until_complete(self.page.wait(0.25)) + source = self.get_page_source() if ( ( 'id="recaptcha-token"' in source From 8a0e53edf8c598be189633334185301076eff70b Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 11 Nov 2025 00:47:28 -0500 Subject: [PATCH 3/5] Update CDP Mode examples --- examples/cdp_mode/raw_ad_blocking.py | 18 +++++++++--------- examples/cdp_mode/raw_cdp_gitlab.py | 1 - examples/cdp_mode/raw_gitlab.py | 1 - examples/cdp_mode/raw_glassdoor.py | 2 +- examples/cdp_mode/raw_planetmc.py | 2 +- examples/cdp_mode/raw_science.py | 8 ++++---- examples/cdp_mode/raw_timezone.py | 1 - examples/cdp_mode/raw_timezone_sb.py | 2 -- 8 files changed, 15 insertions(+), 20 deletions(-) diff --git a/examples/cdp_mode/raw_ad_blocking.py b/examples/cdp_mode/raw_ad_blocking.py index 8d6f8a09c34..5d805388e12 100644 --- a/examples/cdp_mode/raw_ad_blocking.py +++ b/examples/cdp_mode/raw_ad_blocking.py @@ -7,15 +7,15 @@ async def block_urls(tab): await tab.send(mycdp.network.enable()) await tab.send(mycdp.network.set_blocked_urls( urls=[ - "*googlesyndication.com*", - "*googletagmanager.com*", - "*google-analytics.com*", - "*amazon-adsystem.com*", - "*adsafeprotected.com*", - "*doubleclick.net*", - "*fastclick.net*", - "*snigelweb.com*", - "*2mdn.net*", + "*.googlesyndication.com*", + "*.googletagmanager.com*", + "*.google-analytics.com*", + "*.amazon-adsystem.com*", + "*.adsafeprotected.com*", + "*.doubleclick.net*", + "*.fastclick.net*", + "*.snigelweb.com*", + "*.2mdn.net*", ] )) diff --git a/examples/cdp_mode/raw_cdp_gitlab.py b/examples/cdp_mode/raw_cdp_gitlab.py index d983b081253..da3da24c465 100644 --- a/examples/cdp_mode/raw_cdp_gitlab.py +++ b/examples/cdp_mode/raw_cdp_gitlab.py @@ -2,7 +2,6 @@ url = "https://gitlab.com/users/sign_in" sb = sb_cdp.Chrome(url, incognito=True) -sb.sleep(2.2) sb.solve_captcha() sb.highlight('h1:contains("GitLab")') sb.highlight('button:contains("Sign in")') diff --git a/examples/cdp_mode/raw_gitlab.py b/examples/cdp_mode/raw_gitlab.py index 0d9b6a1018d..95e0bef1277 100644 --- a/examples/cdp_mode/raw_gitlab.py +++ b/examples/cdp_mode/raw_gitlab.py @@ -3,7 +3,6 @@ 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) diff --git a/examples/cdp_mode/raw_glassdoor.py b/examples/cdp_mode/raw_glassdoor.py index f50fc0b6af8..7e586e97089 100644 --- a/examples/cdp_mode/raw_glassdoor.py +++ b/examples/cdp_mode/raw_glassdoor.py @@ -3,7 +3,7 @@ with SB(uc=True, test=True, ad_block=True) as sb: url = "https://www.glassdoor.com/Reviews/index.htm" sb.activate_cdp_mode(url) - sb.sleep(2.2) + sb.sleep(1.2) sb.solve_captcha() sb.highlight('[data-test="global-nav-glassdoor-logo"]') sb.highlight('[data-test="site-header-companies"]') diff --git a/examples/cdp_mode/raw_planetmc.py b/examples/cdp_mode/raw_planetmc.py index 5b76720f840..76fdcb7d7ef 100644 --- a/examples/cdp_mode/raw_planetmc.py +++ b/examples/cdp_mode/raw_planetmc.py @@ -3,7 +3,7 @@ with SB(uc=True, test=True) as sb: url = "www.planetminecraft.com/account/sign_in/" sb.activate_cdp_mode(url) - sb.sleep(2) + sb.sleep(1.2) sb.solve_captcha() sb.wait_for_element_absent("input[disabled]") sb.sleep(2) diff --git a/examples/cdp_mode/raw_science.py b/examples/cdp_mode/raw_science.py index 792dca7c278..dbbd4095ff3 100644 --- a/examples/cdp_mode/raw_science.py +++ b/examples/cdp_mode/raw_science.py @@ -4,12 +4,12 @@ url = "https://earth.esa.int/eogateway/search" sb.activate_cdp_mode(url) sb.sleep(1) - sb.cdp.click_if_visible('button:contains("Accept cookies")') + sb.click_if_visible('button:contains("Accept cookies")') for i in range(20): - sb.cdp.scroll_to_bottom() - sb.cdp.click_if_visible('button:contains("READ MORE")') + sb.scroll_to_bottom() + sb.click_if_visible('button:contains("READ MORE")') sb.sleep(1) - elements = sb.cdp.find_elements("h4 a span") + elements = sb.find_elements("h4 a span") for element in elements: print(element.text) print("*** Total entries: %s" % len(elements)) diff --git a/examples/cdp_mode/raw_timezone.py b/examples/cdp_mode/raw_timezone.py index d2dd5a46a6e..b2afa4ca057 100644 --- a/examples/cdp_mode/raw_timezone.py +++ b/examples/cdp_mode/raw_timezone.py @@ -26,7 +26,6 @@ def main(): ) sb.add_handler(mycdp.fetch.RequestPaused, request_paused_handler) sb.remove_elements("#right-sidebar") - sb.remove_elements('[id*="Footer"]') sb.sleep(6) sb.driver.stop() diff --git a/examples/cdp_mode/raw_timezone_sb.py b/examples/cdp_mode/raw_timezone_sb.py index 72120e33d7d..c9d3cbb93d2 100644 --- a/examples/cdp_mode/raw_timezone_sb.py +++ b/examples/cdp_mode/raw_timezone_sb.py @@ -5,9 +5,7 @@ url = "https://www.randymajors.org/what-time-zone-am-i-in" sb.activate_cdp_mode(url, tzone="Asia/Kolkata", geoloc=(26.863, 80.94)) sb.remove_elements("#right-sidebar") - sb.remove_elements('[id*="Footer"]') sb.sleep(5) sb.cdp.open(url, tzone="Asia/Tokyo", geoloc=(35.050681, 136.844728)) sb.remove_elements("#right-sidebar") - sb.remove_elements('[id*="Footer"]') sb.sleep(5) From ba0a01f25782da0b2759f26560607050a74208f8 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 11 Nov 2025 00:47:43 -0500 Subject: [PATCH 4/5] 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 60e08c2b1be..5b69ca1b8a9 100755 --- a/requirements.txt +++ b/requirements.txt @@ -90,7 +90,7 @@ rich>=14.2.0,<15 coverage>=7.6.1;python_version<"3.9" coverage>=7.10.7;python_version>="3.9" and python_version<"3.10" -coverage>=7.11.1;python_version>="3.10" +coverage>=7.11.3;python_version>="3.10" pytest-cov>=5.0.0;python_version<"3.9" pytest-cov>=7.0.0;python_version>="3.9" flake8==5.0.4;python_version<"3.9" diff --git a/setup.py b/setup.py index e1aafdded57..aff87d51705 100755 --- a/setup.py +++ b/setup.py @@ -248,7 +248,7 @@ "coverage": [ 'coverage>=7.6.1;python_version<"3.9"', 'coverage>=7.10.7;python_version>="3.9" and python_version<"3.10"', - 'coverage>=7.11.1;python_version>="3.10"', + 'coverage>=7.11.3;python_version>="3.10"', 'pytest-cov>=5.0.0;python_version<"3.9"', 'pytest-cov>=7.0.0;python_version>="3.9"', ], From 4da6ed25c3e5ec00a01bb9e79794e6793952692f Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 11 Nov 2025 00:47:54 -0500 Subject: [PATCH 5/5] Version 4.44.9 --- seleniumbase/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index dab771339fb..1e7ca9b0568 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.44.8" +__version__ = "4.44.9"