Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Handle a Selenium “popup” according to what actually opened. A JavaScript alert, confirm, or prompt is a native modal dialog and must be handled through WebDriver’s alert API. A new tab or browser window is a separate browsing context and requires window handles. Waiting for the expected object, switching to it, performing the intended user action, and returning to a valid context prevents most popup-related failures.

Selenium describes these dialogs as “the three types of native popup messages offered by JavaScript.” Its official alert documentation covers their API; the windows-and-tabs guide covers browsing contexts.

First identify what “popup” means

The word popup is used for several unrelated browser behaviors. Identify the case before writing a locator or wait:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
What opened What the user sees Selenium operation
Alert Message with an acknowledgement button Wait for an alert, read alert.text, then accept
Confirm Message with accept and cancel choices Accept or dismiss, depending on the scenario
Prompt Message with a text field and accept/cancel choices Send text to the alert, then accept, or dismiss to cancel
New tab or window A complete page in another browsing context Save and switch between window handles
HTML modal, cookie banner, or overlay Elements rendered inside the page DOM Locate and operate on normal WebElements

A native dialog is not a DOM element. While it is open, trying to find a page button is the wrong interaction model. Conversely, a tab that looks like a popup is not an alert and cannot be handled with switch_to.alert.

Handle JavaScript alerts, confirms, and prompts

The reliable sequence

  1. Trigger the page action that opens the dialog.
  2. Wait until an alert is present; do not rely on a fixed sleep.
  3. Switch to the alert object.
  4. Read its text if the test verifies the message.
  5. Accept or dismiss according to the expected user path.
  6. Continue interacting with the page after the modal is closed.

Use an explicit wait because the dialog may appear after JavaScript runs. In Python, Selenium’s official pattern is WebDriverWait(driver, timeout).until(EC.alert_is_present()).

Python: one reusable helper

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException


def get_alert(driver, timeout=10):
    """Wait for and return the currently expected JavaScript dialog."""
    return WebDriverWait(driver, timeout).until(EC.alert_is_present())


driver = webdriver.Chrome()
try:
    driver.get("https://example.test/alerts")
    driver.find_element(By.ID, "open-alert").click()

    alert = get_alert(driver)
    message = alert.text
    assert message == "Saved successfully"
    alert.accept()
finally:
    driver.quit()

The exact locator and expected message are application-specific. The important parts are the alert-presence wait and using the alert interface rather than a DOM locator.

Alerts: acknowledge the message

An alert has a message and an acknowledgement action. Read the text before accepting when the message is part of the assertion:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
assert "Saved" in alert.text
alert.accept()

After accept() returns, the modal is closed and the page context can be used again.

Confirms: test both outcomes

A confirm has two meaningful user paths. Make them separate test cases when the application behaves differently for each:

# Accept path
confirm = WebDriverWait(driver, 10).until(EC.alert_is_present())
assert confirm.text == "Delete this item?"
confirm.accept()

# Dismiss/cancel path (trigger the confirm again first)
confirm = WebDriverWait(driver, 10).until(EC.alert_is_present())
confirm.dismiss()

accept() models choosing OK; dismiss() models Cancel. Assert the resulting page state after each branch.

Prompts: enter text before accepting

A prompt adds an input field. Send the test value to the alert object before accepting:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
prompt = WebDriverWait(driver, 10).until(EC.alert_is_present())
assert prompt.text == "Enter your project name"
prompt.send_keys("Selenium demo")
prompt.accept()

To model cancellation, trigger the prompt again and call dismiss() without sending text. Canceling does not submit a value.

JavaScript binding example

Method names vary by language binding. In Selenium’s JavaScript API, wait for the alert, obtain its text, and accept or dismiss the returned alert object:

const { Builder, By, until } = require('selenium-webdriver');

(async function () {
  const driver = await new Builder().forBrowser('chrome').build();
  try {
    await driver.get('https://example.test/alerts');
    await driver.findElement(By.id('open-confirm')).click();

    const alert = await driver.wait(until.alertIsPresent(), 10000);
    const message = await alert.getText();
    if (message !== 'Delete this item?') throw new Error(message);
    await alert.dismiss();
  } finally {
    await driver.quit();
  }
})();

Consult the API reference for your binding if its alert methods use different spellings. The operation remains the same: wait, switch, inspect, and choose the user outcome.

Handle a popup tab or window with window handles

A new tab and a new window are both browsing contexts in WebDriver. Selenium does not require a different workflow based on how the operating system displays them. Each context has a window handle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python: save, switch, use, close, return

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait


