The correct Selenium code depends on what Chrome is showing. Use driver.switch_to.alert for JavaScript alert, confirm, and prompt dialogs; use window handles for a new tab or window; locate and click elements for HTML modals and cookie banners; and configure Chrome or use separate desktop automation for browser and operating-system surfaces. The examples below classify the popup first, synchronize with explicit waits, and show how to recover when an optional dialog never appears.
Classify the popup before writing code
“Popup” describes several different surfaces. Selenium APIs are not interchangeable, so identify the surface created by the action you just performed.
| What you see | How Selenium handles it | Typical action |
|---|---|---|
JavaScript alert(), confirm(), or prompt() |
Alert API | Wait for the alert, read its text, then accept, dismiss, or enter text |
| A link opens another tab or window | window_handles and switch_to.window() |
Wait for a new handle, switch context, then find elements |
| A dialog is a page element such as a cookie banner or modal | Normal DOM locators and expected conditions | Click its button and wait for the element to disappear |
| Permission bubble, toolbar UI, certificate chooser, download shelf, HTTP-auth prompt, or OS dialog | Chrome capabilities, test policy, or desktop automation | Configure before navigation or use tooling outside ordinary page APIs |
driver.switch_to.alert works only while a web alert, confirm, or prompt is active. It cannot select a DOM modal or a Chrome toolbar bubble.
Set up Selenium and Chrome
Install Selenium in the Python environment used by your test:
python -m pip install -U selenium
Modern Selenium can manage a compatible Chrome driver through Selenium Manager. If your environment supplies its own driver, ensure the driver and browser versions are compatible. A minimal session is:
#1 Best Overall
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
# ...test...
driver.quit()
Always call quit() in teardown so Chrome processes do not accumulate after a failure.
Close a JavaScript alert
Trigger the action first, then wait for the browser event. A fixed time.sleep() can be too short on a busy machine and unnecessarily slow when the dialog appears immediately.
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
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
try:
driver.get("https://your-test-site.example/alerts")
driver.find_element(By.ID, "show-alert").click()
alert = wait.until(EC.alert_is_present())
message = alert.text
print(message)
alert.accept()
finally:
driver.quit()
alert.accept() presses OK. Read alert.text before closing when the message is part of the assertion. After accepting or dismissing, Selenium returns to the page context.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Accept, dismiss, and fill confirm and prompt dialogs
Confirm: choose based on the message
driver.find_element(By.ID, "delete-record").click()
confirm = WebDriverWait(driver, 10).until(EC.alert_is_present())
if "delete" in confirm.text.lower():
confirm.dismiss() # Cancel the destructive operation
else:
confirm.accept() # Continue when the message is not destructive
A confirm dialog normally offers OK and Cancel. Use accept() for OK and dismiss() for Cancel; do not infer the result from a screenshot when the alert text is available.
Prompt: send text before accepting
driver.find_element(By.ID, "ask-name").click()
prompt = WebDriverWait(driver, 10).until(EC.alert_is_present())
prompt.send_keys("Selenium")
prompt.accept()
send_keys() supplies the prompt value. Calling dismiss() leaves the prompt canceled instead.
Rank #2
Handle an alert that may not appear
Optional alerts are a normal branch: a validation error may appear only for invalid data, or a browser policy may suppress a dialog. Do not access driver.switch_to.alert blindly. Use a short explicit wait and catch NoAlertPresentException only around the alert operation.
from selenium.common.exceptions import NoAlertPresentException, TimeoutException
trigger = driver.find_element(By.ID, "maybe-alert")
trigger.click()
try:
optional_alert = WebDriverWait(driver, 3).until(EC.alert_is_present())
except TimeoutException:
optional_alert = None
if optional_alert is not None:
try:
print(optional_alert.text)
optional_alert.accept()
except NoAlertPresentException:
# The page closed it between the wait and this operation.
pass
# Continue with the test's non-alert path
Keep the exception scope narrow. A broad catch can hide a real failure, such as a click that never triggered the expected dialog.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesClose a popup tab or window
A new tab or window is a separate browsing context, not an Alert object. Save the original handles before clicking, wait until the count increases, identify the new handle, and switch before locating any elements.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
original_handles = set(driver.window_handles)
driver.find_element(By.CSS_SELECTOR, "a[target='_blank']").click()
wait.until(EC.new_window_is_opened(original_handles))
new_handle = next(
handle for handle in driver.window_handles
if handle not in original_handles
)
driver.switch_to.window(new_handle)
# The lookup must occur after switching to the popup page.
title = wait.until(EC.visibility_of_element_located((By.TAG_NAME, "h1"))).text
print(title)
driver.close() # Close only the current popup
remaining = [h for h in driver.window_handles if h != new_handle]
if remaining:
driver.switch_to.window(remaining[0])
If the application can open several windows, record the handle set again after each action and select the handle that was not present before. Never assume list order is stable. If the popup is the only remaining window, do not call switch_to.window() with a closed handle; end the session or switch to a handle that still exists.
Waiting by count instead
before = len(driver.window_handles)
driver.find_element(By.ID, "open-report").click()
wait.until(EC.number_of_windows_to_be(before + 1))
This is useful when you need only the count, while comparing handle sets is safer when other windows may already be open.
Rank #3
Close an HTML modal or cookie banner
Many consent panels and sign-up dialogs are ordinary <div> elements. Inspect the page and choose a stable identifier such as an ID, data-* attribute, role, or accessible name. Wait for clickability, click the real control, and verify that the modal is hidden or removed.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
close_button = wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button[aria-label='Close']")
))
close_button.click()
wait.until(EC.invisibility_of_element_located(
(By.CSS_SELECTOR, ".modal")
))
For a consent banner, target the actual accept or reject button rather than deleting the banner with JavaScript. Clicking exercises the site’s state and consent handlers, which makes the test representative of a real visitor.
When the modal is inside an iframe
If inspection shows the controls inside an iframe, switch into that frame before locating the button, then return to the main document:
frame = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "iframe.consent")))
driver.switch_to.frame(frame)
wait.until(EC.element_to_be_clickable((By.ID, "reject"))).click()
driver.switch_to.default_content()
A locator that works in the top document will fail while the control is inside a frame, and vice versa.
Browser and operating-system dialogs
Notification, camera, microphone, geolocation, and download permissions may be controlled by Chrome-specific capabilities or permissions configured before navigation. Set those policies in the driver options where the Selenium and Chrome versions support them.
A toolbar bubble, certificate chooser, HTTP-authentication surface, download shelf, or native operating-system dialog is outside the page DOM and is not handled by switch_to.alert. If a supported Chrome capability cannot suppress or configure it, use a test-environment policy or a separate desktop-automation tool. Design tests to avoid relying on pixel coordinates because browser UI varies with operating-system, display, and Chrome settings.
Rank #4
Synchronization patterns that prevent flaky popup tests
- Perform the click or navigation that creates the surface before waiting for it.
- Use a condition specific to the surface:
alert_is_present(),new_window_is_opened(),number_of_windows_to_be(), visibility, clickability, or invisibility. - Use a timeout long enough for the environment but short enough to expose failures quickly; keep a shorter wait for an optional dialog.
- Read alert text before closing when the message matters to the test.
- Use stable, accessible locators for HTML controls instead of brittle class names generated by a framework.
- After closing a window, switch to a handle that still exists.
- Keep each wait and exception scoped to one expected transition so unrelated failures are not swallowed.
Troubleshooting common failures
NoAlertPresentException
The dialog may not have been triggered, may have already closed, or may be an HTML modal. Confirm the triggering click succeeded, wait with EC.alert_is_present(), and inspect the DOM before changing the API.
UnexpectedAlertPresentException
An alert is blocking a command that tried to interact with the page. Handle the alert immediately after the action that creates it, and configure the session’s unhandled-prompt behavior only when that policy matches the test.
The locator cannot find the popup button
Check whether the control is in an iframe, shadow DOM, or a different window. Switch to the correct context first, then use an accessible name, ID, role, or stable data attribute.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11The new-window wait times out
The click may have been intercepted, the site may reuse the current tab, or a popup blocker may prevent opening. Verify the post-click URL and handle count, and test the link’s behavior in the same Chrome profile and policy used by automation.
Click intercepted or element not clickable
A loading layer, animation, or another modal may cover the control. Wait for clickability, wait for the covering element to become invisible, and avoid forcing a JavaScript click unless bypassing presentation is explicitly the test objective.
Best Value
Chrome permission prompts keep returning
Set the relevant permission or preference before navigation, use a clean profile appropriate for the test, and verify that the prompt is browser UI rather than a page-rendered imitation.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.End-to-end example with all three web popup types
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
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
try:
driver.get("https://your-test-site.example/demo")
# JavaScript alert
driver.find_element(By.ID, "alert").click()
alert = wait.until(EC.alert_is_present())
assert "notice" in alert.text.lower()
alert.accept()
# HTML modal
driver.find_element(By.ID, "open-modal").click()
wait.until(EC.element_to_be_clickable((By.ID, "close-modal"))).click()
wait.until(EC.invisibility_of_element_located((By.ID, "modal")))
# New window
old = set(driver.window_handles)
driver.find_element(By.ID, "open-window").click()
wait.until(EC.new_window_is_opened(old))
popup = next(h for h in driver.window_handles if h not in old)
driver.switch_to.window(popup)
wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
driver.close()
driver.switch_to.window(next(iter(old)))
finally:
driver.quit()
Or skip the browser setup
If your goal is a clean screenshot rather than interacting with a dialog in a test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF, while its capture flow accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. Each step can be turned off.
Recommended Free Tools
Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for all options, including full-page lazy-image capture, CSS-selector element capture, device and retina settings, custom CSS and JavaScript, click and wait conditions, request blocking, headers and cookies, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, usage data, and PDF controls.
The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account to try it.
Quick decision checklist
- Is it a JavaScript alert, confirm, or prompt? Wait with
alert_is_present()and use the Alert API. - Did a separate tab or window open? Compare
window_handles, switch context, then locate elements. - Is it rendered in the page? Treat it as DOM, possibly switching into an iframe first.
- Is it Chrome or OS chrome? Configure supported permissions or use separate desktop tooling.
- Can it be optional? Use a short wait and a narrow exception branch.
Frequently Asked Questions
Can Selenium close a Chrome notification bubble with switch_to.alert?
No. switch_to.alert is for web alert, confirm, and prompt dialogs created by page JavaScript. A Chrome notification bubble is browser UI and requires supported Chrome configuration, a test policy, or separate desktop automation.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Why does my popup button locator work only after switching windows?
Selenium searches the current browsing context. A newly opened tab has its own document, so wait for its handle, call switch_to.window() with that handle, and only then locate the button.
Should I remove an HTML modal with JavaScript?
Usually no. Clicking the site’s close, accept, or reject control tests the behavior and state changes a real user would produce. Use DOM removal only when bypassing presentation is explicitly the purpose of the test.
Quick Recap
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.

