Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

If a Playwright click succeeds but a cookie banner stays visible, first identify what the UI actually is: an HTML banner, a JavaScript dialog, an iframe, or a component inside an open Shadow DOM. Then scope a locator to the correct control, wait for it to be actionable, click it normally, and assert that the banner disappears. If the banner returns in later tests, check how the site stores consent rather than guessing a cookie name.

Start by identifying the kind of consent UI

“Cookie banner” can refer to several different browser interfaces, and each needs a different Playwright approach. Before changing a selector or adding a delay, determine where the control lives.

  • HTML banner in the main page: Use a locator, ideally scoped to a dialog or other identifiable container.
  • JavaScript alert, confirm, or prompt: Handle the browser dialog with the dialog event. It is not a DOM element and cannot be clicked with a locator.
  • Banner inside an iframe: Enter the frame with frameLocator(), then locate the control there.
  • Component inside an open Shadow DOM: Playwright’s regular locators can reach into the open shadow root. XPath does not pierce shadow roots, and closed-mode roots are unsupported.

Also check that the banner belongs to the page you are interacting with. A consent panel may be in a frame or another page, so a locator on the main page can be valid yet target the wrong browsing context.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a scoped locator and verify the result

Prefer accessible, user-facing selectors such as roles and names, or a stable test ID. Playwright recommends locators because they support auto-waiting and retryability; locator actions resolve the current element rather than depending on a previously captured DOM node. See the Playwright locator documentation.

This TypeScript example scopes the accept button to a dialog identified by its text, waits for visibility, clicks normally, and checks that the dialog is hidden:

import { test, expect } from '@playwright/test';

test('dismisses the cookie banner', async ({ page }) => {
  await page.goto('https://example.com');

  const banner = page
    .getByRole('dialog')
    .filter({ hasText: /cookies|privacy|consent/i });
  const accept = banner.getByRole('button', {
    name: /accept all|allow all|agree/i,
  });

  await accept.waitFor({ state: 'visible' });
  await accept.click();
  await expect(banner).toBeHidden();
});

Replace the URL and accessible names with the ones exposed by the site under test. Not every consent panel uses a dialog role or the same wording. If you have a documented, stable test ID, it can be a better contract than a guessed CSS class.

For an even stricter diagnostic, assert a single matching button before clicking:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await expect(accept).toHaveCount(1);
await accept.click();
await expect(banner).toBeHidden();

This catches duplicate desktop and mobile controls rather than silently clicking whichever matching element happens to be first. Do not use a broad selector such as locator('button').first() unless the page’s DOM contract makes that choice intentional.

Handle iframes, Shadow DOM, and JavaScript dialogs

Consent manager in an iframe

Use a frame locator for a stable iframe selector, then find the button inside that frame. For example:

const consentFrame = page.frameLocator('iframe[title="consent"]');
const accept = consentFrame.getByRole('button', {
  name: /accept all|allow all|agree/i,
});

await accept.waitFor({ state: 'visible' });
await accept.click();

Use the actual title or other stable selector from the page; iframe[title="consent"] is only an example. Playwright documents that frame locators search within a specified frame, and that an unqualified frame locator can search across frames. A frame locator is strict when multiple frames match, so narrow the selector if the page has several candidate frames. See Playwright’s frames guide.

Open Shadow DOM

Try a role, text, test ID, or CSS locator exposed by the component. Regular Playwright locators pierce open shadow roots. XPath selectors do not, and closed-mode shadow roots are not supported. If a selector works in the main DOM but not inside a closed component, changing wait timing will not make that boundary accessible. See the locator documentation on Shadow DOM.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JavaScript alert, confirm, or prompt

Register a handler before the page action that triggers the dialog. Accept a dialog only when its message is the cookie or consent prompt you expect; otherwise dismiss it:

page.on('dialog', async dialog => {
  if (/cookie|consent/i.test(dialog.message())) {
    await dialog.accept();
  } else {
    await dialog.dismiss();
  }
});

await page.getByRole('button', { name: /continue|open/i }).click();

A browser dialog is not an HTML element. Playwright states that dialogs must be accepted or dismissed; otherwise the page can remain blocked waiting for a response. See Playwright’s dialog documentation.

Why the click completes but the banner remains

A successful click means the action was performed; it does not prove that the site committed consent or removed the panel. Use a post-click assertion and investigate the page state when it fails.

  • The selector matched the wrong control: A hidden mobile/desktop duplicate or a settings button may share similar text. Scope to the visible banner and use the precise accessible name; assert a single match.
  • “Close” is not “accept”: Some interfaces collapse a panel or close preferences without saving consent. Look for the site’s actual commit action, such as “Save choices,” and assert the resulting state.
  • The site needs another step: The click may open a preferences view where consent must be saved separately. Inspect the state after the first action instead of assuming one click is sufficient.
  • Another layer intercepts the click: A modal overlay or animation may cover the target. Normal click actionability checks can expose this; identify the covering layer and wait for it to disappear or target the correct interface.
  • The manager re-rendered: A stale element handle can refer to an element the site replaced. Prefer locators, which re-resolve the element for actions.
  • The banner rendered late: Wait for the target’s visible state or rely on locator auto-waiting and a bounded assertion. Avoid arbitrary sleeps as the primary fix.
  • The control is in another context: Check whether it is in an iframe or a different page before changing the selector.