driver = webdriver.Chrome()
try:
    driver.get("https://example.test/links")
    original = driver.current_window_handle
    handles_before = set(driver.window_handles)

    driver.find_element(By.ID, "open-report").click()

    # Wait until a handle that was not present before appears.
    WebDriverWait(driver, 10).until(
        lambda d: len(set(d.window_handles) - handles_before) == 1
    )
    new_handle = (set(driver.window_handles) - handles_before).pop()
    driver.switch_to.window(new_handle)

    assert "Report" in driver.title
    driver.find_element(By.ID, "download").click()
    driver.close()

    # The closed handle is invalid; explicitly return to the remaining one.
    driver.switch_to.window(original)
    assert driver.current_window_handle == original
finally:
    driver.quit()

Do not assume that the visibly active operating-system window is Selenium’s current context. Always call switch_to.window(handle) before locating elements in the new page.

When more than one new context opens

If an action can open several tabs, compare the handle set before and after, then select by a property that identifies the intended page (title, URL, or a unique element) rather than assuming list order:

before = set(driver.window_handles)
# trigger action here
WebDriverWait(driver, 10).until(
    lambda d: len(set(d.window_handles) - before) >= 1
)
for handle in set(driver.window_handles) - before:
    driver.switch_to.window(handle)
    if "/checkout" in driver.current_url:
        break
else:
    raise RuntimeError("Checkout context did not open")

JavaScript: switch by handle

const original = await driver.getWindowHandle();
const before = new Set(await driver.getAllWindowHandles());
await driver.findElement(By.id('open-report')).click();
await driver.wait(async () => {
  const now = new Set(await driver.getAllWindowHandles());
  return [...now].some(h => !before.has(h));
}, 10000);
const handles = await driver.getAllWindowHandles();
const popup = handles.find(h => !before.has(h));
await driver.switchTo().window(popup);
// interact with the popup page
await driver.close();
await driver.switchTo().window(original);

Closing contexts safely

close() closes the current tab or window only. It does not automatically select another handle. Switch to a handle that remains open before issuing the next command. Continuing from a closed context can raise a No Such Window Exception, as documented by Selenium.

  • Keep the original handle in a variable before opening the popup.
  • Close only when the scenario calls for closing it; some tests need to leave the context open.
  • After closing, verify that the saved handle is still in driver.window_handles before switching.
  • Call quit() once at teardown to close every remaining context.

Automatic handling of beforeunload prompts

Recent drivers automatically dismiss beforeunload prompts by default. Do not assume that behavior applies identically to every old driver and browser combination. Selenium points to the unhandledPromptBehavior capability for configuring older or special cases. Documented actions include accept, dismiss, accept and notify, dismiss and notify, and ignore; the JavaScript API reference lists these values at UserPromptHandler.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set the capability deliberately when your test must define behavior for an unexpected prompt, and still handle expected dialogs explicitly so the test expresses the user action being verified.

Common failures and precise fixes

“No alert is present” or an alert wait times out

  • The trigger did not run: verify the click, form submission, or JavaScript event.
  • The dialog is an HTML modal, not a native alert: inspect the DOM and locate its elements normally.
  • The wait started too early or with too little time: start it immediately after the trigger and use an explicit timeout appropriate for the page.
  • The browser navigated or the alert was already consumed by another step: reproduce the sequence and ensure only one command handles it.

Element commands fail while a dialog is visible

Switch to the alert and accept or dismiss it first. A native modal blocks ordinary page interaction; a CSS overlay does not and should be handled with normal WebElement commands.

The new tab opened but Selenium still sees the old page

Opening a context does not switch WebDriver automatically. Capture window_handles, identify the new handle, and call switch_to.window().

NoSuchWindowException after closing

The driver is still pointed at the closed context. Switch to a surviving handle immediately after close(), and avoid storing or reusing elements from the closed page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The test is flaky because of sleeps

Replace fixed delays with conditions: EC.alert_is_present() for native dialogs, a new-handle condition for tabs, and a title, URL, or element condition for the destination page. Conditions synchronize with the event you actually need.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean image or PDF of a page rather than testing dialog behavior, ScreenshotNeo provides a single HTTP request. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Use the complete API options in the ScreenshotNeo documentation. A basic call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Practical checklist

  • Classify the popup as a native alert, confirm, prompt, new context, or DOM overlay.
  • Wait for presence instead of sleeping.
  • Read dialog text before acting when it is part of the assertion.
  • Test both accept and dismiss paths for confirms when both matter.
  • Send prompt text before accepting; dismiss to model cancellation.
  • Save the original window handle, switch explicitly, and return after closing.
  • Configure unhandledPromptBehavior only when the browser/driver behavior requires it.

Frequently Asked Questions

Can Selenium click a button behind a JavaScript alert?

No. A native alert blocks normal page commands. Wait for the alert, switch to it, accept or dismiss it, and then interact with the page.

Are browser tabs and windows handled by different Selenium APIs?

No. WebDriver treats both as window handles. The same save, switch, interact, close, and switch-back workflow applies.

Does dismissing a prompt submit an empty value?

No. Dismissal represents canceling the prompt; it does not submit text.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.