ScreenshotNeo

BlogHow-to

How to Capture a Website Screenshot with Cookie Consent Dismissed

Dismiss a site's actual cookie consent control, verify the banner is gone, then capture a viewport or full-page screenshot with Playwright.

By the ScreenshotNeo team4 October 20267 min read

To capture a website screenshot with its cookie consent banner dismissed, open the page in a browser, activate the site’s real consent control, confirm the banner has disappeared, and then take the screenshot. There is no universal consent-button selector: each site has its own interface, and the right choice depends on whether the capture should accept, reject, or simply close the prompt.

For repeatable captures, Playwright can automate those steps locally. This guide uses Python; it also includes cURL, Python, and Node.js examples for ScreenshotNeo, which handles consent-banner cleanup as part of a screenshot API request.

Before automating, decide what the screenshot is meant to represent. If the task is to see the site after a visitor accepts consent, click its accept control. If the task is to see the site without granting optional consent, use the site’s reject or necessary-only control. A close button may only hide the prompt without recording a choice, depending on the site.

Inspect the actual page and identify its button by accessible name, role, or a site-specific selector. Avoid assuming a selector such as #accept-cookies exists everywhere. Consent tools and their wording vary.

2. Capture with Playwright in Python

Install Playwright and its Chromium browser:

python -m pip install playwright
python -m playwright install chromium

Save the following as capture.py. Replace the URL and button name with the target site’s values. The script starts with a fresh browser context, waits for the page to load, clicks the intended consent button, verifies that button is no longer visible, and saves a full-page PNG.

import asyncio
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError

URL = "https://example.com"
CONSENT_BUTTON_NAME = "Accept all cookies"  # Replace with the site's exact accessible name

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(viewport={"width": 1440, "height": 900})
        page = await context.new_page()

        await page.goto(URL, wait_until="domcontentloaded", timeout=60000)
        button = page.get_by_role("button", name=CONSENT_BUTTON_NAME, exact=True)

        try:
            await button.wait_for(state="visible", timeout=10000)
            await button.click()
            await button.wait_for(state="hidden", timeout=10000)
        except PlaywrightTimeoutError:
            raise RuntimeError(
                "Consent button was not found, did not become clickable, or the banner remained visible. "
                "Inspect the page and update the accessible name or selector."
            )

        # Allow the page's post-consent UI to settle when needed.
        await page.wait_for_timeout(500)
        await page.screenshot(path="screenshot.png", full_page=True)
        await browser.close()

asyncio.run(main())

Run it with python capture.py. The example intentionally fails with a useful error if it cannot find or dismiss the named button; silently capturing with the banner still visible would hide a problem in the result.

Use a site-specific selector when accessible names are insufficient

Some controls are not exposed with a useful accessible name. Inspect the page’s HTML and use a selector that matches the actual control, for example:

button = page.locator("#site-specific-consent-accept")
await button.click()
await page.locator(".site-specific-consent-banner").wait_for(state="hidden")

These selectors are examples only. Replace them with selectors verified on the target site. If the prompt is inside an iframe or shadow root, locate the control in that frame or component instead of expecting a top-level page selector to find it.

3. Select viewport or full-page capture

A normal screenshot captures the current viewport. A full-page screenshot captures the full scrollable document. Use the extent that matches the purpose of the image:

# Current viewport
await page.screenshot(path="viewport.png")

# Entire scrollable page
await page.screenshot(path="full-page.png", full_page=True)

For an element-only image, use a locator screenshot. Locator screenshots also support options such as disabling animations. Playwright’s screenshot options support masking selected locators and applying a stylesheet; those change the rendered image and should be disclosed when the capture is evidence. See the Playwright screenshots guide and Playwright Locator API.