Playwright’s click performs actionability checks. Setting force: true bypasses them, which can help confirm that hit testing is the blocker, but it may conceal a genuine user-visible defect. Fix the underlying locator, frame, timing, or overlay when possible. See Playwright’s actionability documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When a failure is unclear, inspect a screenshot, the DOM, and the Playwright trace around the click. Check whether the banner is visible, detached, covered, or replaced, and whether the page navigated or opened a preferences view. Make the assertion match the expected result: toBeHidden() is appropriate if the node may remain in the DOM but become invisible; toHaveCount(0) is appropriate if the site removes it.

Stop consent from returning in later tests

A banner that reappears in a new test may be behaving as designed: a fresh browser context usually does not carry the previous test’s consent. After completing the site’s real consent flow, save the context’s storage state and reuse it for tests that are not meant to cover first visit.

import { chromium } from '@playwright/test';

const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();

await page.goto('https://example.com');
// Perform and verify the site's real consent action here.

await context.storageState({
  path: 'playwright/.auth/consent.json',
});
await browser.close();

Then create later contexts with that saved state:

const context = await browser.newContext({
  storageState: 'playwright/.auth/consent.json',
});

Playwright’s storage-state workflow captures and reuses cookies and local storage. The browser API describes cookie fields such as name, value, domain, and path; a leading-dot domain applies to subdomains. See the authentication guide and BrowserContext storage-state API.

Do not guess cookie names, values, storage keys, domains, or paths. Discover them from the site’s own consent flow, and treat saved consent as environment-specific. Keep a separate fresh context or clear the saved state when testing the first-visit experience; otherwise the test may stop covering the banner at all.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the right test seam

Whether to interact with a consent banner depends on what the test is meant to prove.

  • Test the consent experience itself: Exercise the visible UI, verify the chosen action, and check that the banner’s expected state changes.
  • Test your own page behavior independently of a third-party consent service: Consider controlling the network response instead. Playwright’s best practices recommend using the Network API when linked content, cookie banners, or overlay pages are outside your application’s control and make tests unreliable. See Playwright’s best practices.
  • Test the first-visit path: Use clean storage so consent is not already recorded.
  • Test an already-consented path: Reuse a storage state created by performing the site’s real consent flow.

These approaches answer different questions. Network control can isolate your application from a third-party dependency, but it does not verify that the consent interface itself works.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If the task is to capture a webpage rather than test its consent interaction, ScreenshotNeo provides a screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. Its clean-shot steps accept cookie/consent banners as a visitor and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off.

Example cURL request (replace the target URL and API key):

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

See the ScreenshotNeo API documentation for setup and request options. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status. The MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Every feature is on every plan. These are ScreenshotNeo plan terms, not a claim about Playwright or a substitute for testing whether a consent flow works.

Sign up for 1,000 free screenshots a month with no card.

Troubleshooting checklist

  • Locator times out: Confirm the banner has rendered, the role and accessible name match the actual control, and the locator is scoped to the right dialog or frame. Prefer an explicit visible-state wait or locator auto-waiting over a fixed sleep.
  • Strict-mode violation or multiple matches: Narrow the container or iframe selector and check for desktop/mobile duplicates. Assert the intended control has one match before clicking.
  • Click reports that the target is covered or not actionable: Inspect the overlay and trace. Wait for the relevant transition or target the visible control; use force only to diagnose, not as a default workaround.
  • Click succeeds but the panel remains: Check whether the clicked action merely closes settings, whether a separate save action is needed, or whether the UI re-rendered. Assert hidden or removed state after the final action.
  • Frame locator is ambiguous: Use the provider’s stable iframe selector so exactly one frame matches.
  • Consent returns in every new test: Confirm the prior flow actually saved state, then reuse storage state for tests that require consent. Use clean storage for first-visit tests.
  • Saved state does not work on another environment: Re-run the real flow and inspect the resulting cookie or storage values. Consent domains, paths, and storage keys can differ by site and environment.

Locator signatures and browser behavior are version-sensitive. Pin the Playwright version in the project and re-check the official API documentation when upgrading rather than relying on selectors or behavior copied from another site.

Frequently Asked Questions

Does Playwright automatically accept cookie banners?

No. Playwright provides locators and browser APIs for interacting with page UI, but the test must identify the site’s consent control and handle it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use `force: true` to make the accept click work?

Usually not. It bypasses actionability checks and can hide an overlay or targeting problem. Use it only as a diagnostic while identifying the underlying cause.

Can I use storage state for every cookie-banner test?

No. Reusing consent state is useful for tests that should begin after consent, but first-visit tests need clean storage so they exercise the banner.

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.