Skip to content

Commit 54e76c8

Browse files
authored
Merge pull request #3700 from seleniumbase/add-cdp-options
Add CDP Options
2 parents 94b3fa6 + 5ae12a0 commit 54e76c8

File tree

9 files changed

+193
-11
lines changed

9 files changed

+193
-11
lines changed

examples/cdp_mode/ReadMe.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ sb.cdp.js_dumps(obj_name)
420420
sb.cdp.maximize()
421421
sb.cdp.minimize()
422422
sb.cdp.medimize()
423-
sb.cdp.set_window_rect()
423+
sb.cdp.set_window_rect(x, y, width, height)
424424
sb.cdp.reset_window_size()
425425
sb.cdp.open_new_window(url=None, switch_to=True)
426426
sb.cdp.switch_to_window(window)

examples/cdp_mode/raw_geolocation.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Geolocation example using CDP Mode without WebDriver"""
2+
from seleniumbase import decorators
3+
from seleniumbase import sb_cdp
4+
5+
6+
@decorators.print_runtime("Geolocation CDP Example")
7+
def main():
8+
url = "https://www.openstreetmap.org/"
9+
sb = sb_cdp.Chrome(url, geoloc=(48.87645, 2.26340))
10+
sb.click("span.geolocate")
11+
sb.assert_url_contains("48.876450/2.263400")
12+
sb.sleep(5)
13+
14+
15+
if __name__ == "__main__":
16+
main()

examples/cdp_mode/raw_timezone.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Timezone example using CDP Mode without WebDriver"""
2+
import mycdp
3+
from seleniumbase import decorators
4+
from seleniumbase import sb_cdp
5+
6+
7+
async def request_paused_handler(event, tab):
8+
r = event.request
9+
is_image = ".png" in r.url or ".jpg" in r.url or ".gif" in r.url
10+
if not is_image: # Let the data through
11+
tab.feed_cdp(mycdp.fetch.continue_request(request_id=event.request_id))
12+
else: # Block the data (images)
13+
TIMED_OUT = mycdp.network.ErrorReason.TIMED_OUT
14+
tab.feed_cdp(mycdp.fetch.fail_request(event.request_id, TIMED_OUT))
15+
16+
17+
@decorators.print_runtime("Timezone CDP Example")
18+
def main():
19+
url = "https://www.randymajors.org/what-time-zone-am-i-in"
20+
sb = sb_cdp.Chrome(
21+
url,
22+
ad_block=True,
23+
lang="bn",
24+
tzone="Asia/Kolkata",
25+
geoloc=(26.855323, 80.937710)
26+
)
27+
sb.add_handler(mycdp.fetch.RequestPaused, request_paused_handler)
28+
sb.remove_elements("#right-sidebar")
29+
sb.remove_elements('[id*="Footer"]')
30+
sb.sleep(6)
31+
32+
33+
if __name__ == "__main__":
34+
main()

requirements.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pip>=25.0.1
22
packaging>=25.0
33
setuptools~=70.2;python_version<"3.10"
4-
setuptools>=79.0.0;python_version>="3.10"
4+
setuptools>=79.0.1;python_version>="3.10"
55
wheel>=0.45.1
66
attrs>=25.3.0
77
certifi>=2025.1.31
@@ -11,7 +11,7 @@ websockets>=15.0.1;python_version>="3.9"
1111
filelock~=3.16.1;python_version<"3.9"
1212
filelock>=3.18.0;python_version>="3.9"
1313
fasteners>=0.19
14-
mycdp>=1.1.1
14+
mycdp>=1.2.0
1515
pynose>=1.5.4
1616
platformdirs>=4.3.6;python_version<"3.9"
1717
platformdirs>=4.3.7;python_version>="3.9"
@@ -36,7 +36,7 @@ urllib3>=1.26.20,<2;python_version<"3.10"
3636
urllib3>=1.26.20,<2.5.0;python_version>="3.10"
3737
requests==2.32.3
3838
sniffio==1.3.1
39-
h11==0.14.0
39+
h11==0.16.0
4040
outcome==1.3.0.post0
4141
trio==0.27.0;python_version<"3.9"
4242
trio==0.30.0;python_version>="3.9"

seleniumbase/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.37.6"
2+
__version__ = "4.37.7"

seleniumbase/undetected/cdp_driver/browser.py

