← Back

Playwright Alert, Dialog & Popup Handling

Learn how Playwright handles JavaScript alerts, confirmations, prompts, browser dialogs, popups and new tabs with real-world automation examples — plus the equivalent Selenium approach.

1. What Are Alerts, Dialogs and Popups?

Modern web applications can display different types of browser interactions. In automation, these interactions must be handled correctly before the test can continue.

Alert Displays an informational message and usually requires the user to click OK.
Confirm Asks the user to accept or cancel an action.
Prompt Displays a message and allows the user to enter text.
Popup / New Tab Opens another browser page or tab after an action.
2. Browser Dialog vs Popup — Important Difference

A JavaScript dialog and a browser popup are not the same thing. Understanding this distinction is very important in Playwright.

User clicks button
→
JavaScript alert()
→
Playwright Dialog
User clicks link
→
New tab / window
→
Playwright Page
Key idea:
JavaScript alert(), confirm() and prompt() are handled through Playwright's dialog object. A new tab or browser window is represented as another Playwright Page.
3. Handle JavaScript Alert in Playwright

Suppose an application contains:

Application JavaScript
function deleteCustomer() {
    alert("Customer deleted successfully");
}

Playwright can listen for the dialog and accept it.

Playwright Python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:

    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    page.goto("https://example.test/customers")

    def handle_dialog(dialog):
        print(dialog.type)
        print(dialog.message)
        dialog.accept()

    page.on("dialog", handle_dialog)

    page.get_by_role("button", name="Delete Customer").click()

    browser.close()
Important: Playwright exposes JavaScript dialogs through the dialog event.
4. Real-Time Example — Delete Customer Alert

Imagine an admin application where deleting a customer displays a JavaScript alert:

Admin opens Customers
→
Click Delete
→
Alert appears
→
Accept
→
Customer deleted
Real-Time Business Scenario
from playwright.sync_api import expect

def test_delete_customer(page):

    page.goto("https://example.test/customers")

    def handle_dialog(dialog):

        assert dialog.type == "alert"

        print("Alert message:", dialog.message)

        dialog.accept()

    page.on("dialog", handle_dialog)

    page.get_by_role(
        "button",
        name="Delete Customer"
    ).click()

    expect(
        page.get_by_text("Customer deleted successfully")
    ).to_be_visible()
Professional tip: Register the dialog handler before performing the action that triggers the dialog.
5. Handle Confirm Dialog

A JavaScript confirmation dialog normally contains OK and Cancel.

JavaScript
function cancelOrder() {

    const result = confirm(
        "Are you sure you want to cancel this order?"
    );

    if (result) {
        console.log("Order cancelled");
    }
}

Accept the confirmation

Playwright
def handle_dialog(dialog):

    print(dialog.type)
    print(dialog.message)

    dialog.accept()

page.on("dialog", handle_dialog)

page.get_by_role(
    "button",
    name="Cancel Order"
).click()

Dismiss the confirmation

Playwright
def handle_dialog(dialog):

    print(dialog.message)

    dialog.dismiss()

page.on("dialog", handle_dialog)

page.get_by_role(
    "button",
    name="Cancel Order"
).click()
6. Real-Time Example — Cancel Order

A common e-commerce workflow is cancelling an order.

Open Order
→
Click Cancel
→
Confirm Dialog
→
Accept
→
Status = Cancelled
Complete Playwright Example
from playwright.sync_api import expect

def test_cancel_order(page):

    page.goto(
        "https://example.test/orders/ORD-1001"
    )

    def handle_dialog(dialog):

        assert dialog.type == "confirm"

        assert (
            "cancel this order"
            in dialog.message.lower()
        )

        dialog.accept()

    page.on("dialog", handle_dialog)

    page.get_by_role(
        "button",
        name="Cancel Order"
    ).click()

    expect(
        page.get_by_text("Cancelled")
    ).to_be_visible()
7. Handle Prompt Dialog

A JavaScript prompt asks the user for text.

JavaScript
const name = prompt(
    "Enter customer name"
);

In Playwright, use dialog.accept("text") to provide a value.

Playwright Python
def handle_dialog(dialog):

    print(dialog.type)
    print(dialog.message)

    dialog.accept("Rahul")

page.on("dialog", handle_dialog)

page.get_by_role(
    "button",
    name="Enter Customer Name"
).click()
Prompt flow:
prompt() → Playwright receives a dialog → dialog.accept("value").
8. Real-Time Example — Enter Reference Number

Consider an order-management application that asks the support engineer for a reference number.

