How to connect Selenium to an existing browser that was opened manually?

Learn how to connect Selenium to an already running browser session that was opened manually or by another program, using Chrome DevTools Protocol.

8 min read

Sometimes we come across scenarios where we want Selenium to connect to and use an existing browser that was previously opened manually or by some other program.

Wait, why would anyone want to do that? Selenium launches a fresh browser every time, right?

Yes, it does. But hear me out – there are some really practical scenarios where connecting to an already running browser is a game changer:

  • Manual steps before automation – Let's say your application has a captcha on the login page. You can't automate captcha (well, you shouldn't). So you manually open the browser, log in by solving the captcha, and then let your Selenium script take over from there.
  • Desktop + Web hybrid testing – Imagine clicking a button on a desktop application opens a webpage. You use some other tool (like AutoIt or WinAppDriver) for the desktop part, but you want Selenium to take control the moment the webpage opens.
  • Debugging your scripts – This one is my favorite. Let's say you're writing a test for the checkout page, but the script to reach there (add to cart, fill address, etc.) isn't ready yet. Instead of waiting, you manually navigate to the checkout page and run just your checkout test. Huge time saver!

Alright, I'm convinced. But how does this actually work?

We can take advantage of the Chrome DevTools Protocol (CDP). It allows external clients to inspect, debug, and control the Chrome browser. We'll launch Chrome with a special flag that opens a debugging port, and then tell Selenium to connect to that port instead of launching a new browser.

Let's do this step by step.

Step 1: Make Sure Chrome Is Accessible from Terminal

Before anything else, we need to make sure we can launch Chrome from the command line.

On Windows, open Command Prompt and try:

chrome.exe

On Mac, open Terminal and try:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

On Linux, try:

google-chrome

If any of these launch Chrome, you're good to go!

I tried it and got "chrome is not recognized as an internal or external command."

That means Chrome's executable isn't in your system's PATH. You have two options:

  1. Add Chrome's installation directory to your PATH environment variable (Google "add Chrome to PATH" for your OS)
  2. Use the full path to Chrome's executable directly in the next step

Step 2: Launch Chrome with Remote Debugging Enabled

This is where the magic starts. We need to launch Chrome with two special flags:

On Windows:

chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenium\ChromeProfile"

On Mac:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir="/tmp/ChromeProfile"

On Linux:

google-chrome --remote-debugging-port=9222 --user-data-dir="/tmp/ChromeProfile"

Hold on, what are these flags?

  • --remote-debugging-port=9222 – This tells Chrome to open a debugging connection on port 9222. You can use any available port, but 9222 is the convention.
  • --user-data-dir – This creates a separate Chrome profile so your default profile (with all your bookmarks, passwords, extensions) doesn't get messed up. Point it to any directory you like.

Once Chrome launches this way, it's ready to accept connections from external tools – including Selenium!

Verify It's Working

Want to confirm that remote debugging is active? Open a different browser window (or a regular Chrome window) and navigate to:

http://127.0.0.1:9222

You should see a page listing the open tabs in your debuggable Chrome instance. If you see that, everything is set up correctly.

Now go ahead and use the debuggable Chrome window however you want – navigate to pages, log in, solve captchas, do whatever manual steps you need. When you're ready for automation to take over, move to the next step.

Step 3: Connect Selenium to the Running Browser

Here's where Selenium comes in. Instead of launching a new browser, we'll tell it to connect to the one that's already running.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class ConnectToExistingBrowser {
    public static void main(String[] args) {
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");

        WebDriver driver = new ChromeDriver(options);

        // Selenium is now controlling the existing browser!
        System.out.println("Page Title: " + driver.getTitle());
        System.out.println("Current URL: " + driver.getCurrentUrl());
    }
}

Wait, we're not calling driver.quit() at the end?

Great catch! Since we didn't launch this browser through Selenium, we usually don't want Selenium to close it. If you call driver.quit(), it will close the browser you opened manually. Most of the time, you want to leave it running so you can continue using it or re-run your script.

Of course, if you do want Selenium to close it when done, go ahead and add driver.quit().

That's surprisingly simple. What's the debuggerAddress doing exactly?

The debuggerAddress option tells Selenium – "Hey, don't launch a new browser. Instead, connect to the Chrome instance that's already listening on this address and port." The value 127.0.0.1:9222 means localhost on port 9222 – the same port we used when launching Chrome with --remote-debugging-port.

A Real-World Example

Let's put it all together with a practical scenario. Say you need to automate a test on a page that requires manual login (because of captcha or 2FA).

Step 1: Launch Chrome with remote debugging (as shown above).

Step 2: Manually navigate to the site, solve the captcha, and log in.

Step 3: Run your Selenium script:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class AutomateAfterManualLogin {
    public static void main(String[] args) {
        // Connect to the existing browser
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        WebDriver driver = new ChromeDriver(options);

        // You're already logged in! Now automate the rest.
        driver.get("https://example.com/dashboard");

        // Interact with elements on the authenticated page
        WebElement welcomeMessage = driver.findElement(By.id("welcome"));
        System.out.println(welcomeMessage.getText());

        // Continue with your test...
    }
}

Since you already logged in manually, Selenium picks up right where you left off – with the session cookies and everything intact. Pretty neat, right?

Troubleshooting

Things don't always go smoothly on the first try. Here are some common issues:

"Cannot connect to the browser"

  • Make sure you launched Chrome with the --remote-debugging-port flag. A regular Chrome window won't work.
  • Check that the port number in your code matches the port you used when launching Chrome.
  • Verify the debugging port is active by visiting http://127.0.0.1:9222 in another browser.

"This version of ChromeDriver only supports Chrome version XX"

Even though you're connecting to an existing browser, Selenium still uses ChromeDriver under the hood. If you're on Selenium 4.6+, Selenium Manager should handle this automatically. If you're on an older version, make sure your ChromeDriver version matches your Chrome version.

"Session already exists"

Make sure you don't have another Selenium script already connected to the same browser. Only one client can connect to a debugging session at a time.

Chrome closes when the script ends

If you accidentally added driver.quit() at the end of your script, remove it. As we discussed earlier, calling quit() will terminate the browser session.

Things to Keep in Mind

  • This technique works with Chrome and Chromium-based browsers (Edge, Brave, etc.). For Edge, use msedge.exe with the same flags.
  • The --user-data-dir flag is important. Without it, Chrome might not launch if another Chrome instance is already running with the default profile.
  • This approach is great for debugging and development. For production test suites, you'd typically want Selenium to manage the browser lifecycle entirely.

What's Next?

Now that you know how to connect Selenium to an existing browser, you can combine manual and automated steps in your testing workflow. This is especially powerful when dealing with captchas, two-factor authentication, or complex manual setup procedures.