PRACTICAL GUIDE / handle alerts in Selenium
Handle Alerts in Selenium: Complete Guide
Handle alerts in Selenium with examples for accept, dismiss, prompt text, explicit waits, unexpected alerts, browser prompts, and common mistakes in CI.
In this guide8 sections
- Identify What Actually Opened
- Wait for the Alert Before Switching
- Test Alert, Confirm, and Prompt Branches
- Simple alert
- Confirmation dialog
- Prompt dialog
- Assert the Consequence, Not Only the Dialog
- Recover From Unexpected Alerts Without Hiding Defects
- Prevent Timing and Focus Mistakes
- Design Data for Destructive Dialogs
- Use a Focused Alert Test Checklist
What you will learn
- Identify What Actually Opened
- Wait for the Alert Before Switching
- Test Alert, Confirm, and Prompt Branches
- Assert the Consequence, Not Only the Dialog
A JavaScript alert stops the browser's normal interaction flow. Until it is accepted or dismissed, Selenium cannot click the page behind it. That blocking behavior is useful when the alert is expected and baffling when it appears halfway through an unrelated test.
Reliable alert coverage has two parts: switch to the dialog at the right time, then verify what the application does after the user's choice. Calling accept() is only an interaction. The test earns its value by checking the message, the branch selected, and the resulting page state.
Identify What Actually Opened
Selenium's Alert interface handles browser-native JavaScript dialogs created by alert(), confirm(), and prompt(). It does not handle every UI that looks like a popup.
| UI interruption | How to recognize it | Selenium approach |
|---|---|---|
| JavaScript alert | Browser-native dialog, page is blocked | driver.switch_to.alert |
| HTML modal | Elements appear in DOM | Normal locators and waits |
| Browser permission prompt | Browser chrome asks for camera or location | Browser profile/options or DevTools support |
| File chooser | Native file selection window | Send file path to <input type="file"> |
| HTTP authentication | Browser credentials challenge | Browser-specific configuration or supported URL/auth approach |
| OS notification | Outside browser content | Platform tooling, not DOM Selenium commands |
Inspect the DOM while the “popup” is visible. If you can locate its buttons as HTML, it is a modal, not an alert. Trying to switch to an HTML modal raises NoAlertPresentException. Trying to locate a JavaScript alert with CSS waits forever because it is not part of the document.
Wait for the Alert Before Switching
An alert triggered by an immediate button handler may appear quickly on a laptop and later after validation or a network response in CI. Switch only after an explicit condition confirms its presence.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
try:
driver.get("https://example.test/account")
driver.find_element(By.ID, "delete-account").click()
alert = wait.until(EC.alert_is_present())
assert alert.text == "Delete your account permanently?"
alert.accept()
confirmation = wait.until(
EC.visibility_of_element_located((By.ID, "account-deleted"))
)
assert confirmation.text == "Your account was deleted"
finally:
driver.quit()alert_is_present() returns the alert object, so there is no need to switch a second time. Repeated calls can race with code that already closed the dialog.
Keep the alert wait close to the action expected to trigger it. A global helper that waits for any alert after every click slows the suite and can normalize defects that should fail loudly.
Test Alert, Confirm, and Prompt Branches
All three dialog types use the same Selenium interface, but the product decisions differ.
Simple alert
A simple alert has one acceptance path. Verify the exact or intentionally variable message, accept it, then assert the page is usable again.
alert = wait.until(EC.alert_is_present())
assert "Session saved" in alert.text
alert.accept()Avoid weak checks such as assert alert.text. Any non-empty error message would pass.
Confirmation dialog
A confirmation presents two business branches. Test both when they have meaningful consequences. For a delete action, acceptance should remove the record, while dismissal should preserve it.
driver.find_element(By.ID, "remove-item").click()
wait.until(EC.alert_is_present()).dismiss()
item = wait.until(EC.visibility_of_element_located((By.ID, "item-42")))
assert item.is_displayed()Do not handle accept and dismiss in the same test if one branch destroys data needed by the other. Separate cases with independent setup are easier to rerun.
Prompt dialog
A prompt accepts text before acceptance. Verify how the application treats ordinary, empty, long, and special-character input according to its requirements.
driver.find_element(By.ID, "rename-list").click()
prompt = wait.until(EC.alert_is_present())
assert prompt.text == "Enter a new list name"
prompt.send_keys("Release blockers")
prompt.accept()
heading = wait.until(EC.visibility_of_element_located((By.ID, "list-name")))
assert heading.text == "Release blockers"send_keys() is relevant only when the dialog provides an input. Sending text to a simple alert does not convert it into a prompt.
Assert the Consequence, Not Only the Dialog
An alert can display correct copy while the underlying action fails. Conversely, the correct action can occur even if the warning text is misleading. Cover both contracts.
For each case, record:
- the action that should trigger the dialog;
- the expected message or stable part of dynamic copy;
- the user's choice, including prompt input;
- the expected server or UI state after that choice;
- whether focus and interaction return to the correct page.
For destructive actions, confirm the server result through a visible refresh or an API query if the test architecture supports it. A removed row alone might be an optimistic UI update that later rolls back.
If alert text contains a generated order number, compare the stable structure and independently known value. Do not reduce the assertion to a vague substring simply because the message is dynamic.
Recover From Unexpected Alerts Without Hiding Defects
An unexpected alert often points to a real product condition: session timeout, unsaved changes, validation failure, duplicate submission, or an environment banner. Automatically accepting it in a broad exception handler can push the test down a path no user selected.
Capture evidence before deciding what to do:
from selenium.common.exceptions import UnexpectedAlertPresentException
try:
driver.find_element(By.ID, "continue").click()
except UnexpectedAlertPresentException:
alert = wait.until(EC.alert_is_present())
message = alert.text
alert.dismiss()
raise AssertionError(f"Unexpected browser alert: {message}")This dismissal is cleanup, not recovery. The test still fails and reports the message. If a known optional alert is valid in one environment, model that choice explicitly and assert why it is allowed. Do not create a generic closeAnyAlert() called from teardown, because the screenshot and browser state may be the best clues to the original failure.
WebDriver also has an unhandled prompt behavior capability. Its values can dismiss, accept, ignore, or notify when an unexpected prompt blocks a command. Configure it intentionally for the browser and binding you use. It is a last line of session behavior, not a replacement for testing dialogs your application deliberately opens.
Prevent Timing and Focus Mistakes
Most alert failures fall into a few recognizable patterns:
| Symptom | Likely mistake | Better response |
|---|---|---|
NoAlertPresentException | Switched too early or twice | Wait once and retain returned alert |
UnexpectedAlertPresentException | Another command ran while alert was open | Handle the expected dialog immediately |
| Test hangs after click | Popup is HTML, not JavaScript | Inspect DOM and use element waits |
| Wrong window after closing | Trigger occurred in a new tab/window | Track window handles separately |
| Passes locally, fails headless | Different trigger timing or environment message | Save alert text and browser logs |
| Prompt value missing | Text sent after acceptance | Send text before accept() |
An implicit wait does not solve alert synchronization. It applies to element searches, not every WebDriver operation. Use the alert-specific expected condition.
Alerts also belong to the current browsing context. If an action in an iframe triggers one, Selenium still handles the browser alert through the driver. After it closes, confirm whether you must switch out of the frame before locating the next page element.
Design Data for Destructive Dialogs
Delete confirmations and irreversible actions need isolated data. Create a fresh record for each test, capture its ID, and avoid a shared account that multiple CI workers can delete from simultaneously.
A good pair of tests might be:
- Create record A, request deletion, dismiss, verify A remains.
- Create record B, request deletion, accept, verify B is absent from both UI and API.
This structure avoids test ordering and makes cleanup straightforward. If test two fails after deletion succeeds, teardown should tolerate the record already being absent.
For browser alerts caused by beforeunload, do not assert exact browser-generated wording. Browsers may control that text. Assert the product behavior around dirty state: navigation is blocked or allowed according to the user's choice, and saved data has the expected value.
Use a Focused Alert Test Checklist
Before committing an alert case, verify the popup is truly JavaScript-native, wait with alert_is_present(), assert meaningful message content, choose accept or dismiss deliberately, and check the resulting application state. Save the alert text when an unexpected prompt occurs, and keep browser permissions or HTML modals in separate handling code.
Start by implementing one confirmation with two independent tests, one for cancellation and one for acceptance. Run both in headed and CI browser modes. If they fail, use the exception type and captured message to identify the dialog layer before changing waits. That habit prevents most alert “fixes” from becoming silent defect suppressors.
// FIELD DISPATCH
Get the QA Field Notes
Weekly QA battles, AI testing guides, and interview drills. Free on Substack.
// LIVE COURSE / THE TESTING ACADEMY
Playwright Automation Mastery
Go beyond Selenium. Master Playwright with JS/TS in 90 days.
From the instructor behind this guide.
Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.
PRIMARY REFERENCES
Verify the details at the source
QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.
- 01Selenium documentation
Selenium Project
Canonical WebDriver, Grid, waits, element, and browser automation guidance.
- 02WebDriver standard
W3C
The browser automation protocol specification behind WebDriver implementations.
FAQ / QUICK ANSWERS
Questions testers ask
How do you handle alerts in Selenium?
Use WebDriverWait with expected_conditions.alert_is_present, then switch to the alert with driver.switch_to.alert. After that you can read text, accept, dismiss, or send text for prompt alerts. Always wait for the alert before switching.
What is the difference between alert, confirm, and prompt?
An alert shows a message and usually has OK. A confirm dialog usually has OK and Cancel. A prompt accepts text input before OK or Cancel. Selenium handles all three through the Alert interface.
Why do I get NoAlertPresentException?
NoAlertPresentException appears when Selenium tries to switch before the browser alert exists or after it has already been handled. Add an explicit wait, remove duplicate handling, and confirm the action really triggers a JavaScript alert.
Can Selenium handle browser permission popups?
JavaScript alerts are handled with switch_to.alert. Browser permission prompts, file pickers, authentication dialogs, and OS level popups often need browser options, profiles, DevTools support, or separate tooling depending on the browser.
How do I handle unexpected alerts in Selenium?
Capture the alert text, decide whether the test should accept or fail, then fix the flow that caused the surprise. Unexpected alerts often indicate validation, session timeout, or unsaved changes behavior that needs explicit coverage.
RELATED GUIDES
Continue the learning route
GUIDE 01
Selenium vs Playwright vs Cypress in 2026
Compare Selenium vs Playwright vs Cypress in 2026 for speed, browsers, CI, flakiness, ecosystem, and which web automation framework beginners should choose.
GUIDE 02
Implicit vs Explicit Waits in Selenium
Compare implicit vs explicit waits in Selenium with clear examples, timing rules, common pitfalls, and reliable patterns that reduce flaky tests.
GUIDE 03
How to Handle Dropdowns in Selenium
Learn how to handle dropdowns in Selenium using Select, custom lists, multi-select, dynamic options, keyboard actions, and stable click patterns.
GUIDE 04
CSS Selectors vs XPath: A Cheat Sheet for Testers
Compare CSS selectors vs XPath for test automation, with a cheat sheet, speed notes, Playwright locator advice, and stable data-testid practices.