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

For a native JavaScript confirm() dialog, wait until the alert exists, switch to it, call getText(), and only then choose accept() or dismiss(). The dialog is browser chrome, not a DOM element, so searching the page with a CSS selector will not find its message.

await driver.wait(until.alertIsPresent());
const alert = await driver.switchTo().alert();
const message = await alert.getText();
await alert.dismiss();

The correct Selenium JavaScript sequence

Selenium’s WebDriver alert interface handles native JavaScript alert, confirm, and prompt dialogs. The official documentation says WebDriver can retrieve popup text and accept or dismiss these dialogs. In the JavaScript binding, Alert.getText() returns a promise resolving to the message currently displayed.

  1. Trigger the action that calls window.confirm().
  2. Wait for an alert with until.alertIsPresent().
  3. Switch to it with driver.switchTo().alert().
  4. Read the message with await alert.getText().
  5. Assert, log, or store the string.
  6. Choose the test outcome with accept() or dismiss().

Read the text before closing the dialog. Once accepted or dismissed, that alert no longer exists.

See Selenium’s alerts documentation and the JavaScript Alert API for the binding’s current method behavior. The alerts documentation was marked last modified September 16, 2026.

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

Complete JavaScript example

Runnable test with a native confirm dialog

Install Selenium’s JavaScript package with npm install selenium-webdriver, and make sure a compatible Chrome browser and ChromeDriver are available to your environment. This example creates a page, clicks a button that invokes confirm(), verifies the exact message, and dismisses the confirmation.

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

(async function readConfirmationText() {
  const driver = await new Builder().forBrowser('chrome').build();

  try {
    const html = `<!doctype html>
      <button id="delete" onclick="confirm('Delete item?')">Delete</button>`;
    await driver.get('data:text/html;charset=utf-8,' + encodeURIComponent(html));

    await driver.findElement(By.id('delete')).click();
    await driver.wait(until.alertIsPresent(), 10000);

    const alert = await driver.switchTo().alert();
    const message = await alert.getText();

    if (message !== 'Delete item?') {
      throw new Error(`Unexpected confirmation text: ${message}`);
    }

    console.log('Confirmation text:', message);
    await alert.dismiss();                 // choose Cancel
    // Use await alert.accept() to choose OK instead.
  } finally {
    await driver.quit();
  }
})();

getText() is asynchronous, so omitting await leaves you with a promise rather than the displayed string. The application controls the wording; “Delete item?” is only the text generated by this example, not a universal Selenium message.

Waiting reliably for the dialog

Why an explicit wait matters

A click can return before the browser has exposed the resulting dialog to WebDriver. Calling switchTo().alert() immediately can therefore raise a no-alert-present error. until.alertIsPresent() polls until the dialog is available or the timeout expires.

await driver.findElement(By.css('button.confirm')).click();
await driver.wait(until.alertIsPresent(), 10000);
const alert = await driver.switchTo().alert();
const text = await alert.getText();
await alert.accept();

Set the timeout to match your application’s normal response time, but keep it finite so a missing dialog fails clearly instead of hanging the test. If the click itself is asynchronous, wait for the button to be interactable first and then wait separately for the alert.

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

Preserving whitespace and line breaks

Compare the returned value to the application’s real string. Do not assume capitalization, punctuation, or whitespace. If the application deliberately includes line breaks, assert those characters or use a narrowly scoped normalization such as trimming outer whitespace; avoid broad transformations that could hide a wording regression.

Accepting or dismissing after reading

Method Effect Use when
accept() Activates the affirmative action (usually OK). The test should proceed with the confirmed operation.
dismiss() Cancels the confirmation (usually Cancel). The test should verify the operation is abandoned.

Both methods return promises in the JavaScript binding, so await them. Capture the text first, then close the dialog. A confirm dialog has no text-entry field; do not call sendKeys() on it.

Alert, confirm, and prompt are different cases

Dialog created by the page Read text Next action
alert('Message') await alert.getText() await alert.accept()
confirm('Message') await alert.getText() accept() for OK or dismiss() for Cancel
prompt('Question') await alert.getText() Use sendKeys(value) for the response, then accept or dismiss

The same alert object exposes the message for all three native dialog types. Only prompts accept input. Selenium’s API reference documents sendKeys() for prompt responses and does not support it for alert or confirm dialogs.

Python Selenium equivalent

Python uses the same WebDriver alert concept but exposes the message as the text property. Selenium’s documented wait pattern uses WebDriverWait and EC.alert_is_present().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

 driver = webdriver.Chrome()
try:
    driver.get("https://example.test/confirm-page")
    driver.find_element("css selector", "button.confirm").click()

    alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
    message = alert.text
    assert message == "Delete item?"
    alert.dismiss()
finally:
    driver.quit()

Remove the accidental leading space before driver = if you paste this into a file; it is shown indented here only for readability. In normal Python code, the statements inside try should be indented consistently.

