Connecting Selenium to existing browser with multiple tabs

·

4 min read

Quick word before we begin

Although re-using already running browser ( it's not officially supported in Selenium ), there are some workarounds. I've come across many tutorial and answers on StackOverflow regarding this matter, but none of them fully provided the solution I needed.
In my case, I was working on an app in which end-user had to be able to run it on previously opened browser in any given time. And this was the tricky part.
You see, all of the workarounds that I've found were assuming that you will manually configure browser and just after you will connect Selenium to it. As long as it can be good if you're the only one who is using it, it's not really the most convenient way for other users, who want to use an app after running their computers for hours with many tabs already opened.

The workaround proposed below can be applied to any browser, but in this example I will use Edge Chromium running on Windows. I assume that you have also downloaded the webdriver already. All be done using Python.

Let's do it

So, straight to the point. What you have to do is modify your browser's shortcut target by adding debugging port. I assume that probably you open your browser from your desktop, and for this purpose it will be enough to change it only there. (If you have one shortcut on the desktop and also for example browser icon pinned to task bar, and you open both of then, script will only be able to connect to the window of the browser opened from desktop).
Right click on the browser shortcut - properties - shortcut tab - target. You will see something like this: image.png

Click on the target path, go at the end and add the following:

--remote-debugging-port=9222 --user-data-dir="C:\Users\your_username\AppData\Local\Microsoft\Edge\Profile"

Click OK. You browser has been set up correctly!

Of course, this can be done programatically, such as:

import win32com.client
import os.path as path

"""Adding port 9222 to Chromium..."""
current_user = path.expanduser("~")
sh = win32com.client.Dispatch("WScript.Shell")
lnk = sh.CreateShortcut(f"{sh.specialfolders('desktop')}\Microsoft Edge.lnk") 
lnk.targetpath = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
lnk.arguments = r'--remote-debugging-port=9222 --user-data-dir="{}\AppData\Local\Microsoft\Edge\Profile"'.format(current_user)
lnk.Save()

Now, open the browser. You may notice some changes (e.g. if you had dark mode turned on, now it's in light mode. It just opened with default settings. Thus, if you open not modified shortcut, it will open normally).

In order to connect Selenium to opened browser, you have to include code below:

from msedge.selenium_tools import EdgeOptions
from msedge.selenium_tools import Edge

def connect_PORT():
    global driver
    print("Connecting to port 9222...")
    options = EdgeOptions()
    options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
    options.use_chromium = True
    driver = Edge(
        executable_path=r"\path\to\your\driver",
        options=options,
    )

After calling the function connect_PORT(), your already opened browser can be now manipulated. Try it by yourself (e.g. invoke driver.get('https://google.com').

You will quickly notice, that script attaches itself to lastly opened tab. If you want to choose specific tab, I would recommend writing simple GUI in which you list names of all opened tabs and choosing which one you want to work on. To switch between tabs, we're going to need window_handles check docs: 'Moving between windows and frames'
I won't focus on the GUI part (you can use Tkinter - see python docs, but to give you an idea:

def get_opened_tabs():
    print("Getting opened tabs...")
    list_of_tabs = driver.window_handles
    titles_handles = dict()
    for tab in list_of_tabs:
        driver.switch_to.window(tab)
        titles_handles[driver.title] = tab
    return titles_handles

It returns dictionary of titles and its handles. From then it's easy to hook it up with GUI. To switch tab based on window_handle use:

driver.switch_to.window(handle_id)

...and that's it :)

Ending note

I hope that you found it useful. I'm aware that some of the stuff mentioned above may have been clear & easy, but for someone who is a beginner, it might not be the case.
Although I "connected the dots" a while ago, I didn't really have much time to write about this. From quick research, I still did not find any satisfying answer, so I thought I will share this anyway. Maybe it will help someone. :)