2025, Oct 02 23:00

Fixing Selenium current_url After a New Tab Opens: Switch Window Handles or Build the URL from onclick

Learn why Selenium current_url shows the original page after a new tab opens and how to fix it: switch to the window handle or build the URL from onclick.

If a click in Selenium opens a new browser tab, calling current_url right after often returns the URL of the original page. The driver keeps its focus on the first tab unless explicitly told to switch. That is why getting the URL of the newly opened tab can be confusing at first glance.

Reproducing the issue

The following script opens solrenview.com, filters by installer, selects a suggestion, and clicks a result that opens in a second tab. Despite the new tab being visibly active in the browser, the printed URL remains the original one.

import time
import os, sys
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

print(f"Program name: {os.path.basename(__file__)}")
TRY_MODE = True
EXIT_AFTER = 10
SAVE_EVERY = 1
WAIT_SEC = 1
base_dir = os.path.abspath(os.path.dirname(sys.argv[0]))

print("Checking Browser driver...")
chrome_opts = Options()
chrome_opts.add_argument("start-maximized")
chrome_opts.add_argument('--use-gl=swiftshader')
chrome_opts.add_argument('--disable-gpu')
chrome_opts.add_argument('--no-sandbox')
chrome_opts.add_argument('--disable-dev-shm-usage')
chrome_opts.add_argument("start-maximized")
chrome_opts.add_argument('--log-level=3')
chrome_opts.add_argument('--enable-unsafe-swiftshader')

svc = Service()
browser = webdriver.Chrome(service=svc, options=chrome_opts)
sync = WebDriverWait(browser, 10)

home_url = "https://www.solrenview.com/"
browser.get(home_url)

sync.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[@id='gMapsFr']")))
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, '//label[@for="ByInstaller"]'))))
time.sleep(0.5)
sync.until(EC.presence_of_element_located((By.XPATH, '//input[@id="searchBox"]'))).clear()
time.sleep(0.5)
sync.until(EC.presence_of_element_located((By.XPATH, '//input[@id="searchBox"]'))).send_keys("Barrier Solar Inc.")
time.sleep(0.5)
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, '//div[@id="autoSuggestionsList"]//li'))))
time.sleep(3)
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, f'(//a[contains(text(), "Double E")])[{1}]'))))

current_url = browser.current_url
print(current_url)
input("Press!")

What is really happening

Selenium does not automatically switch context to a newly opened window or tab. The click opens a second tab, but the driver’s focus remains on the original one, so current_url represents the first tab. This behavior is by design and documented in Selenium’s window and tab handling. You must switch to the tab you want to inspect before reading its URL.

Selenium docs: Working with windows and tabs

Direct fix: switch to the new tab

Grab the last handle from window_handles, switch to it, and then read the URL. The second tab will be the last handle in this case.

last_tab = browser.window_handles[-1]
browser.switch_to.window(last_tab)
print(browser.current_url)

Alternative: build the target URL without switching

On the page, the target anchors use onclick like SiteUrlFunc(5746). The id inside onclick matches the siteId parameter of the actual destination. You can read onclick, extract the id, and construct the URL directly without following the link.

target = browser.find_element(By.XPATH, f'(//a[contains(text(), "Double E")])[{1}]')
handler = target.get_attribute('onclick')
print('on_click:', handler)
site_id = handler.replace("SiteUrlFunc(", "").replace(");", "")
print('number:', site_id)
print(f"https://www.solrenview.com/SolrenView/mainFr.php?siteId={site_id}")

Complete example with both approaches

The following end-to-end script demonstrates generating the URL from onclick and also switching to the newly opened tab to obtain the URL directly from the browser.

import time
import os, sys
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

print(f"Program name: {os.path.basename(__file__)}")
TRY_MODE = True
EXIT_AFTER = 10
SAVE_EVERY = 1
WAIT_SEC = 1
base_dir = os.path.abspath(os.path.dirname(sys.argv[0]))

print("Checking Browser driver...")
chrome_opts = Options()
chrome_opts.add_argument("start-maximized")
chrome_opts.add_argument('--use-gl=swiftshader')
chrome_opts.add_argument('--disable-gpu')
chrome_opts.add_argument('--no-sandbox')
chrome_opts.add_argument('--disable-dev-shm-usage')
chrome_opts.add_argument("start-maximized")
chrome_opts.add_argument('--log-level=3')
chrome_opts.add_argument('--enable-unsafe-swiftshader')

svc = Service()
browser = webdriver.Chrome(service=svc, options=chrome_opts)
sync = WebDriverWait(browser, 10)

home_url = "https://www.solrenview.com/"
browser.get(home_url)

sync.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//iframe[@id='gMapsFr']")))
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, '//label[@for="ByInstaller"]'))))
time.sleep(0.5)
sync.until(EC.presence_of_element_located((By.XPATH, '//input[@id="searchBox"]'))).clear()
time.sleep(0.5)
sync.until(EC.presence_of_element_located((By.XPATH, '//input[@id="searchBox"]'))).send_keys("Barrier Solar Inc.")
time.sleep(0.5)
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, '//div[@id="autoSuggestionsList"]//li'))))
time.sleep(3)
browser.execute_script("arguments[0].click();", sync.until(EC.element_to_be_clickable((By.XPATH, f'(//a[contains(text(), "Double E")])[{1}]'))))

print(f"{browser.current_url = }")

# Build the URL from onclick
anchor = browser.find_element(By.XPATH, f'(//a[contains(text(), "Double E")])[{1}]')
onclick_val = anchor.get_attribute('onclick')
print('onclick:', onclick_val)
site_id = onclick_val.replace("SiteUrlFunc(", "").replace(");", "")
print('number:', site_id)
print(f"generated: https://www.solrenview.com/SolrenView/mainFr.php?siteId={site_id}")

# Switch to the newly opened tab and print its URL
last_tab = browser.window_handles[-1]
browser.switch_to.window(last_tab)
print(f"last : {browser.current_url = }")

# Switch back to the first tab
first_tab = browser.window_handles[0]
browser.switch_to.window(first_tab)
print(f"first: {browser.current_url = }")

input("Press ENTER to close")

Why this matters

Multi-tab and multi-window flows are common in web apps. Assuming Selenium will follow the user-visible active tab leads to subtle bugs, unreliable assertions, and misleading logs. Explicitly switching context or deriving target URLs from available attributes keeps automation stable and transparent. When tab management is intentional, result collection, navigation control, and teardown logic become predictable.

Takeaways

When a click opens a new tab, the driver stays in the original context until you switch it. Use window_handles to select the correct tab and then read current_url. If the page exposes the destination parameters in attributes like onclick, you can also construct the final URL without switching. Keeping these two techniques in the toolbox saves time when debugging navigation and makes test flows more deterministic.

The article is based on a question from StackOverflow by Rapid1898 and an answer by furas.