Reusing Existing Browser Sessions in Selenium WebDriver
When WebDriver instantiates a new browser, it always creates a fresh browser session. However, there are scenarios where reusing an existing session becomes necessary. For web scraping tasks, you might want the browser to remain idle after script completion so the next run continues from where it left off. In test automation, after performing numerous setup operations, you wouldn't want to repeat them if the program crashes and restarts.
While this functionality proves quite practical, the official Selenium API doesn't provide built-in support for it.
How Browser Sessions Work
Starting a browser session through WebDriver involves three distinct phases:
- Launching the browser driver proxy (ChromeDriver, GeckoDriver, etc.)
- Creating a command executor to send operational commands to the proxy
- Establishing a new browser session through the proxy, which communicates with the browser using a
sessionIdto identify the session
To reuse an existing session, you need only two components: the executor from phase 2 and the sessionId from phase 3.
Capturing Session Information
from selenium import webdriver
browser = webdriver.Chrome()
remote_url = browser.command_executor._url
session_id = browser.session_id
print(session_id)
print(remote_url)
browser.get("http://example.com")
Running this script opens Chrome. Since quit() was never called, the browser remains active. However, the browser object has been destroyed in Python, making this a zombie browser that can only be controlled manually.
The output displays something like:
abc123def456
http://127.0.0.1:52869
Attempting Direct Reconnection
Stack Overflow suggests a straightforward approacch:
from selenium import webdriver
browser = webdriver.Chrome()
remote_url = browser.command_executor._url
session_id = browser.session_id
browser.get("http://example.com")
print(session_id)
print(remote_url)
browser2 = webdriver.Remote(command_executor=remote_url, desired_capabilities={})
browser2.session_id = session_id
print(browser2.current_url)
This method connects to the previous session but simultaneously opens a new blank tab. The Remote class automatically calls start_session during instantiation, wich creates a fresh session regardless of the session_id assignment.
Creating a Custom Remote Class
The solution requires subclassing Remote and overriding start_session to prevent automatic session creation:
from selenium.webdriver import Remote
from selenium.webdriver.chrome import options
from selenium.common.exceptions import InvalidArgumentException
class ReusableBrowser(Remote):
def __init__(self, command_executor, session_id):
self.stored_session_id = session_id
Remote.__init__(self, command_executor=command_executor, desired_capabilities={})
def start_session(self, capabilities, browser_profile=None):
"""
Override start_session to use existing session instead of creating a new one
"""
if not isinstance(capabilities, dict):
raise InvalidArgumentException("Capabilities must be a dictionary")
if browser_profile:
if "moz:firefoxOptions" in capabilities:
capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded
else:
capabilities.update({'firefox_profile': browser_profile.encoded})
self.capabilities = options.Options().to_capabilities()
self.session_id = self.stored_session_id
self.w3c = False
Complete Reconnection Example
from selenium import webdriver
# First run: create new browser session
browser = webdriver.Chrome()
# Store connection details for later reuse
remote_url = browser.command_executor._url
session_id = browser.session_id
# Navigate to a site
browser.get("http://example.com")
print(session_id)
print(remote_url)
# Simulate the browser object being destroyed
del browser
# Reconnect using the custom class
browser2 = ReusableBrowser(command_executor=remote_url, session_id=session_id)
# Verify reconnection succeeded by checking current URL
print(browser2.current_url)
# Continue using the existing session
browser2.get("http://another-site.com")
This approach successfully reconnects to the previously opened browser session without launching a new instance, allowing you to pick up exactly where you left off.