Playwright provides comprehensive support for handling JavaScript dialogs (alerts, confirmations, prompts) and popup windows in web automation. Here's how to handle both types effectively.
Handling JavaScript Dialogs
JavaScript dialogs (alert, confirm, prompt, beforeunload) are modal dialogs that block user interaction until dismissed. Playwright automatically handles these through the dialog
event.
Basic Dialog Handling
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Set up dialog handler before triggering dialog
page.on('dialog', async dialog => {
console.log(`Dialog type: ${dialog.type()}`);
console.log(`Dialog message: ${dialog.message()}`);
await dialog.dismiss(); // or dialog.accept()
});
// Navigate to page that triggers dialog
await page.goto('https://example.com');
await page.click('#alert-button');
await browser.close();
})();
Handling Different Dialog Types
page.on('dialog', async dialog => {
switch (dialog.type()) {
case 'alert':
console.log(`Alert: ${dialog.message()}`);
await dialog.accept();
break;
case 'confirm':
console.log(`Confirm: ${dialog.message()}`);
await dialog.accept(); // or dialog.dismiss() for "Cancel"
break;
case 'prompt':
console.log(`Prompt: ${dialog.message()}`);
await dialog.accept('User input text'); // Provide input
break;
case 'beforeunload':
console.log('Page attempting to unload');
await dialog.accept();
break;
}
});
Python Example
from playwright.sync_api import sync_playwright
def handle_dialog(dialog):
print(f"Dialog: {dialog.message}")
dialog.accept()
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.on("dialog", handle_dialog)
page.goto("https://example.com")
page.click("#alert-button")
browser.close()
Handling Popup Windows
Popup windows are new browser windows opened via window.open()
or target="_blank" links. Use the popup
event to handle them.
Basic Popup Handling
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Wait for popup and get popup page
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.click('a[target="_blank"]') // Action that opens popup
]);
// Interact with popup
console.log(`Popup URL: ${popup.url()}`);
await popup.fill('#input', 'text');
await popup.click('#submit');
// Close popup
await popup.close();
await browser.close();
})();
Multiple Popups Management
const popups = [];
page.on('popup', popup => {
console.log(`New popup: ${popup.url()}`);
popups.push(popup);
});
// Trigger actions that might open popups
await page.click('#multiple-popups-button');
// Handle all popups
for (const popup of popups) {
await popup.bringToFront();
// Perform actions on popup
await popup.close();
}
Python Popup Example
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
# Handle popup
with page.expect_popup() as popup_info:
page.click("a[target='_blank']")
popup = popup_info.value
print(f"Popup URL: {popup.url}")
popup.close()
browser.close()
Advanced Scenarios
Conditional Dialog Handling
page.on('dialog', async dialog => {
if (dialog.message().includes('Are you sure?')) {
await dialog.accept();
} else {
await dialog.dismiss();
}
});
Popup with Specific URL Pattern
page.on('popup', async popup => {
await popup.waitForLoadState();
if (popup.url().includes('login')) {
await popup.fill('#username', 'user');
await popup.fill('#password', 'pass');
await popup.click('#login-btn');
}
});
Dialog with Custom Input
page.on('dialog', async dialog => {
if (dialog.type() === 'prompt') {
const defaultValue = dialog.defaultValue();
await dialog.accept(defaultValue || 'custom input');
}
});
Important Notes
- Set handlers before navigation: Always set up dialog and popup handlers before navigating to pages that might trigger them
- Auto-dismiss: Unhandled dialogs are automatically dismissed, which might cause unexpected behavior
- New tabs vs popups: New tabs opened in the same window are new pages, not popups. Only
window.open()
with separate window features triggers popup events - Context isolation: Popups inherit the browser context of their parent page
- Timeout handling: Use timeouts when waiting for popups to avoid hanging tests
// With timeout
const [popup] = await Promise.all([
page.waitForEvent('popup', { timeout: 5000 }),
page.click('#popup-button')
]);