Playwright Python
from playwright.sync_api import expect

def test_enter_reference_number(page):

    page.goto(
        "https://example.test/support"
    )

    def handle_dialog(dialog):

        assert dialog.type == "prompt"

        assert (
            "reference"
            in dialog.message.lower()
        )

        dialog.accept("REF-2026-1001")

    page.on("dialog", handle_dialog)

    page.get_by_role(
        "button",
        name="Enter Reference"
    ).click()

    expect(
        page.get_by_text("REF-2026-1001")
    ).to_be_visible()
9. Inspect Dialog Properties

Playwright provides useful information through the dialog object.

Property / Method Purpose
dialog.type Returns alert, confirm, prompt or beforeunload.
dialog.message Returns the dialog text.
dialog.default_value Returns the default value for a prompt.
dialog.accept() Accepts the dialog.
dialog.accept("value") Accepts a prompt and provides text.
dialog.dismiss() Dismisses the dialog.
10. Handle a Dialog Only for One Action

Sometimes you do not want a permanent dialog listener. You can explicitly wait for the dialog while performing the action.

Playwright Python
with page.expect_dialog() as dialog_info:

    page.get_by_role(
        "button",
        name="Delete"
    ).click()

dialog = dialog_info.value

print(dialog.type)
print(dialog.message)

dialog.accept()
Why this is useful:
expect_dialog() clearly connects the expected dialog with the specific action that triggers it.
11. Popup / New Tab Handling in Playwright

A popup or new tab is different from a JavaScript dialog. Playwright represents a new browser tab as another Page.

Click "Open Report"
→
New Tab Opens
→
Capture Page
→
Validate Report
Playwright Python
with page.expect_popup() as popup_info:

    page.get_by_role(
        "link",
        name="Open Report"
    ).click()

report_page = popup_info.value

report_page.wait_for_load_state()

print(report_page.url)

assert "report" in report_page.url
12. Real-Time Example — Payment Gateway Popup

Payment applications frequently open a separate page or tab for an external payment provider.

Shopping Cart
→
Checkout
→
Pay Now
→
Payment Page
Real-World Playwright Example
from playwright.sync_api import expect

def test_payment_popup(page):

    page.goto(
        "https://example.test/checkout"
    )

    page.get_by_role(
        "button",
        name="Pay Now"
    ).click()

    with page.expect_popup() as popup_info:

        page.get_by_role(
            "link",
            name="Open Payment Gateway"
        ).click()

    payment_page = popup_info.value

    expect(
        payment_page
        .get_by_role("heading", name="Payment")
    ).to_be_visible()

    print(
        "Payment URL:",
        payment_page.url
    )
Important: The exact popup behavior depends on the application. Some payment flows navigate the same page instead of creating a new page. Automate the actual browser behavior of the application.
13. Popup Created by a Button

A common pattern is a button using JavaScript such as window.open().

Application
<button onclick="window.open('/invoice')">
    Open Invoice
</button>

Playwright can capture the new page before the click completes.

Playwright
with page.expect_popup() as popup_info:

    page.get_by_role(
        "button",
        name="Open Invoice"
    ).click()

invoice_page = popup_info.value

expect(
    invoice_page.get_by_text("Invoice")
).to_be_visible()
14. Handle Multiple Pages / Tabs

When an application opens multiple tabs, each tab is represented by a Playwright Page.

Playwright Python
with page.expect_popup() as popup_info:

    page.get_by_role(
        "link",
        name="Customer Portal"
    ).click()

customer_page = popup_info.value

print("Main page:", page.url)
print("Customer page:", customer_page.url)

customer_page.get_by_role(
    "heading",
    name="Customer Portal"
)
Mental model:
Browser → Context → Page → Dialog / Popup.
15. Avoid Fragile Dialog Handling

❌ Avoid

page.get_by_role("button", name="Delete").click() time.sleep(3) # Hope the alert has appeared by now

✅ Preferred

with page.expect_dialog() as dialog_info: page.get_by_role( "button", name="Delete" ).click() dialog = dialog_info.value assert dialog.type == "alert" dialog.accept()
Avoid arbitrary sleep statements for browser synchronization. Coordinate the action with the browser event you expect.
16. Complete Real-Time Example — Order Cancellation

This example combines a confirmation dialog with application validation.

Professional Playwright Test
from playwright.sync_api import expect

