ScreenshotNeo

BlogHow-to

How to Remove Cookie Banners Before Capturing Web Pages

Hide a consent banner for a clean screenshot, or make a real consent choice before capturing. Here are practical Playwright methods and ways to verify the result.

By the ScreenshotNeo team4 October 20269 min read

To remove a cookie banner from a screenshot without accepting cookies, hide or mask the specific banner only while taking the screenshot. That changes what appears in the image; it does not record consent or reject cookies. If you need a screenshot after a real visitor choice, click the page’s reject or preferences control, verify the resulting state, and then capture.

This guide uses Playwright with Node.js. It also covers cURL, Python, and a hosted screenshot option. Choose the method based on whether you need a clean image or evidence of an actual consent interaction.

Goal Method What it changes
Keep the banner out of a one-off image Screenshot-time CSS or a locator mask The screenshot appearance only; no consent choice is made.
Capture the page after a real choice Click the intended page control and wait for the result The page’s consent flow, according to that site’s implementation.
Reduce banners during manual browsing Browser or extension feature Behavior depends on browser, filter lists, and site support.

Prefer a site-specific banner selector. A broad rule matching every element whose text or class contains “cookie,” “popup,” or “overlay” can hide unrelated content, including page content you wanted to capture. Inspect the resulting image to make sure the page is still intact.

2. Set up Playwright

Install Node.js, create a project, and install Playwright. Install the Chromium browser Playwright uses:

npm init -y
npm install playwright
npx playwright install chromium

Save the following as capture.mjs. Replace the URL and #cookie-consent with the target page and the banner container selector you identified using the browser’s developer tools.

3. Hide the banner only in the screenshot

Playwright’s page.screenshot() supports screenshot-time style injection. The style is applied for the screenshot rather than saved as a site change.

import { chromium } from 'playwright';

const url = 'https://example.com';
const bannerSelector = '#cookie-consent';
const browser = await chromium.launch({ headless: true });

try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
  await page.locator(bannerSelector).waitFor({ state: 'visible', timeout: 5_000 }).catch(() => {});

  await page.screenshot({
    path: 'page.png',
    fullPage: true,
    style: `${bannerSelector} { display: none !important; }`
  });
  console.log('Saved page.png');
} finally {
  await browser.close();
}

The locator wait is optional. It gives a banner that appears shortly after page load a chance to render; if the site does not show it, the wait expires and capture continues. If the banner is inside an iframe, a style injected into the main document may not reach it. Inspect the frame and handle it separately, or use a mask if the screenshot API and target support it.

Mask the known banner instead

If you only need to cover the banner’s region, use Playwright’s screenshot mask option. A mask keeps the page layout in place and overlays the matched locator; it does not remove the banner from the page.

await page.screenshot({
  path: 'page-masked.png',
  fullPage: true,
  mask: [page.locator('#cookie-consent')]
});

Check the installed Playwright version’s Page API documentation for current screenshot options and behavior. A locator that matches nothing or multiple unintended elements can produce an error or an incorrect image; inspect the locator before relying on it in a batch job.

For consent testing, interact with the intended control instead of hiding the banner. Use an accessible role and name where possible, then wait for a meaningful post-choice condition. Button text and behavior vary by site, so adjust the example for the page under test.

import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded', timeout: 30_000 });

  const rejectButton = page.getByRole('button', { name: /reject|decline|necessary only/i });
  await rejectButton.waitFor({ state: 'visible', timeout: 10_000 });
  await rejectButton.click();

  await page.locator('#cookie-consent').waitFor({ state: 'hidden', timeout: 10_000 });
  // Replace this with an assertion for the consent state your test requires.
  await page.screenshot({ path: 'after-reject.png', fullPage: true });
} finally {
  await browser.close();
}

Do not treat disappearance of the overlay as proof that the intended preference was recorded. For a reliable test, verify the site’s resulting state using an observable behavior appropriate to that application, such as its confirmation UI or the consent state your test is designed to check. Browserless’s cookie-consent example illustrates automated dismissal and notes the practical challenge: sites do not share one universal button attribute or selector.

5. Use cURL, Python, or Node.js with ScreenshotNeo

If you do not want to run and maintain a browser for screenshot capture, ScreenshotNeo provides a screenshot API and MCP server. Its API can return PNG, JPEG, WebP, or PDF, and its capture flow accepts consent banners and removes known consent platforms, newsletter popups, and chat widgets before the shot. Each cleanup step can be turned off. See the ScreenshotNeo API documentation for parameters and response details.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Replace the example target URL as needed. Keep the API key private; do not put it in public client-side code. This API’s automatic cleanup aims at a clean capture and does not represent a visitor’s recorded consent choice. If your task is consent-flow testing, use browser automation to make and verify the actual choice.

6. Browser and extension options