4. Make the capture repeatable

  • Start with a known consent state. A fresh browser context avoids cookies left by an earlier run. If the goal is to test returning visitors, deliberately reuse a context and record that choice.
  • Wait for the right condition. domcontentloaded is a starting point, but sites may render content afterward. Wait for a page-specific selector or another meaningful condition before capturing.
  • Confirm dismissal. Wait for the banner or clicked button to become hidden, and inspect the output if the page has multiple consent layers.
  • Control the viewport. Set width and height explicitly so responsive layout does not change between runs.
  • Handle dynamic content deliberately. Ads, rotating banners, animations, and personalization can change between captures. Masking, styling, or disabling animations may help with consistency, but they alter what appears in the screenshot.

For example, wait for a known content element after navigation rather than adding an arbitrary long delay:

await page.get_by_role("main").wait_for(state="visible", timeout=15000)

Use a selector that actually exists on the target site. Playwright documents page navigation and screenshot behavior in its Page API.

5. Alternative: hosted browser automation

If you need a hosted browser instead of managing a local browser installation, Browserless documents an example workflow for detecting and dismissing cookie consent banners before capture. You still need to determine the site’s actual control and intended action; the example does not make consent interfaces universal. See Browserless’s cookie-consent example.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its capture flow accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. It reports page verdict and billing status in response headers, and bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Its MCP tools let AI agents take screenshots, inspect page information, and capture PDFs.

Make one GET request with a URL. This cURL example saves a WebP image:

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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo API documentation for options and configuration. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up free and capture your first 1,000 screenshots a month with no card.

Troubleshooting

Symptom Likely cause What to do
The consent button times out The name or selector differs, the banner did not appear, or it is in a frame. Inspect the rendered page, verify the accessible name and role, and check frames or shadow roots.
The banner remains in the screenshot The click did not register, another layer appeared, or the script captured too soon. Wait for the banner to become hidden; handle any second dialog and confirm the intended consent action.
The page is blank or incomplete Navigation completed before client-rendered content appeared, or the page failed to load. Wait for a page-specific content locator and check navigation errors before capturing.
The screenshot differs between runs Viewport, cookies, personalization, animation, or live content changed. Set a fixed viewport and deliberate browser context; wait for stable content and document any masking or styling.
Click intercepted or not actionable An overlay, animation, or layout shift is covering or moving the control. Wait for the overlay and control to settle, then retry with a verified locator. Avoid forcing a click unless that matches the intended interaction.
Full-page image misses lazy content Some sites load content only as it approaches the viewport. Scroll through the page before capture and wait for the content needed in the image.

Performance, reliability, and cost

A local Playwright run uses time and compute on the machine or CI runner that launches the browser. Reuse a browser process for batches of captures when practical, but use separate contexts when each capture needs isolated cookies and storage. Full-page screenshots and pages with heavy media can take longer and use more memory than viewport captures.

Reliability mostly depends on choosing accurate selectors and waiting for observable page states. Consent interfaces can change, so keep selectors near the site-specific configuration and revisit them when the page changes. A fresh context makes first-visit prompts reproducible; a persistent context models a returning visitor.

Playwright is an open-source automation framework; the local browser workflow has no per-screenshot API charge, though the machine or CI resources have their own cost. For ScreenshotNeo, the free allowance is 1,000 shots per month without a card. Paid plans are Starter at $5 for 3,000, Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000; yearly billing gives two months free, and every feature is on every plan.

FAQ

Should I accept or reject cookies before taking the screenshot?

Use the action that reflects the screenshot’s purpose. Accepting and rejecting can produce different page states and consent behavior.

Can I just hide the banner with CSS?

You can style or mask content in a screenshot, but that only changes the image. It does not perform the site’s consent action. For an authentic post-consent view, interact with the actual control.

Can I capture only the area below the banner?

Dismiss the banner and capture the relevant locator or viewport. If the target is a specific element, Playwright supports locator screenshots.

Does full-page capture always include every image?

Not necessarily. Lazy-loaded images may require scrolling or waiting before the full-page capture.