In Playwright, first identify what you are seeing: a cookie banner or modal rendered inside the page is ordinary DOM content, while an alert, confirm, prompt, or beforeunload message is a native browser dialog. Click the first with a locator such as getByRole(); handle the second with Playwright’s page.on('dialog') event. Using the wrong API is the usual reason a test cannot find the control or appears to hang.
Decide which kind of popup appeared
Inspect the page and the test behavior before writing a selector. A DOM popup can be inspected in browser developer tools, has elements in the page tree, and can normally be targeted with a locator. A native JavaScript dialog is outside the DOM; it exposes a message and dialog type through Playwright’s dialog object.
| Popup type | What it is | Correct Playwright API |
|---|---|---|
| Cookie consent banner | Page HTML containing buttons such as “Accept all” or “Reject optional” | Locator click, usually getByRole('button', { name: ... }) |
| In-page modal | An overlay and dialog container rendered by the application | Locator scoped to the modal; optionally page.addLocatorHandler() for intermittent overlays |
alert, confirm, prompt |
Native JavaScript dialog, not an element in the page | page.on('dialog') or a one-time page.once('dialog') listener |
beforeunload |
Browser confirmation shown while leaving a page | Dialog event handling |
Playwright’s official dialog documentation covers native dialogs. Its locator guidance recommends user-facing locators and stable testing contracts rather than long CSS or XPath chains.
Click a cookie consent banner
Use the accessible button name
Prefer the role and name a real user would see. The name must match the application’s accessible name, so substitute the wording used by your site.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →import { test, expect } from '@playwright/test';
test('accepts the cookie banner', async ({ page }) => {
await page.goto('https://example.com');
await page.getByRole('button', { name: 'Accept all' }).click();
});
Other common choices are Accept, Reject optional, and Manage preferences. Do not automatically accept consent when the purpose of the test is to verify consent choices; click the option the scenario is meant to exercise and assert the resulting state.
#1 Best Overall
- Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
- Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
- Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
- Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
- Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)
Scope the locator when several buttons match
A page may contain an “Accept” button in more than one component. Locate the banner or its dialog container first, then find the button inside it.
const banner = page.getByRole('region', { name: /cookie|consent/i });
await banner.getByRole('button', { name: 'Accept all' }).click();
If the component is exposed as a dialog, scope with getByRole('dialog'). If the application provides a stable test ID, that is a reasonable fallback:
const banner = page.getByTestId('cookie-consent');
await banner.getByRole('button', { name: 'Reject optional' }).click();
Use CSS or XPath only when the page has no useful accessible name or test contract, and keep the selector narrow. Locator actions auto-wait for actionability and re-resolve the element, whereas a selector tied to several layers of DOM structure is more likely to break when markup changes. See Playwright’s best practices and the Locator API.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteAssert that the choice took effect
A successful click is not proof that consent was recorded. Assert a visible state, a cookie, a navigation result, or another application contract.
Rank #2
- The next-generation optical HERO sensor delivers incredible performance and up to 10x the power efficiency over previous generations, with 400 IPS precision and up to 12,000 DPI sensitivity
- Ultra-fast LIGHTSPEED wireless technology gives you a lag-free gaming experience, delivering incredible responsiveness and reliability with 1 ms report rate for competition-level performance
- G305 wireless mouse boasts an incredible 250 hours of continuous gameplay on just 1 AA battery; switch to Endurance mode via Logitech G HUB software and extend battery life up to 9 months
- Wireless does not have to mean heavy, G305 lightweight mouse provides high maneuverability coming in at only 3.4 oz thanks to efficient lightweight mechanical design and ultra-efficient battery usage
- The durable, compact design with built-in nano receiver storage makes G305 not just a great portable desktop mouse, but also a great laptop travel companion, use with a gaming laptop and play anywhere
await page.getByRole('button', { name: 'Accept all' }).click();
await expect(page.getByRole('region', { name: /cookie|consent/i })).toBeHidden();
// Or assert a post-consent control that only appears after acceptance.
await expect(page.getByRole('button', { name: 'Account' })).toBeVisible();
Click an in-page modal
Handle a modal that appears as part of the tested flow
Locate the modal by its role or heading, then click the intended action within that container.
await page.getByRole('button', { name: 'Open settings' }).click();
const modal = page.getByRole('dialog', { name: 'Settings' });
await modal.getByRole('button', { name: 'Save' }).click();
If the component has no dialog semantics, use a visible heading, text, or test ID as the container. Keep the action scoped so an unrelated button cannot satisfy the test.
Deal with an intermittent overlay
For a newsletter or sign-up overlay that can appear at an unexpected point, register a locator handler before the action that might encounter it. Playwright documents this pattern in the Page API reference.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #3
- Compact Mouse: With a comfortable and contoured shape, this Logitech ambidextrous wireless mouse feels great in either right or left hand and is far superior to a touchpad
- Durable and Reliable: This USB wireless mouse features a line-by-line scroll wheel, up to 1 year of battery life (2) thanks to a smart sleep mode function, and comes with the included AA battery
- Universal Compatibility: Your Logitech mouse works with your Windows PC, Mac, or laptop, so no matter what type of computer you own today or buy tomorrow your mouse will be compatible
- Plug and Play Simplicity: Just plug in the tiny nano USB receiver and start working in seconds with a strong, reliable connection to your wireless computer mouse up to 33 feet / 10 m (5)
- Better than touchpad: Get more done by adding M185 to your laptop; according to a recent study, laptop users who chose this mouse over a touchpad were 50% more productive (3) and worked 30% faster (4)
await page.addLocatorHandler(
page.getByText('Sign up to the newsletter'),
async () => {
await page.getByRole('button', { name: 'No thanks' }).click();
}
);
await page.getByRole('link', { name: 'Read article' }).click();
The handler should represent the test’s intention. Do not dismiss a consent banner globally if the test is checking whether consent is requested or whether each choice has the correct effect.
Handle native JavaScript alerts and confirmations
Register a handler before triggering the dialog
Native dialogs are handled through the dialog event, not a DOM locator. Accept a confirmation when the scenario tests the positive path:
page.on('dialog', async dialog => {
await dialog.accept();
});
await page.getByRole('button', { name: 'Delete' }).click();
For a cancellation test, dismiss it instead:
page.once('dialog', async dialog => {
await dialog.dismiss();
});
await page.getByRole('button', { name: 'Delete' }).click();
For a prompt, provide the value expected by the application:
page.once('dialog', async dialog => {
expect(dialog.type()).toBe('prompt');
await dialog.accept('approved by test');
});
await page.getByRole('button', { name: 'Enter approval' }).click();
You can inspect the message before choosing an outcome:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
- Computer mouse for easily navigating a computer interface; click, scroll, and more
- USB-A wired connection; if existing device only supports USB-C, an additional adapter will be required
- High-definition (1000 dpi) optical tracking ensures responsive cursor control for precise tracking and easy text selection
- 3 buttons offer effortless fingertip control
- Plug-and-go ready for instant use
page.once('dialog', async dialog => {
expect(dialog.message()).toContain('Are you sure');
await dialog.accept();
});
Understand Playwright’s default behavior
When no page.on('dialog') listener is registered, Playwright automatically dismisses JavaScript dialogs. That is convenient when the dialog is irrelevant, but it can hide a behavior your test should verify. Once a listener is registered, it must accept or dismiss every dialog it receives. The official documentation warns that merely logging the message leaves the triggering action blocked: “Otherwise your action will stall, be it locator.click() or something else.”
Use a one-time listener for one expected dialog
page.once() prevents a handler intended for one action from affecting later dialogs. Use page.on() only when every matching dialog in the test should receive the same policy, and make that policy explicit.
page.once('dialog', async dialog => {
if (dialog.type() !== 'confirm') {
await dialog.dismiss();
return;
}
await dialog.accept();
});
await page.getByRole('button', { name: 'Publish' }).click();
Reliable test patterns
Attach listeners before the trigger
Set up the handler before clicking the button or navigating. A listener added afterward can miss the event, leaving the test waiting for a result that cannot occur.
Best Value
- 【Plug and Play for Home/Office/School】The wireless computer mouse features 2.4GHz connectivity, delivering a stable, interference-free connection up to 32ft. Designed for 𝐦𝐞𝐝𝐢𝐮𝐦 𝐭𝐨 𝐥𝐚𝐫𝐠𝐞 𝐬𝐢𝐳𝐞𝐝 𝐡𝐚𝐧𝐝𝐬, it ensures comfortable use all day. Simply plug in the USB-A receiver for instant pairing—no drivers needed. 📌📌 If the mouse isn’t suitable, place the USB receiver in the battery compartment and return both.
- 【3 Levels Adjustable DPI】This travel USB mouse offers 3 adjustable DPI settings (800, 1200, 1600), allowing you to customize sensitivity for precise design work. Effortlessly switch to match your task and elevate your productivity. 📌 Please remove the film at the bottom of the mouse before use.
- 【Effortless Browsing】Equipped with forward and backward buttons, this computer mice streamlines your workflow, making it easy to navigate through web pages and files with a simple click. 📌Side button does not work on Mac.
- 【Visible Indicator Light】 The pc mouse features a visual indicator for DPI levels and low battery alerts. The red light flashes once for 800 DPI, twice for 1200 DPI, and three times for 1600 DPI. When the battery level is below 10%, the light flashes red until the mouse is completely out of power.
- 【Click to Wake】With smart sleep mode, it saves power by standby after 10 inactive minutes, just 2-3 clicks to wake. This efficient design delivers 3x longer battery life than motion-wake mice. Engineered for durability, its buttons and scroll wheel are tested for 10 million clicks, ensuring long-term reliability and consistent performance.
Keep popup policy local
Register consent and dialog handling in the test or fixture that owns the behavior. A global “accept everything” listener can make destructive tests pass without proving that the application asked for confirmation.
Use actionability rather than arbitrary sleeps
Locator clicks wait for the element to be present, visible, enabled, and usable. Prefer that built-in waiting, a locator assertion, or a documented application state over waitForTimeout(). For a delayed banner, wait for its locator and then click it.
const accept = page.getByRole('button', { name: 'Accept all' });
await expect(accept).toBeVisible();
await accept.click();
Make repeated runs deterministic
- Start with a fresh browser context when consent cookies must not leak between tests.
- Use a preloaded storage state when the suite intentionally starts after consent.
- For consent-choice tests, clear storage and verify the banner’s initial visibility.
- Use tracing or screenshots on failure to distinguish a missing banner from an incorrect locator.
Troubleshooting cookie popups and modal alerts
| Symptom | Likely cause | Fix |
|---|---|---|
| “Button not found” | The popup is native, the accessible name differs, or the banner has not appeared. | Determine whether it is in the DOM; inspect the accessible name; wait for the scoped locator. |
| Click matches multiple elements | Several “Accept” controls exist. | Scope to the banner or dialog and use the exact accessible name. |
| The click hangs after a JavaScript confirmation | A dialog listener was registered but never accepted or dismissed. | Handle every emitted dialog and attach the listener before the trigger. |
| The dialog was silently skipped | No dialog listener was registered, so Playwright dismissed it automatically. | Add a one-time listener and assert its type or message. |
| Overlay reappears in another test | Consent storage is shared or the site sets a new consent state. | Use isolated contexts, clear cookies/local storage, or deliberately load a storage state. |
| CSS selector breaks after a redesign | The selector depends on DOM nesting or generated classes. | Prefer role/name, label, text, or a stable test ID. |
| Handler closes the wrong popup | A broad text match or global handler catches an unrelated overlay. | Use a distinctive locator, scope the action, and keep the handler local. |
Or skip the browser setup
If your goal is a clean image or PDF rather than an interaction test, ScreenshotNeo provides a website screenshot API and MCP server. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
One request is enough:
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}`);
See the full parameter reference in the ScreenshotNeo documentation. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo.
Frequently Asked Questions
Can I click a native alert with getByRole()?
No. Native JavaScript dialogs are outside the DOM; handle them with the page dialog event and call accept or dismiss.
Recommended Free Tools
Should every test accept the cookie banner?
Only tests whose scenario requires acceptance should do so. Consent-choice tests should click and assert the specific option under test.
What happens if I never register a dialog handler?
Playwright automatically dismisses native dialogs when no dialog listener exists.
When is page.addLocatorHandler() appropriate?
Use it for an in-page overlay that may appear unexpectedly and can be safely closed without changing the behavior being tested.
Quick Recap
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.
Free tools Windows power users keep installed
One-click scans. No signup required.

