How to Handle Pop-ups and Modals in Puppeteer
Puppeteer provides several methods to handle different types of pop-ups and modals that appear on web pages. This guide covers JavaScript dialogs, HTML modals, and popup windows.
JavaScript Dialogs (Alerts, Confirms, Prompts)
JavaScript dialogs like alert()
, confirm()
, and prompt()
are handled using the dialog
event listener.
Basic Dialog Handling
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Set up dialog handler before navigating
page.on('dialog', async dialog => {
console.log(`Dialog type: ${dialog.type()}`);
console.log(`Dialog message: ${dialog.message()}`);
// Dismiss the dialog
await dialog.dismiss();
});
await page.goto('https://example.com');
// Trigger an alert
await page.evaluate(() => alert('Hello World!'));
await browser.close();
})();
Accepting Dialogs
page.on('dialog', async dialog => {
if (dialog.type() === 'confirm') {
// Accept confirm dialog
await dialog.accept();
} else if (dialog.type() === 'prompt') {
// Accept prompt with input text
await dialog.accept('My input text');
} else {
// Dismiss other dialogs
await dialog.dismiss();
}
});
Dialog Types and Methods
dialog.type()
: Returns 'alert', 'confirm', 'prompt', or 'beforeunload'dialog.message()
: Gets the dialog message textdialog.defaultValue()
: Gets default value for promptsdialog.accept(promptText?)
: Accepts the dialogdialog.dismiss()
: Dismisses the dialog
HTML Modals
HTML modals are regular DOM elements that can be interacted with using standard Puppeteer methods.
Waiting for and Closing Modals
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
// Click button that opens modal
await page.click('#open-modal-btn');
// Wait for modal to appear
await page.waitForSelector('.modal', { visible: true });
// Interact with modal content
await page.type('.modal input[name="email"]', 'user@example.com');
// Close modal by clicking close button
await page.click('.modal .close-btn');
// Wait for modal to disappear
await page.waitForSelector('.modal', { hidden: true });
await browser.close();
})();
Handling Bootstrap Modals
// Wait for Bootstrap modal to be fully shown
await page.waitForSelector('.modal.show', { visible: true });
// Close using backdrop click
await page.click('.modal-backdrop');
// Or close using close button
await page.click('.modal .btn-close');
// Wait for modal to be fully hidden
await page.waitForFunction(() =>
!document.querySelector('.modal.show')
);
Popup Windows
Handle new browser windows/tabs that open via window.open()
or target="_blank" links.
Detecting New Pages
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Listen for new pages (popups)
browser.on('targetcreated', async target => {
if (target.type() === 'page') {
const newPage = await target.page();
console.log('New popup opened:', await newPage.url());
// Interact with popup
await newPage.waitForLoadState('networkidle');
// Close popup
await newPage.close();
}
});
await page.goto('https://example.com');
// Click link that opens popup
await page.click('a[target="_blank"]');
await browser.close();
})();
Working with Multiple Pages
// Get all open pages
const pages = await browser.pages();
// Click link and wait for new page
const [newPage] = await Promise.all([
new Promise(resolve => browser.once('targetcreated', target => resolve(target.page()))),
page.click('#popup-link')
]);
// Work with the new page
await newPage.waitForLoadState();
await newPage.screenshot({ path: 'popup.png' });
await newPage.close();
Advanced Techniques
Conditional Modal Handling
// Handle modals that may or may not appear
try {
await page.waitForSelector('.modal', { timeout: 3000 });
console.log('Modal appeared, closing it...');
await page.click('.modal .close-btn');
} catch (error) {
console.log('No modal appeared within 3 seconds');
}
Multiple Dialog Types
page.on('dialog', async dialog => {
const type = dialog.type();
const message = dialog.message();
switch (type) {
case 'alert':
console.log(`Alert: ${message}`);
await dialog.accept();
break;
case 'confirm':
// Accept if message contains "proceed"
if (message.toLowerCase().includes('proceed')) {
await dialog.accept();
} else {
await dialog.dismiss();
}
break;
case 'prompt':
await dialog.accept('Default response');
break;
case 'beforeunload':
await dialog.accept(); // Allow page navigation
break;
}
});
Handling Cookie Consent Modals
// Common cookie consent modal patterns
const cookieSelectors = [
'#cookie-consent .accept-all',
'.cookie-banner .accept',
'[data-testid="cookie-accept"]',
'.gdpr-consent .agree'
];
for (const selector of cookieSelectors) {
try {
await page.waitForSelector(selector, { timeout: 2000 });
await page.click(selector);
console.log(`Accepted cookies using selector: ${selector}`);
break;
} catch (error) {
// Try next selector
}
}
Best Practices
- Set up dialog handlers before navigation to avoid missing early dialogs
- Use proper timeouts when waiting for modals to prevent hanging
- Verify modal state before and after interactions
- Handle multiple dialog types appropriately
- Clean up popup windows to prevent resource leaks
- Use specific selectors rather than generic ones for reliability
Common Issues and Solutions
Dialog Not Handled
// Always set dialog handler before triggering events
page.on('dialog', dialog => dialog.dismiss());
await page.goto('https://example.com'); // Now dialogs will be handled
Modal Not Visible
// Wait for both presence and visibility
await page.waitForSelector('.modal', { visible: true });
// Or check if element is actually visible
await page.waitForFunction(() => {
const modal = document.querySelector('.modal');
return modal && modal.offsetParent !== null;
});
Popup Blocked
// Launch with popup blocking disabled
const browser = await puppeteer.launch({
args: ['--disable-popup-blocking']
});
This comprehensive approach ensures reliable handling of all types of pop-ups and modals in your Puppeteer automation scripts.