Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions help_docs/cdp_mode_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ sb.cdp.open(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()
sb.cdp.is_running()
sb.cdp.get_rd_host() # Returns the remote-debugging host
sb.cdp.get_rd_port() # Returns the remote-debugging port
sb.cdp.get_rd_url() # Returns the remote-debugging URL
Expand Down
2 changes: 1 addition & 1 deletion mkdocs_build/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

regex>=2026.5.9
pymdown-extensions>=10.21.3
pipdeptree>=2.35.2
pipdeptree>=2.35.3
python-dateutil>=2.8.2
Markdown==3.10.2
click==8.4.0
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ six>=1.17.0
parse>=1.22.0
parse-type>=0.6.6
colorama>=0.4.6
psutil>=7.2.2
pyyaml>=6.0.3
pygments>=2.20.0
pyreadline3>=3.5.4;platform_system=="Windows"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.49.0"
__version__ = "4.49.1"
24 changes: 24 additions & 0 deletions seleniumbase/undetected/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import re
import psutil
import requests
import subprocess
import sys
Expand Down Expand Up @@ -299,6 +300,13 @@ def __init__(
creationflags=creationflags,
)
self.browser_pid = browser.pid
self._process_pid = browser.pid
try:
self._process_create_time = (
psutil.Process(self._process_pid).create_time()
)
except psutil.NoSuchProcess:
self._process_create_time = None
service_ = None
log_output = subprocess.PIPE
if patch_driver:
Expand Down Expand Up @@ -392,6 +400,22 @@ def _hook_remove_cdc_props(self, cdc_props):
},
)

def is_running(self):
"""Check if the browser is still running."""
if not getattr(self, "_process_pid", None):
return False
# Not good enough: return psutil.pid_exists(self._process_pid)
try:
process = psutil.Process(self._process_pid)
# Check for PID recycling: Is this actually our process?
if hasattr(self, "_process_create_time"):
if process.create_time() != self._process_create_time:
return False # The PID was reused by a different process!
# If the process is a zombie, assume the browser isn't running
return process.status() != psutil.STATUS_ZOMBIE
except psutil.NoSuchProcess:
return False

def remove_cdc_props_as_needed(self):
cdc_props = self._get_cdc_props()
if len(cdc_props) > 0:
Expand Down
23 changes: 23 additions & 0 deletions seleniumbase/undetected/cdp_driver/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os
import pathlib
import pickle
import psutil
import re
import shutil
import time
Expand Down Expand Up @@ -263,6 +264,22 @@ async def _handle_target_update(
)
self.targets.remove(current_tab)

def is_running(self):
"""Check if the browser is still running."""
if not getattr(self, "_process_pid", None):
return False
# Not good enough: return psutil.pid_exists(self._process_pid)
try:
process = psutil.Process(self._process_pid)
# Check for PID recycling: Is this actually our process?
if hasattr(self, "_process_create_time"):
if process.create_time() != self._process_create_time:
return False # The PID was reused by a different process!
# If the process is a zombie, assume the browser isn't running
return process.status() != psutil.STATUS_ZOMBIE
except psutil.NoSuchProcess:
return False

def get_rd_host(self):
return self.config.host

Expand Down Expand Up @@ -617,6 +634,12 @@ async def start(self=None) -> Browser:
)
await asyncio.sleep(0.05)
self._process_pid = self._process.pid
try:
self._process_create_time = (
psutil.Process(self._process_pid).create_time()
)
except psutil.NoSuchProcess:
self._process_create_time = None
await asyncio.sleep(0.05)
self._http = HTTPApi((self.config.host, self.config.port))
await asyncio.sleep(0.05)
Expand Down
11 changes: 4 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,12 @@
'typing-extensions>=4.15.0',
'sbvirtualdisplay>=1.4.0',
'MarkupSafe>=3.0.3',
"Jinja2>=3.1.6",
"six>=1.17.0",
'Jinja2>=3.1.6',
'six>=1.17.0',
'parse>=1.22.0',
'parse-type>=0.6.6',
'colorama>=0.4.6',
'psutil>=7.2.2',
'pyyaml>=6.0.3',
'pygments>=2.20.0',
'pyreadline3>=3.5.4;platform_system=="Windows"',
Expand Down Expand Up @@ -303,11 +304,7 @@
# pip install -e .[playwright]
# (For the Playwright integration.)
"playwright": [
"playwright>=1.58.0",
],
# pip install -e .[psutil]
"psutil": [
"psutil>=7.2.2",
"playwright>=1.60.0",
],
# pip install -e .[pyautogui]
# (Already a required dependency on Linux now.)
Expand Down