+55-2
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,63 @@ async def get(
287287
connection: tab.Tab = next(
288288
filter(lambda item: item.type_ == "page", self.targets)
289289
)
290-
# Use the tab to navigate to new url
291290
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
292291
await connection.send(cdp.page.navigate("about:blank"))
293-
await connection.set_locale(sb_config._cdp_locale)
292+
if (
293+
hasattr(sb_config, "_cdp_user_agent")
294+
and sb_config._cdp_user_agent
295+
):
296+
pass
297+
elif (
298+
hasattr(sb_config, "_cdp_platform")
299+
and sb_config._cdp_platform
300+
):
301+
pass
302+
else:
303+
await connection.set_locale(sb_config._cdp_locale)
304+
if hasattr(sb_config, "_cdp_timezone") and sb_config._cdp_timezone:
305+
await connection.send(cdp.page.navigate("about:blank"))
306+
await connection.set_timezone(sb_config._cdp_timezone)
307+
if (
308+
hasattr(sb_config, "_cdp_user_agent")
309+
and sb_config._cdp_user_agent
310+
):
311+
await connection.send(cdp.page.navigate("about:blank"))
312+
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
313+
_cdp_platform = None
314+
if (
315+
hasattr(sb_config, "_cdp_platform")
316+
and sb_config._cdp_platform
317+
):
318+
_cdp_platform = sb_config._cdp_platform
319+
await connection.set_user_agent(
320+
sb_config._cdp_user_agent,
321+
sb_config._cdp_locale,
322+
_cdp_platform,
323+
)
324+
else:
325+
await connection.set_user_agent(sb_config._cdp_user_agent)
326+
elif (
327+
hasattr(sb_config, "_cdp_platform") and sb_config._cdp_platform
328+
):
329+
await connection.send(cdp.page.navigate("about:blank"))
330+
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
331+
_cdp_platform = sb_config._cdp_platform
332+
await connection.set_user_agent(
333+
accept_language=sb_config._cdp_locale,
334+
platform=_cdp_platform,
335+
)
336+
else:
337+
await connection.set_user_agent(
338+
platform=sb_config._cdp_platform
339+
)
340+
if (
341+
hasattr(sb_config, "_cdp_geolocation")
342+
and sb_config._cdp_geolocation
343+
):
344+
await connection.send(cdp.page.navigate("about:blank"))
345+
await connection.set_geolocation(sb_config._cdp_geolocation)
346+
# Use the tab to navigate to new url
294347
frame_id, loader_id, *_ = await connection.send(
295348
cdp.page.navigate(url)
296349
)

seleniumbase/undetected/cdp_driver/cdp_util.py

+49
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import typing
1111
from contextlib import suppress
1212
from seleniumbase import config as sb_config
13+
from seleniumbase import extensions
1314
from seleniumbase.config import settings
1415
from seleniumbase.core import detect_b_ver
16+
from seleniumbase.core import download_helper
1517
from seleniumbase.core import proxy_helper
1618
from seleniumbase.fixtures import constants
1719
from seleniumbase.fixtures import shared_utils
@@ -25,7 +27,10 @@
2527

2628
logger = logging.getLogger(__name__)
2729
IS_LINUX = shared_utils.is_linux()
30+
DOWNLOADS_FOLDER = download_helper.get_downloads_folder()
2831
PROXY_DIR_LOCK = proxy_helper.PROXY_DIR_LOCK
32+
EXTENSIONS_DIR = os.path.dirname(os.path.realpath(extensions.__file__))
33+
AD_BLOCK_ZIP_PATH = os.path.join(EXTENSIONS_DIR, "ad_block.zip")
2934
T = typing.TypeVar("T")
3035

3136

@@ -168,6 +173,19 @@ def __add_chrome_ext_dir(extension_dir, dir_path):
168173
return extension_dir
169174

170175

176+
def __unzip_to_new_folder(zip_file, folder):
177+
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
178+
with proxy_dir_lock:
179+
with suppress(Exception):
180+
shared_utils.make_writable(PROXY_DIR_LOCK)
181+
if not os.path.exists(folder):
182+
import zipfile
183+
zip_ref = zipfile.ZipFile(zip_file, "r")
184+
os.makedirs(folder)
185+
zip_ref.extractall(folder)
186+
zip_ref.close()
187+
188+
171189
def __add_chrome_proxy_extension(
172190
extension_dir,
173191
proxy_string,
@@ -231,14 +249,18 @@ async def start(
231249
browser_executable_path: Optional[PathLike] = None,
232250
browser_args: Optional[List[str]] = None,
233251
xvfb_metrics: Optional[List[str]] = None, # "Width,Height" for Linux
252+
ad_block: Optional[bool] = False,
234253
sandbox: Optional[bool] = True,
235254
lang: Optional[str] = None, # Set the Language Locale Code
236255
host: Optional[str] = None, # Chrome remote-debugging-host
237256
port: Optional[int] = None, # Chrome remote-debugging-port
238257
xvfb: Optional[int] = None, # Use a special virtual display on Linux
239258
headed: Optional[bool] = None, # Override default Xvfb mode on Linux
240259
expert: Optional[bool] = None, # Open up closed Shadow-root elements
260+
agent: Optional[str] = None, # Set the user-agent string
241261
proxy: Optional[str] = None, # "host:port" or "user:pass@host:port"
262+
tzone: Optional[str] = None, # Eg "America/New_York", "Asia/Kolkata"
263+
geoloc: Optional[list | tuple] = None, # Eg (48.87645, 2.26340)
242264
extension_dir: Optional[str] = None, # Chrome extension directory
243265
**kwargs: Optional[dict],
244266
) -> Browser:
@@ -296,6 +318,13 @@ async def start(
296318
proxy_user,
297319
proxy_pass,
298320
)
321+
if ad_block:
322+
incognito = False
323+
guest = False
324+
ad_block_zip = AD_BLOCK_ZIP_PATH
325+
ad_block_dir = os.path.join(DOWNLOADS_FOLDER, "ad_block")
326+
__unzip_to_new_folder(ad_block_zip, ad_block_dir)
327+
extension_dir = __add_chrome_ext_dir(extension_dir, ad_block_dir)
299328
if not config:
300329
config = Config(
301330
user_data_dir,
@@ -329,6 +358,26 @@ async def start(
329358
sb_config._cdp_locale = kwargs["locale_code"]
330359
else:
331360
sb_config._cdp_locale = None
361+
if tzone:
362+
sb_config._cdp_timezone = tzone
363+
elif "timezone" in kwargs:
364+
sb_config._cdp_timezone = kwargs["timezone"]
365+
else:
366+
sb_config._cdp_timezone = None
367+
if geoloc:
368+
sb_config._cdp_geolocation = geoloc
369+
elif "geolocation" in kwargs:
370+
sb_config._cdp_geolocation = kwargs["geolocation"]
371+
else:
372+
sb_config._cdp_geolocation = None
373+
if agent:
374+
sb_config._cdp_user_agent = agent
375+
elif "user_agent" in kwargs:
376+
sb_config._cdp_user_agent = kwargs["user_agent"]
377+
else:
378+
sb_config._cdp_user_agent = None
379+
if "platform" in kwargs:
380+
sb_config._cdp_platform = kwargs["platform"]
332381
return driver
333382

334383

seleniumbase/undetected/cdp_driver/connection.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,37 @@ async def wait(self, t: Union[int, float] = None):
348348

349349
async def set_locale(self, locale: Optional[str] = None):
350350
"""Sets the Language Locale code via set_user_agent_override."""
351-
await self.send(cdp.network.set_user_agent_override("", locale))
351+
await self.set_user_agent(user_agent="", accept_language=locale)
352+
353+
async def set_timezone(self, timezone: Optional[str] = None):
354+
"""Sets the Timezone via set_timezone_override."""
355+
await self.send(cdp.emulation.set_timezone_override(timezone))
356+
357+
async def set_user_agent(
358+
self,
359+
user_agent: Optional[str] = "",
360+
accept_language: Optional[str] = None,
361+
platform: Optional[str] = None, # navigator.platform
362+
):
363+
"""Sets the User Agent via set_user_agent_override."""
364+
if not user_agent:
365+
user_agent = ""
366+
await self.send(cdp.network.set_user_agent_override(
367+
user_agent=user_agent,
368+
accept_language=accept_language,
369+
platform=platform,
370+
))
371+
372+
async def set_geolocation(self, geolocation: Optional[tuple] = None):
373+
"""Sets the User Agent via set_geolocation_override."""
374+
await self.send(cdp.browser.grant_permissions(
375+
permissions=["geolocation"],
376+
))
377+
await self.send(cdp.emulation.set_geolocation_override(
378+
latitude=geolocation[0],
379+
longitude=geolocation[1],
380+
accuracy=100,
381+
))
352382

353383
def __getattr__(self, item):
354384
""":meta private:"""

setup.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
'pip>=25.0.1',
151151
'packaging>=25.0',
152152
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
153-
'setuptools>=79.0.0;python_version>="3.10"',
153+
'setuptools>=79.0.1;python_version>="3.10"',
154154
'wheel>=0.45.1',
155155
'attrs>=25.3.0',
156156
"certifi>=2025.1.31",
@@ -160,7 +160,7 @@
160160
'filelock~=3.16.1;python_version<"3.9"',
161161
'filelock>=3.18.0;python_version>="3.9"',
162162
'fasteners>=0.19',
163-
"mycdp>=1.1.1",
163+
"mycdp>=1.2.0",
164164
"pynose>=1.5.4",
165165
'platformdirs>=4.3.6;python_version<"3.9"',
166166
'platformdirs>=4.3.7;python_version>="3.9"',
@@ -185,7 +185,7 @@
185185
'urllib3>=1.26.20,<2.5.0;python_version>="3.10"',
186186
'requests==2.32.3',
187187
'sniffio==1.3.1',
188-
'h11==0.14.0',
188+
'h11==0.16.0',
189189
'outcome==1.3.0.post0',
190190
'trio==0.27.0;python_version<"3.9"',
191191
'trio==0.30.0;python_version>="3.9"',

0 commit comments

Comments
 (0)