ScreenshotNeo

BlogHow-to

Fix Website Screenshots That Capture a Cookie Banner Over the Page

Hide a cookie banner for a clean screenshot, or click the intended consent choice when the screenshot must show a real interaction. Includes runnable Playwright code and troubleshooting.

By the ScreenshotNeo team4 October 20267 min read

To keep a cookie banner out of a screenshot, inspect the page and hide its specific banner selector with Playwright’s screenshot-only style option. If the screenshot needs to represent an actual consent choice, click the intended accept, reject, or settings control, wait for the page to settle, and verify the result before capturing. Hiding a banner for an image does not record consent.

Choose the screenshot state you need

Goal Method What the screenshot means
Show page content without the banner Hide the inspected banner selector with screenshot-time CSS The banner was omitted from the image; no consent choice is proven
Show the page after a real consent choice Click the specific intended control, wait, assert the resulting state, then capture The image documents the page after that interaction

Keep those goals distinct. Do not click “accept” merely to clear an overlay if the intended state is rejection or no choice. Playwright recommends handling predictable overlays explicitly in the normal test flow rather than relying on a locator handler. Its documentation also notes that handlers can change focus and mouse state, so later actions should be self-contained and the expected result should be checked.

Hide a banner only in the screenshot

1. Inspect the target site

Open browser developer tools, inspect the visible banner, and identify a narrow, stable selector for the banner element. Check whether it has a separate backdrop or overlay; that may need its own inspected selector. Avoid broad selectors such as [class*="cookie"] or [class*="overlay"] unless inspection confirms they match only the intended element.

2. Capture with screenshot-time CSS

Runnable example using Playwright’s JavaScript library:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });

  try {
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    await page.screenshot({
      path: 'page.png',
      fullPage: true,
      style: [
        '#site-specific-consent-banner { display: none !important; }',
        '#site-specific-consent-backdrop { display: none !important; }'
      ].join('\n')
    });
  } finally {
    await browser.close();
  }
})();

Install Playwright with npm install playwright and install the browser with npx playwright install chromium. Replace both example selectors with selectors inspected on the target site. Remove the backdrop rule if the site has no separate backdrop. The screenshot style option is intended for capture-specific style changes, including hiding dynamic elements; Playwright documents that it pierces Shadow DOM and applies to inner frames.

The CSS is applied for the screenshot. It does not click a consent control or establish that the website saved a consent state. Inspect the resulting image: a missed banner, backdrop, or fixed element can still obscure content. If the banner is inside a cross-origin frame, verify the capture on that site rather than assuming the selector applies across frame boundaries.

When the test or evidence needs to show the page after a choice, use a locator for the exact control the scenario calls for. The example below rejects optional cookies; change the accessible name and expected result to match the target site and your test case.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();

  try {
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

    const rejectButton = page.getByRole('button', {
      name: 'Reject optional cookies',
      exact: true
    });
    await rejectButton.waitFor({ state: 'visible' });
    await rejectButton.click();

    await page.locator('#site-specific-consent-banner').waitFor({ state: 'hidden' });
    // Add a site-specific assertion that confirms the intended post-choice state.
    await page.screenshot({ path: 'page-after-reject.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

The button name and banner selector are examples, not universal values. Use the site’s actual accessible name or a stable locator. If dismissal triggers navigation or asynchronous content changes, wait for the relevant navigation, state, or content instead of relying on a fixed delay. Assert the consent state when the site exposes one you can check. This method interacts with the page and may persist state through cookies or other storage; use a fresh browser context when each run needs an independent state.

Full-page and element screenshots

Playwright’s fullPage: true captures the full scrollable page as if it fit in a tall viewport. It changes the capture area, not the consent state. If the banner covers only a particular element or viewport, you can capture that element directly:

const target = page.locator('main article');
await target.screenshot({ path: 'article.png' });

Choose the scope that matches the intended evidence: a full-page image for the whole document, or an element image for a specific section. Check whether a fixed banner still overlaps the target element in the rendered result.

Common problems and fixes

Problem Likely cause Fix
The banner still appears The selector does not match the live element, or the banner is rendered in another frame Inspect the page after it loads, confirm the matched element, and test the screenshot output. Add a separately inspected backdrop selector if needed.
Other page content disappears A broad CSS selector matched unrelated elements Replace it with a site-specific selector verified in developer tools.
The banner vanishes but the page remains dimmed A separate backdrop or modal overlay remains visible Inspect the backdrop and hide its specific selector for visual-only captures.
The click times out The control is not visible yet, the accessible name differs, or a different dialog is present Inspect the live dialog, use the actual control name, and wait for that control to become visible. Do not substitute an unintended choice.
The banner returns on the next run The new browser context has no saved consent state For a post-choice capture, perform the intended choice in each fresh context. For screenshot-only cleanup, keep using capture-time CSS.
A click seems to work but the screenshot is inconsistent The site has asynchronous updates or a handler changed page interaction state Wait for a specific post-choice condition and assert it before capture. Keep subsequent actions self-contained.

Repeatable captures: reliability, speed, and cost

  • Prefer stable selectors. Site-specific inspection is more reliable than guessing from common class-name fragments because cookie interfaces do not share one universal selector.
  • Wait for conditions, not arbitrary time. Wait for the banner, the intended control, or a meaningful post-choice state. Fixed sleeps can be too short on a slow page and waste time on a fast one.
  • Keep the consent state reproducible. Use a clean browser context for independent test cases, then make the intended choice explicitly when the test requires one.
  • Verify representative pages. Banner markup and backdrops can differ by site or consent platform. Check screenshots for the actual targets and after selector changes.
  • Account for browser setup. A local Playwright flow requires a compatible browser installation and the time to launch, navigate, settle the page, and capture. Reuse browser processes for batches where your test architecture permits it, while keeping contexts separate when state isolation matters.
  • Budget for retries thoughtfully. A retry can help with transient loads, but repeated clicks may be unsafe if the action changes state. Check whether the intended choice already took effect before repeating an interaction.

Playwright is a do-it-yourself browser automation option. A hosted screenshot service can reduce browser setup for repeated captures, but automatic consent handling may click a control and change site state. For example, Browserless documents a screenshot endpoint with blockConsentModals=true and a custom-selector fallback when its built-in handling misses a site. Verify what choice its behavior makes before treating the resulting image as evidence of a particular consent state. Its Playwright example likewise uses a short list of common selectors and checks visibility before clicking, underscoring that site behavior needs checking.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF. For example, use this cURL call to capture a page:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. The service accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each of those steps 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. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents.

ScreenshotNeo includes 1,000 screenshots per month free with no card. Paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan. The API also supports full-page and element captures, custom CSS and JavaScript, waits, request blocking, custom headers and cookies, caching, and more; consult the docs for the available parameters.

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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Use screenshot-time CSS in Playwright when you need a controlled, visual-only change. Use an explicit consent interaction when the capture must reflect a real choice. For an API capture, try ScreenshotNeo when removing common banners and overlays without managing a browser is useful; verify that its automatic interaction matches your intended consent state.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

No. Screenshot-time CSS changes what appears in the image. It does not by itself activate the site’s consent interface or prove a choice was stored.

No. For a predictable overlay, handle it explicitly in the test flow. Locator handlers can be useful for unexpected overlays, but they can affect focus and mouse state, so make following actions self-contained and verify the outcome.

No. Full-page capture changes the screenshot’s dimensions. Hide the specific element or handle the consent interaction separately.