How to Capture a Website Screenshot after Dismissing Cookie Popups
Use Playwright to make a real cookie choice, wait for the page to update, and capture a viewport, full page, or element—even when consent is in an iframe.
To capture a website screenshot after dismissing cookie popups, use browser automation to load the page, activate the site’s actual consent control, wait for the banner to close and the desired content to render, then capture the viewport, full page, or a specific element. Playwright is a practical way to do this. There is no universal cookie-banner selector: the control, its label, and whether it lives in an iframe vary by site.
This distinction matters: hiding or deleting a banner is not the same as recording consent. Consent-gated content may not appear, and the banner may return on a later run. Choose the consent option that matches your task, such as accept, reject, or configure, using the controls the site actually provides.
1. Set up a Playwright capture
The example below is a runnable Node.js starting point for a site whose consent button is exposed by the accessible role and name shown. Replace the URL and button name with the target site’s actual values. It accepts the site’s consent prompt, waits for it to disappear, and saves a full-page screenshot.
import { chromium } from 'playwright';
const url = 'https://example.com';
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
try {
await page.goto(url, { waitUntil: 'domcontentloaded' });
// Adapt the role and accessible name to the site's actual consent control.
const acceptButton = page.getByRole('button', { name: 'Accept all cookies' });
await acceptButton.waitFor({ state: 'visible', timeout: 10_000 });
await acceptButton.click();
// Confirm the consent interface closed before taking the screenshot.
await acceptButton.waitFor({ state: 'hidden', timeout: 10_000 });
// Replace this with a meaningful page-specific signal when possible.
await page.locator('main').waitFor({ state: 'visible', timeout: 10_000 });
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
Install Playwright and its browser with npm install playwright and npx playwright install chromium, then save the example as an ES module file and run it with Node.js. The locator is deliberately site-specific: inspect the page’s accessible controls or DOM and use the actual button name or a stable selector. Playwright’s guidance is to explicitly wait for and dismiss a predictable overlay in the normal flow. [Playwright Page API]
2. Find and handle the consent control
Use the real control
Prefer a locator based on an accessible role and name when the page exposes one, for example getByRole('button', { name: 'Reject optional cookies' }). A CSS selector can also work if it is stable for the target site. Select accept, reject, or settings according to the purpose of the capture; do not silently equate removing the visual overlay with a consent choice.
Check whether the banner is in an iframe
Third-party consent widgets may render inside a separate frame. A locator evaluated against the main page will not find a button inside that frame. Inspect the page’s frames, then scope the locator to the relevant frame:
for (const frame of page.frames()) {
console.log(frame.url());
}
const consentFrame = page.frameLocator('iframe[title="Consent"]');
const acceptInFrame = consentFrame.getByRole('button', { name: 'Accept all cookies' });
await acceptInFrame.waitFor({ state: 'visible', timeout: 10_000 });
await acceptInFrame.click();
The iframe selector and button name above are examples, not universal values. Inspect the actual frame URL, title, and controls. A forced click does not fix a wrong-frame locator: skipping actionability checks does not move a locator into another frame. For page structure and control discovery, inspect the DOM or accessibility information; use a screenshot to verify the visual result. [Implementation notes on consent banners in Playwright, Playwright screenshot guidance]
3. Wait for the post-consent page state
After clicking, verify both that the prompt is gone and that the content you need is present. A page-specific signal is stronger than a generic delay:
await page.getByRole('button', { name: 'Accept all cookies' })
.waitFor({ state: 'hidden', timeout: 10_000 });
await page.getByRole('heading', { name: 'Pricing' })
.waitFor({ state: 'visible', timeout: 10_000 });
Replace the heading with an element that indicates the relevant post-consent content is ready. A fixed delay can help with a known animation, but it is less reliable than waiting for an observable state. If the banner appears unpredictably, Playwright’s locator-handler mechanism may help during relevant actions or assertions; it is not a timer that runs simply because time passed. [Playwright Page API]
4. Choose the screenshot scope and output
| Goal | Playwright option | Notes |
|---|---|---|
| Visible browser viewport | page.screenshot({ path: 'page.png' }) |
Captures the current viewport. |
| Scrollable page content | page.screenshot({ path: 'page.png', fullPage: true }) |
Captures the full page beyond the viewport. |
| One component | page.locator('.product-card').screenshot({ path: 'card.png' }) |
Use a selector that identifies the intended element. |
| Higher-resolution output | await page.setViewportSize({ width: 1440, height: 900 }) with device scale configured on the browser context |
Choose scale based on the output’s resolution needs. |
Playwright supports viewport, full-page, element, and device-scale screenshot workflows. Its Python documentation also demonstrates saving to a file, returning image bytes, and capturing a locator. [Playwright screenshots, Playwright screenshots for Python]
5. Python example
Install the Python package and browser with pip install playwright and playwright install chromium. This script uses the same site-specific accessible button assumption as the Node.js example.
from playwright.sync_api import sync_playwright
url = "https://example.com"
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(viewport={"width": 1440, "height": 900})
try:
page.goto(url, wait_until="domcontentloaded")
accept = page.get_by_role("button", name="Accept all cookies")
accept.wait_for(state="visible", timeout=10_000)
accept.click()
accept.wait_for(state="hidden", timeout=10_000)
page.locator("main").wait_for(state="visible", timeout=10_000)
page.screenshot(path="page.png", full_page=True)
finally:
browser.close()
For a consent button inside an iframe, use Playwright’s frame-aware locator API, such as page.frame_locator('iframe[title="Consent"]').get_by_role(...), after determining the real frame selector.
6. cURL and Node.js with ScreenshotNeo
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. The API takes a URL and returns an image or PDF. Its cookie-consent handling accepts the banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. That behavior is useful when the target is supported, while a site-specific Playwright flow gives you direct control over the exact consent choice.
See the ScreenshotNeo API documentation for the request options. The following examples use the supplied one-call endpoint and save the response as WebP.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.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())));
ScreenshotNeo’s response includes X-Page-Verdict and X-Billed headers to identify the page result and billing status. The service does not bill bot checks or CAPTCHAs, blank pages, timeouts, failed loads, or cache hits. It also offers an MCP server for AI agents, with take_screenshot, get_page_info, and capture_pdf tools. One thousand screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Consent locator times out | The name or selector does not match, the banner has not appeared yet, or the control is inside an iframe. | Inspect accessible controls and frames, then use the actual name and frame-aware locator. Wait for the banner when it is predictable. |
| Forced click still cannot find the button | The locator is scoped to the wrong frame or document. | Identify the frame and scope the locator to it; forcing an action does not change its scope. |
document.querySelector returns nothing |
The element may be in a separate, potentially cross-origin iframe. | Use the automation framework’s frame API instead of querying the main document for that frame’s DOM. |
| Banner vanishes but expected content is missing | The banner was hidden without recording consent, or the page has not rendered its post-consent state. | Use the site’s actual consent control and wait for a meaningful content signal. |
| Banner appears inconsistently | It may be delayed or shown only for particular browser state or routes. | For predictable overlays, explicitly wait and dismiss in the flow. For unpredictable overlays, use a handler that runs at relevant actions and assertions. |
| Screenshot still contains the banner | The capture ran before dismissal completed, or the locator targeted a different banner. | Wait for the correct banner to become hidden and inspect the saved image. |
| Full-page image omits expected content | Lazy-loaded content may not have been triggered, or the page was captured before rendering finished. | Wait for the relevant content and verify the full-page result; use a page-specific readiness condition. |
For the frame and consent-state failure modes, see the implementation discussion in the Playwright cookie banner guide. Treat its examples as site-dependent rather than guarantees.
8. Performance, reliability, and cost
- Wait for the right signal: navigation completion alone may precede client-rendered or consent-gated content. Waiting on a meaningful element makes captures more repeatable than an arbitrary delay.
- Keep browser work scoped: use the needed viewport or element capture when a full-page image is unnecessary. Full-page captures can contain substantially more pixels and produce larger files.
- Make consent state intentional: browser context state, cookies, and storage can affect whether a prompt appears. Use a fresh context when the task requires seeing the prompt, and preserve the intended state when repeatability requires it.
- Inspect output and failures: save screenshots to a known path, handle timeouts, close the browser in a cleanup block, and review images when visual correctness matters. Accessibility snapshots and DOM inspection help diagnose structure; screenshots verify layout.
- Compare operating costs: a self-hosted Playwright workflow requires running the browser and maintaining selectors and frame handling. ScreenshotNeo pricing is Free for 1,000 shots monthly, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Check current options in the documentation.
FAQ
Can I use one selector for cookie banners on every website?
No. The control and its location depend on the site’s implementation and consent vendor. Inspect each target or use a service that handles supported consent platforms.
Should I accept or reject cookies for a screenshot?
Choose the site’s offered option that matches your purpose. A visual capture should represent the state you intend to document, and the real control should record that choice.
Can I take a screenshot without clicking the banner?
You can capture the page as it appears, but hiding the banner is not equivalent to recording consent and may leave consent-dependent content unavailable.
How can I verify the result?
Check the resulting image for the overlay and the expected content. Use DOM or accessibility inspection to diagnose which controls and content the page exposed.


