How to Accept a JavaScript Dialog with Puppeteer
Handle alert, confirm, prompt, and beforeunload dialogs in Puppeteer with the right event listener, acceptance logic, and troubleshooting tips.
To accept a JavaScript dialog in Puppeteer, register a dialog event listener on the page and call await dialog.accept(). For a JavaScript prompt, pass the value to enter as await dialog.accept('your text'). Register the listener before the click, navigation, or other action that opens the dialog.
page.on('dialog', async dialog => {
await dialog.accept();
});
Puppeteer delivers JavaScript alert, confirm, prompt, and beforeunload dialogs through this event. Inspect dialog.type() when different dialogs need different responses. Use dialog.dismiss() to cancel or decline one. See the official Puppeteer Dialog API and PageEvent reference.
Accept an alert, confirm, or prompt
Here is a complete runnable Node.js example. It opens a local page that creates an alert, registers the listener first, clicks the button, and waits for the dialog to be accepted.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setContent('<button onclick="alert(\\'Saved\\')">Save</button>');
page.on('dialog', async dialog => {
console.log(`Dialog type: ${dialog.type()}`);
console.log(`Dialog message: ${dialog.message()}`);
await dialog.accept();
});
await page.click('button');
console.log('The alert was accepted.');
} finally {
await browser.close();
}
})();
Install Puppeteer in a new project with npm install puppeteer, then save the sample as accept-dialog.js and run node accept-dialog.js. Puppeteer normally downloads a compatible browser during installation. If your project already provides a browser, configure its executable path according to the Puppeteer version and environment you use.
Accept a prompt and enter text
Pass the text as the argument to accept(). The optional argument only affects prompt dialogs; it is ignored for alerts and other dialog types.
page.on('dialog', async dialog => {
if (dialog.type() === 'prompt') {
await dialog.accept('value to enter');
}
});
Choose an action based on the dialog type
All four supported dialog categories arrive on the same page event. Make the response reflect the interaction your test intends:
| Dialog type | Accept | Dismiss |
|---|---|---|
alert |
Close the alert | Close the alert |
confirm |
Choose the affirmative response | Choose the negative response |
prompt |
Submit the optional text value | Cancel the prompt |
beforeunload |
Proceed with the page action | Stay on the page |
The table describes the intent of the browser interaction. For an alert, both actions close the dialog; for other types, acceptance and dismissal can produce different page behavior. These dialogs are browser JavaScript dialogs, not HTML elements, so do not try to locate them with a CSS selector or click them as DOM buttons.
page.on('dialog', async dialog => {
const type = dialog.type();
const message = dialog.message();
const defaultValue = dialog.defaultValue();
if (type === 'prompt') {
await dialog.accept('approved value');
} else if (type === 'confirm' && message.includes('Delete')) {
await dialog.dismiss();
} else {
await dialog.accept();
}
});
type() identifies the dialog category, message() returns its message, and defaultValue() returns a prompt’s default value (it is empty for non-prompt dialogs). The handled property indicates whether the dialog has been handled. These methods are documented by Puppeteer’s Dialog API.
Handle the dialog reliably
Attach the listener before the trigger
Set up the event handler before the action that can open a dialog. If you click first and attach the handler afterward, the dialog may already be blocking page activity. This ordering is particularly important when starting navigation or clicking a submit button.
const dialogHandled = new Promise((resolve, reject) => {
page.once('dialog', async dialog => {
try {
await dialog.accept();
resolve(dialog.type());
} catch (error) {
reject(error);
}
});
});
await page.click('#submit');
const type = await dialogHandled;
console.log(`Handled ${type}`);
Use page.once() when exactly one dialog is expected. Use page.on() for a test that intentionally handles multiple dialogs. Awaiting a promise tied to the event makes the test’s sequence explicit; add a timeout in your test framework if the dialog is optional or might never appear.
Handle only the dialogs your scenario expects
A blanket handler that accepts every dialog can hide an unexpected confirmation or approve a beforeunload prompt that your test should detect. Check the type and, when useful, the message before acting. If a dialog type or message is unexpected, fail the test or dismiss it deliberately instead of silently proceeding.
Wait for navigation when the dialog action causes it
If accepting a dialog also submits a form or causes navigation, coordinate the navigation wait with the triggering action. For example, use Puppeteer’s navigation-wait pattern around the click, and have the already-registered dialog listener accept the dialog. This prevents the test from assuming navigation has finished just because accept() resolved. Choose a navigation wait condition appropriate to the page; sites that keep network connections open may not reach network idle.
cURL, Python, and ScreenshotNeo
cURL and Python do not provide Puppeteer’s browser event interface, so they cannot accept a JavaScript dialog through Puppeteer. The following examples are ScreenshotNeo’s screenshot API calls, which capture a page and return an image; they are not dialog-acceptance commands. See the ScreenshotNeo API documentation for available request options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
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)
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}`);
Or skip the browser setup
If your goal is a clean screenshot rather than controlling a dialog in a browser test, ScreenshotNeo can return an image or PDF with one GET request. Its clean-shot steps accept cookie and consent banners like a visitor, then remove more than 60 known consent platforms along with newsletter popups and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Sign up for 1,000 free screenshots a month, with no card required.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The test hangs after clicking | A dialog opened without a handler, or the handler was registered after the trigger. | Attach a dialog listener before clicking or navigating, and accept or dismiss the dialog in the handler. |
| The dialog event never fires | The site may use an HTML modal instead of a JavaScript dialog, or the action did not trigger a dialog. | Inspect the page implementation. Use DOM selectors and normal interaction for an HTML modal; use the page event for JavaScript dialogs. |
| A prompt does not contain the expected value | No prompt text was supplied, or the dialog is not actually a prompt. | Check dialog.type() and pass the desired string to dialog.accept(value) for a prompt. |
| The test takes the wrong branch after a confirm | The handler accepted when the scenario expected cancellation, or vice versa. | Use accept() for the affirmative choice and dismiss() for the negative choice; assert the resulting page state. |
| Navigation does not finish when the dialog is accepted | Accepting the dialog resolves the dialog action, but the test may not have awaited the navigation it triggered. | Coordinate the click with a navigation wait, and select a wait condition suited to the site. |
| An unrelated dialog is accepted | The handler accepts every dialog without checking its type or message. | Inspect type() and message(); explicitly handle expected cases and make unexpected dialogs visible to the test. |
Performance, reliability, and cost
Dialog handling itself is a small event-driven operation; overall runtime is usually governed by launching the browser, loading the page, and any navigation or application work in the test. Reuse a browser across related test cases when your test setup permits it, while keeping page state isolated where needed. Registering the listener before each trigger avoids race conditions and makes failures easier to diagnose.
Puppeteer is an open-source browser automation library. The dialog API does not introduce a per-dialog service charge; your costs come from the environment running the browser and the resources your test consumes. For screenshot-only workflows, ScreenshotNeo offers a free monthly allowance and paid tiers listed on its site. Its responses indicate page verdict and whether a capture was billed.
FAQ
Can Puppeteer accept a prompt with an empty value?
Yes. Call await dialog.accept('') when you need to submit an empty string. Omit the argument when the prompt should use the browser’s default behavior.
Can I accept a dialog after it has appeared?
The dialog event is the reliable place to receive and handle it. Attach the listener before the action that opens the dialog so page execution does not remain blocked while your test waits to install a handler.
Does this work for custom HTML popups?
No. The dialog event covers JavaScript dialogs such as alerts, confirms, prompts, and beforeunload prompts. A custom modal is part of the page DOM and should be handled with its selectors and normal page interactions.


