What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The correct Selenium method 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; use normal DOM locators for an HTML modal or cookie banner. Chrome permission bubbles and operating-system dialogs are outside the page DOM and require Chrome configuration or separate desktop automation.
Identify the pop-up before writing code
“Pop-up” describes several different surfaces. Classifying it first prevents the most common error—calling the Alert API for something that is not a web alert.
| Surface | What Selenium sees | Correct approach |
|---|---|---|
| JavaScript alert, confirm or prompt | An active WebDriver alert | Wait with EC.alert_is_present(), then use accept(), dismiss(), text or send_keys(). |
| New tab or window | A second window handle | Save the original handles, wait for a new handle, switch with switch_to.window(). |
| HTML modal or cookie banner | Ordinary page elements such as <div> and <button> |
Locate and click the control, then wait for the modal to disappear. |
| Chrome permission bubble or OS dialog | Browser or desktop UI, not page DOM | Set supported Chrome permissions before navigation or use a separate desktop-automation tool. |
Always trigger the action that creates the surface before waiting for it. Prefer explicit waits to a fixed time.sleep(); the wait synchronizes with the browser event and is usually faster when the event happens early.
Prerequisites and a reusable Selenium setup
Install Selenium in the Python environment used by your test:
python -m pip install -U selenium
Recent Selenium releases can manage a compatible ChromeDriver automatically. If your environment manages drivers separately, ensure ChromeDriver and Chrome are compatible.
#1 Best Overall
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 NoAlertPresentException, TimeoutException
options = webdriver.ChromeOptions()
# options.add_argument("--headless=new") # enable when a visible browser is unnecessary
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
try:
driver.get("https://example.com")
# perform the action that may open a dialog here
finally:
driver.quit()
Use a try/finally block so a failed assertion or wait does not leave Chrome processes running.
Close JavaScript alert, confirm and prompt dialogs
Selenium WebDriver has built-in support for popup dialog boxes. The active dialog is exposed through driver.switch_to.alert, but accessing it before the page creates it raises an error. The reliable pattern is an explicit wait with EC.alert_is_present().
Accept an alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Trigger the alert first, for example by clicking a button.
driver.find_element(By.ID, "show-alert").click()
alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
message = alert.text
print(message)
alert.accept()
alert() has only a message and an OK button. Read text before accepting if the test must verify the message.
Accept or dismiss a confirmation
driver.find_element(By.ID, "delete-account").click()
confirm = WebDriverWait(driver, 10).until(EC.alert_is_present())
if "delete" in confirm.text.lower():
confirm.dismiss() # choose Cancel for this test case
else:
confirm.accept() # choose OK for another message
accept() presses OK; dismiss() presses Cancel or the dialog’s close action. The application may take a different path after each choice, so assert the resulting page state.
Rank #2
Enter text in a prompt
driver.find_element(By.ID, "ask-name").click()
prompt = WebDriverWait(driver, 10).until(EC.alert_is_present())
prompt.send_keys("Selenium")
prompt.accept()
Call send_keys() before accepting. If the prompt should be cancelled, omit text and call dismiss().
Handle an optional alert
If the dialog is conditional, wait briefly and branch instead of blindly reading driver.switch_to.alert:
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 →from selenium.common.exceptions import TimeoutException
try:
optional = WebDriverWait(driver, 3).until(EC.alert_is_present())
except TimeoutException:
optional = None
if optional is not None:
print(optional.text)
optional.dismiss()
You can also catch NoAlertPresentException around a narrowly scoped alert operation, but an explicit wait communicates the expected synchronization more clearly. Do not catch the exception around an entire test; that can hide an actual application failure.
Close a pop-up that opened a new tab or window
A link opened with target="_blank" does not create an Alert object. Selenium exposes each browsing context through driver.window_handles. Save the original set before clicking, wait until the count increases, then switch before locating elements on the new page.
Rank #3
from selenium.webdriver.common.by import By
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.open-popup").click()
WebDriverWait(driver, 10).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 happen after switching contexts.
heading = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.TAG_NAME, "h1"))
)
print(heading.text)
driver.close()
remaining = [h for h in driver.window_handles if h != new_handle]
if remaining:
driver.switch_to.window(remaining[0])
For a test that expects an exact total, EC.number_of_windows_to_be(2) is useful. For multiple possible windows, compare the sets as shown above. Never assume the new handle is at index 1; handle order is not a contract.
Common window-handling mistakes
- Searching too early: element lookup still runs in the original window until
switch_to.window(new_handle)succeeds. - Closing the wrong context: confirm the current handle before calling
close(). - Forgetting to return: after closing, switch to a handle that still exists before continuing the test.
- Waiting for a handle before clicking: the action that opens the window must occur first.
Close an HTML modal or cookie banner
Many marketing dialogs, newsletter forms and cookie notices are rendered as HTML. They may look like browser pop-ups but are ordinary DOM elements, so switch_to.alert will never find them.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
close_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button[aria-label='Close']")
)
)
close_button.click()
WebDriverWait(driver, 10).until(
EC.invisibility_of_element_located((By.CSS_SELECTOR, ".modal"))
)
Prefer stable attributes such as an ID, data-* attribute, ARIA label, role or accessible name. Avoid brittle selectors based on generated class names. If the banner has separate consent choices, click the real accept or reject control rather than removing the element with JavaScript. Clicking exercises the site’s state and consent handlers; deleting the node only hides the presentation.
When the modal is inside an iframe
A consent provider may render its controls inside an iframe. In that case, wait for the frame and switch into it before finding the button, then switch back:
frame = WebDriverWait(driver, 10).until(
EC.frame_to_be_available_and_switch_to_it(
(By.CSS_SELECTOR, "iframe[title='Consent']")
)
)
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button.accept"))
).click()
driver.switch_to.default_content()
The selector and iframe title are site-specific; inspect the page rather than assuming this example’s values.
Rank #4
Chrome permission prompts and operating-system dialogs
Notifications, camera, microphone, geolocation and downloads can involve Chrome permission UI. Configure supported Chrome capabilities or permissions before navigation when your Selenium version exposes the required setting. Chrome’s browser-specific functionality documentation is the appropriate reference for those options.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallA toolbar bubble, certificate chooser, download shelf, HTTP-authentication surface or operating-system dialog is not a page element and is not a JavaScript alert. driver.switch_to.alert cannot control it. Use a test-environment policy, Chrome configuration, or a desktop-automation tool where supported; do not waste time changing DOM selectors.
Synchronization, reliability and performance
Use the narrowest explicit condition
EC.alert_is_present()for an active JavaScript dialog.EC.new_window_is_opened(handles)orEC.number_of_windows_to_be(n)for browsing contexts.EC.visibility_of_element_located()when a modal must be visible.EC.element_to_be_clickable()for a control that must receive a click.EC.invisibility_of_element_located()after closing a modal.
Set the timeout to the slowest legitimate environment rather than adding arbitrary sleeps. Keep waits local to the event they synchronize; a ten-second global sleep slows every test even when the dialog appears immediately.
Make cleanup deterministic
Capture dialog text before closing, assert the expected outcome after accepting or dismissing, and always quit the driver in teardown. For parallel tests, give each test its own driver and avoid sharing window handles.
Best Value
Troubleshooting Chrome pop-up failures
| Symptom | Likely cause | Fix |
|---|---|---|
NoAlertPresentException |
The surface is an HTML modal, the action did not trigger an alert, or the code ran too soon. | Classify the surface, trigger first, and wait with EC.alert_is_present(). |
| Wait for alert times out | The dialog is optional, blocked by another element, or the application uses a custom modal. | Inspect the resulting DOM and branch for an absent optional alert. |
| Elements from the new tab are not found | The driver is still focused on the original window. | Wait for the new handle and call switch_to.window() before locating elements. |
| Close button is not clickable | The modal is still animating, covered by an overlay, inside an iframe, or the locator is unstable. | Wait for clickability, switch into the iframe if needed, and use a stable accessible locator. |
| Chrome permission bubble remains | It is browser UI, not page DOM. | Set the permission before navigation or use supported desktop automation. |
| Test hangs after a popup test | A window was closed without switching back, or the driver was not quit. | Switch to a remaining handle and put driver.quit() in finally. |
Complete example that handles all three web surfaces
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://example.com/test-page")
# JavaScript dialog, if this page's action creates one.
driver.find_element(By.ID, "show-alert").click()
try:
alert = wait.until(EC.alert_is_present())
except TimeoutException:
alert = None
if alert:
print(alert.text)
alert.accept()
# New tab/window.
before = set(driver.window_handles)
driver.find_element(By.CSS_SELECTOR, "a.open-popup").click()
wait.until(EC.new_window_is_opened(before))
popup = next(h for h in driver.window_handles if h not in before)
driver.switch_to.window(popup)
print(wait.until(EC.visibility_of_element_located((By.TAG_NAME, "h1"))).text)
driver.close()
driver.switch_to.window(next(iter(before)))
# HTML modal.
wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button[aria-label='Close']")
)).click()
wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".modal")))
finally:
driver.quit()
Replace the example selectors with controls from the application under test. The important part is the separation of alert, window and DOM logic.
Or skip the browser setup
If your goal is a clean image or PDF rather than interactive browser testing, ScreenshotNeo provides a single screenshot API call. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response reports the result in X-Page-Verdict and X-Billed headers.
Use the API documentation at https://screenshotneo.com/docs/ for options such as full-page lazy-image loading, CSS-selector element capture, device and viewport settings, dark mode, custom CSS or JavaScript, click-before-capture, waits, request blocking, cookies, headers, geolocation, PDF output, resizing, caching, signed links, asynchronous jobs and bulk capture.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for the free plan.
Frequently Asked Questions
Can Selenium close a popup without accepting it?
Yes. For a JavaScript confirm or prompt, call dismiss(); for a new window, switch to its handle and call close(); for an HTML modal, click its cancel or close control.
Why does a popup work locally but fail in headless Chrome?
Headless mode can change timing, viewport layout and permission behavior. Keep explicit waits, set a realistic window size, and configure permissions before navigation rather than relying on a visible browser bubble.
Should I use JavaScript to remove a stubborn modal?
Only when the test is specifically about bypassing presentation. For functional tests, click the site’s actual control so consent, focus and application state handlers run.
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.