Binding Retrieve message Wait
JavaScript await alert.getText() await driver.wait(until.alertIsPresent())
Python alert.text WebDriverWait(...).until(EC.alert_is_present())

Reusable JavaScript helper

Centralizing the sequence keeps individual tests focused on their expected wording and outcome.

async function readAndCloseConfirm(driver, expectedText, outcome = 'dismiss') {
  await driver.wait(until.alertIsPresent(), 10000);
  const alert = await driver.switchTo().alert();
  const actualText = await alert.getText();

  if (expectedText !== undefined && actualText !== expectedText) {
    // Close the modal before failing so the session remains usable for cleanup.
    await alert.dismiss();
    throw new Error(`Expected "${expectedText}", got "${actualText}"`);
  }

  if (outcome === 'accept') {
    await alert.accept();
  } else if (outcome === 'dismiss') {
    await alert.dismiss();
  } else {
    throw new Error(`Unknown outcome: ${outcome}`);
  }

  return actualText;
}

// Example:
const text = await readAndCloseConfirm(driver, 'Delete item?', 'accept');

The helper returns the captured string while making the decision explicit. If a failed assertion should leave the dialog open for debugging, move the close operation into a cleanup block instead.

Common failures and fixes

“No such alert” or “no alert present”

  • Cause: The test switched too soon, the click did not trigger a native dialog, or the dialog already closed.
  • Fix: Verify the click target, wait with until.alertIsPresent(), and check that the page calls native alert(), confirm(), or prompt().

The test times out waiting for an alert

  • Cause: The expected dialog is conditional, blocked by validation, or implemented as HTML.
  • Fix: Reproduce the action manually, inspect the page’s event flow, and test the condition that should invoke confirm(). For an HTML modal, locate its elements instead of using the alert API.

The value is a promise instead of text

  • Cause: JavaScript’s asynchronous API was called without await.
  • Fix: Use const text = await alert.getText() inside an async function.

Calling sendKeys() fails

  • Cause: A confirm or alert dialog has no input control.
  • Fix: Use sendKeys() only for a prompt, then call accept() or dismiss().

The text assertion is unexpectedly different

  • Cause: The application changed punctuation, localization, capitalization, or line breaks.
  • Fix: Log the returned string, compare the exact intended locale, and update the expected value only after confirming the product requirement.

A later test starts with an unexpected alert

  • Cause: A previous test left a dialog open or an application event triggered another one.
  • Fix: Always close the handled alert, use a finally block for driver cleanup, and isolate tests that intentionally leave dialogs open.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Native dialogs versus custom HTML modals

A native JavaScript dialog is rendered by the browser and is exposed through switchTo().alert(). A custom modal built with a div, dialog component, or framework library is ordinary page content. Handle it with normal Selenium locators, for example:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const modal = await driver.findElement(By.css('[role="dialog"]'));
const message = await modal.findElement(By.css('.message')).getText();
await modal.findElement(By.css('button.cancel')).click();

Do not mix the two approaches. If until.alertIsPresent() never succeeds but a visible overlay appears in the DOM, inspect that overlay’s markup and accessibility attributes.

Or skip the browser setup

ScreenshotNeo is a website screenshot API, not a replacement for Selenium’s alert interface: it cannot return the internal string from a native confirmation dialog for an assertion. It is useful when you need a visual capture of a test page, documentation page, or rendered state without maintaining browser-launch code. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Make a screenshot with one GET request; see the ScreenshotNeo documentation for all options.

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

The same request in 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)

And in 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}`);

Every plan includes the full feature set, including full-page and element captures, device and retina settings, PDF output, custom CSS and JavaScript, waits, request blocking, cookies and headers, geolocation, caching, signed links, asynchronous jobs, bulk capture, usage reporting, and an OpenAPI specification. 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 test design

  • Assert the message when wording is part of the user-facing contract; otherwise assert a stable, intentional substring or localization key through the application layer.
  • Keep the alert timeout separate from page-load and element timeouts so failures identify the waiting stage.
  • Record the message in a test failure while avoiding sensitive data that the page might place in a prompt.
  • Close every dialog in the same test that opened it, and quit the driver in cleanup code.
  • Use the native alert API only for browser dialogs; use locators and accessibility checks for HTML modals.

Frequently Asked Questions

Can Selenium read a confirmation dialog without clicking the button that opens it?

No. Selenium must first perform the action that causes the page to call confirm(); then wait for the resulting alert and switch to it.

Can one test handle several confirmations in sequence?

Yes. Read and close the current alert, perform the next action, wait for the next alert, and repeat. Only one native dialog is active at a time.

Does the message returned by Selenium include the dialog buttons?

No. getText() (or Python’s text property) returns the displayed message, not the browser’s OK, Cancel, or prompt controls.

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.