For repeated manual browsing, browser-level blocking can reduce banner interruptions, but coverage and behavior vary. Mozilla’s current support page says its Firefox cookie banner blocker is no longer available and points readers to uBlock Origin with the AdGuard/uBO – Cookie Notices filter list. Mozilla’s description of the former feature, including its Firefox 120 history and supported-site limitations, is historical context rather than a currently available Firefox setting. See Mozilla’s cookie-banner guidance.

For automation, a hosted browser or screenshot service can avoid maintaining browser binaries and capture infrastructure. Browserless documents an automation example for consent dismissal; ScreenshotNeo offers automatic cleanup before a shot. These approaches have different semantics: dismissal attempts to interact with page controls, while visual removal is intended to produce a clean image. Confirm which outcome you need before choosing.

7. Relevant capture choices and edge cases

  • Full page or viewport: Full-page capture can include content below the fold, but lazy-loaded content may need scrolling or a service option that loads lazy images. A viewport capture is faster and avoids stitching behavior.
  • Late banners: Consent scripts may render after the initial document load. Wait for the known selector or use a bounded delay; avoid arbitrary long waits in large batches.
  • Single-page apps: Wait for the page’s meaningful content or a specific selector, not just the navigation event.
  • Frames and shadow DOM: A selector in the main document cannot necessarily reach an iframe or closed shadow root. Locate the correct frame or use the supported page interaction.
  • Sticky overlays: A banner may be fixed to the viewport and appear differently in full-page screenshots. Inspect both viewport and full-page output.
  • Persistent state: A click may persist consent in cookies or local storage. Use a fresh browser context for repeatable tests, and do not reuse state unless persistence is what you intend to test.
  • Selector drift: Site redesigns can change IDs, classes, accessible names, and button order. Keep selectors close to the test and fail visibly when the expected target is absent.
  • Authentication or geo-specific banners: The displayed consent interface can depend on region, account state, or previous visits. Set up the same context the test is meant to represent.

8. Reliability, performance, and cost

For one screenshot, screenshot-time CSS is usually the smallest change to manage. For a recurring test, use a fresh context, a page-specific selector, a bounded timeout, and an assertion for the expected result. Save screenshots on failure as well as success when they are needed to diagnose a test, and avoid silently swallowing a missing banner when its presence is part of the scenario.

Capture time is shaped by navigation, site scripts, image loading, and wait conditions. Prefer a specific ready condition over a long fixed sleep. Full-page capture can take longer and produce larger files than viewport capture. Reusing a browser process can reduce setup overhead in a batch, while a fresh context helps isolate cookies and storage between URLs.

Self-hosted Playwright has no per-shot API charge, but it uses your compute, browser maintenance, and engineering time. With ScreenshotNeo, failed loads, timeouts, blank pages, bot checks/CAPTCHAs, and cache hits are not billed; response headers identify the page verdict and billing status. Plans include 1,000 shots a month free without a card; paid plans start at $5 for 3,000 shots. Yearly billing gives two months free, and every feature is available on every plan. Check the current ScreenshotNeo site for plan details.

9. Troubleshooting

Symptom Likely cause Fix
The banner remains visible Wrong selector, late render, or the banner is inside a frame. Inspect the live DOM, wait for the actual container, and check frames. Confirm the screenshot-time style includes the right selector.
Page content disappeared too The selector is too broad or matches a shared wrapper. Use a narrow site-specific container selector and inspect the full-page image.
Consent test passes but the choice was not made The script hid the UI or clicked a generic control without verifying state. Click the intended reject/preferences button and assert the expected post-choice condition.
Playwright times out waiting for a locator The site changed, the banner is absent in this context, or it appears in another frame. Confirm the expected scenario, update the locator, and make timeout behavior explicit.
Screenshot is blank or incomplete Capture happened before the page rendered, navigation failed, or the site gates content. Wait for a relevant content selector, check navigation errors, and inspect the response/page state before capture.
Python reports a connection or timeout error The API request exceeded its timeout or network access failed. Use a suitable timeout, check connectivity and status, and retry only transient failures with a bounded policy.
API returns an error instead of an image Missing/invalid key, invalid parameters, or a failed page capture. Check the key and request parameters, inspect the HTTP status and ScreenshotNeo response headers, and consult the API docs.

10. Frequently asked questions

Does hiding the banner accept or reject cookies?

No. Screenshot-time CSS and masking affect the image. To make a real choice, operate the page’s consent controls and verify the resulting state.

Can I use one selector on every website?

No universal selector is reliable. Banner markup and button names differ, so inspect each target or use a service’s documented cleanup behavior with output verification.

Mozilla’s current support article says the Firefox cookie banner blocker is no longer available. It recommends a uBlock Origin cookie-notice filter-list approach.

No. A visually clean image says nothing by itself about stored preferences or which scripts ran. Use a consent-focused test and verify the relevant page behavior.

Or skip the browser setup

ScreenshotNeo makes one API call for a page capture. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

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

Create a free ScreenshotNeo account to get 1,000 screenshots a month without a card.