def test_customer_cancels_order(page):

    # Arrange
    page.goto(
        "https://example.test/orders/ORD-1001"
    )

    # Dialog handler
    def handle_dialog(dialog):

        assert dialog.type == "confirm"

        assert (
            "cancel"
            in dialog.message.lower()
        )

        dialog.accept()

    page.on("dialog", handle_dialog)

    # Act
    page.get_by_role(
        "button",
        name="Cancel Order"
    ).click()

    # Assert
    expect(
        page.get_by_test_id("order-status")
    ).to_have_text("Cancelled")

The test follows:

Arrange
→
Register Dialog Handler
→
Act
→
Dialog Accept
→
Assert
17. Selenium Alert Handling

Selenium handles JavaScript alerts through the browser's alert interface.

Selenium Python — Alert
from selenium import webdriver
from selenium.webdriver.common.alert import Alert

driver = webdriver.Chrome()

driver.get(
    "https://example.test/customers"
)

driver.find_element(
    "id",
    "deleteCustomer"
).click()

alert = Alert(driver)

print(alert.text)

alert.accept()

driver.quit()
18. Selenium Confirm Dialog
Selenium Python
from selenium.webdriver.common.alert import Alert

driver.find_element(
    "id",
    "cancelOrder"
).click()

alert = Alert(driver)

print(alert.text)

alert.accept()

Dismiss the confirmation

Selenium Python
alert = Alert(driver)

alert.dismiss()
19. Selenium Prompt Handling
Selenium Python
from selenium.webdriver.common.alert import Alert

driver.find_element(
    "id",
    "enterReference"
).click()

alert = Alert(driver)

print(alert.text)

alert.send_keys(
    "REF-2026-1001"
)

alert.accept()
20. Selenium Popup / New Tab Handling

Selenium commonly works with window handles when a new browser window or tab is opened.

Selenium Python
main_window = driver.current_window_handle

driver.find_element(
    "id",
    "openReport"
).click()

windows = driver.window_handles

for window in windows:

    if window != main_window:

        driver.switch_to.window(window)

        print(
            driver.current_url
        )

        break
Selenium can handle multiple windows/tabs, but the test commonly has to manage window handles and explicitly switch between them.
21. Playwright vs Selenium — Alert/Dialog/Popup Comparison
Scenario Playwright Selenium
JavaScript Alert page.on("dialog") Alert(driver)
Accept Alert dialog.accept() alert.accept()
Dismiss Alert dialog.dismiss() alert.dismiss()
Prompt Text dialog.accept("value") alert.send_keys("value")
Wait for Dialog page.expect_dialog() Usually interact with Alert(driver) after the alert appears.
New Tab / Popup page.expect_popup() Window handles
Switch Tab Work directly with the returned Page. driver.switch_to.window()
Popup URL popup.url driver.current_url after switching.
22. Same Business Scenario — Playwright vs Selenium

Scenario

User clicks Delete Customer, confirms the JavaScript dialog, and verifies that the customer is removed.

Playwright

Playwright Python
with page.expect_dialog() as dialog_info:

    page.get_by_role(
        "button",
        name="Delete Customer"
    ).click()

dialog = dialog_info.value

assert dialog.type == "confirm"

dialog.accept()

expect(
    page.get_by_text(
        "Customer deleted"
    )
).to_be_visible()

Selenium

Selenium Python
driver.find_element(
    "id",
    "deleteCustomer"
).click()

alert = Alert(driver)

assert alert.text == (
    "Delete this customer?"
)

alert.accept()

assert driver.find_element(
    "id",
    "successMessage"
).is_displayed()
23. Same Popup Scenario — Playwright vs Selenium

Playwright

Popup Handling
with page.expect_popup() as popup_info:

    page.get_by_role(
        "link",
        name="Open Invoice"
    ).click()

invoice = popup_info.value

expect(
    invoice.get_by_text(
        "Invoice"
    )
).to_be_visible()

Selenium

Window Handle Handling
main_window = (
    driver.current_window_handle
)

driver.find_element(
    "id",
    "openInvoice"
).click()

for window in driver.window_handles:

    if window != main_window:

        driver.switch_to.window(window)

        break

assert "Invoice" in (
    driver.title
)
Conceptual difference: Playwright's popup API returns the new page as an object that can be used directly. Selenium commonly exposes window handles and requires an explicit switch to the desired window.
24. Why Playwright Can Be Simpler for These Scenarios

Both Playwright and Selenium can automate alerts, dialogs and multiple browser windows. Their APIs and synchronization models differ.

Area Playwright Approach Selenium Approach
Dialog event Event listener or expect_dialog() Alert interface
Popup expect_popup() Window handles
New page Returned Page object Switch driver context
Synchronization Designed around browser events and auto-waiting behavior Explicit waits are commonly used for many conditions
Test readability Popup handling can be expressed close to the action that creates it. Window-handle management can add additional steps.
These are API and workflow differences rather than a statement that one framework is universally superior. Selenium remains a widely used browser automation framework and supports these scenarios as well.
25. Professional Pattern — Handle Different Dialog Types

In a larger test suite, you may want to validate the dialog type and choose the correct behavior.

Reusable Dialog Handler
def handle_dialog(dialog):

    print("Dialog type:", dialog.type)
    print("Message:", dialog.message)

    if dialog.type == "alert":

        dialog.accept()

    elif dialog.type == "confirm":

        dialog.accept()

    elif dialog.type == "prompt":

        dialog.accept("Test User")

    else:

        dialog.dismiss()


page.on("dialog", handle_dialog)
Avoid putting one global dialog handler into every test without considering what each test expects. A global handler that blindly accepts every dialog can hide an unexpected application behavior.
26. Better Professional Pattern — Validate Unexpected Dialogs

A test should not simply accept every dialog. If a dialog is unexpected, the test should make that visible.

Controlled Dialog Handling
with page.expect_dialog() as dialog_info:

    page.get_by_role(
        "button",
        name="Delete Customer"
    ).click()

dialog = dialog_info.value

assert dialog.type == "confirm"

assert (
    dialog.message
    == "Are you sure you want to delete this customer?"
)

dialog.accept()

This pattern verifies both the dialog type and the dialog message before accepting it.

27. Common Mistakes
Mistake Better Approach
Using time.sleep() Wait for the actual dialog or popup event.
Registering the dialog handler too late Register it before triggering the dialog.
Accepting every dialog blindly Validate type and message when relevant.
Treating a popup as a JavaScript alert Use expect_popup() for a new page/tab.
Using window-handle logic in Playwright Work with the returned Playwright Page.
Ignoring popup state Assert the popup URL, title or important content.
28. Complete Professional Example

The following example demonstrates a realistic order-management workflow containing both a confirmation dialog and a popup.

End-to-End Playwright Example
from playwright.sync_api import expect


def test_order_management(page):

    # --------------------------------
    # 1. Open application
    # --------------------------------

    page.goto(
        "https://example.test/orders"
    )


    # --------------------------------
    # 2. Cancel order
    # --------------------------------

    with page.expect_dialog() as dialog_info:

        page.get_by_role(
            "button",
            name="Cancel Order"
        ).click()

    dialog = dialog_info.value

    assert dialog.type == "confirm"

    assert (
        "cancel"
        in dialog.message.lower()
    )

    dialog.accept()


    # --------------------------------
    # 3. Validate order status
    # --------------------------------

    expect(
        page.get_by_test_id("order-status")
    ).to_have_text("Cancelled")


    # --------------------------------
    # 4. Open invoice in new tab
    # --------------------------------

    with page.expect_popup() as popup_info:

        page.get_by_role(
            "link",
            name="Open Invoice"
        ).click()

    invoice_page = popup_info.value


    # --------------------------------
    # 5. Validate popup
    # --------------------------------

    expect(
        invoice_page.get_by_role(
            "heading",
            name="Invoice"
        )
    ).to_be_visible()

    expect(
        invoice_page
    ).to_have_title(
        "Order Invoice"
    )

    print(
        "Invoice URL:",
        invoice_page.url
    )
Open Orders
→
Cancel Order
→
Confirm Dialog
→
Verify Status
→
Open Invoice
→
Validate New Tab
29. Quick Reference
Requirement Playwright Python
Listen for any dialog page.on("dialog", handler)
Wait for one dialog page.expect_dialog()
Read dialog type dialog.type
Read dialog message dialog.message
Accept dialog.accept()
Accept prompt with value dialog.accept("value")
Cancel / dismiss dialog.dismiss()
Wait for popup page.expect_popup()
Access popup popup_info.value
Popup URL popup.url
30. Professional Best Practices
31. Final Mental Model
Alert
dialog.accept()
Confirm
accept / dismiss
Prompt
accept("value")
New Tab
expect_popup()
Remember:

JavaScript dialog → dialog

New browser tab / popup → Page

Playwright pattern → wait for the browser event + perform the action + validate the result
Simple learning formula:

Alert → expect_dialog()
Confirm → accept() / dismiss()
Prompt → accept("value")
New Tab → expect_popup()
Popup validation → expect()