How to Accept Only Necessary Cookies Before Taking a Website Screenshot
Choose the site's necessary-only or reject-nonessential option, verify the choice, then capture the page. Here is a site-specific Playwright workflow.
Use a fresh browser session, identify the site’s actual necessary-only or reject non-essential control, select it deliberately, verify the choice, and then take the screenshot. There is no universal cookie-banner selector that can reliably make this choice: banners use different frameworks, wording, and controls. A button called “Accept” may accept every category.
The example below uses Playwright with a non-persistent browser context. You must supply a selector for the correct control on the target site and, where possible, a site-specific way to verify the saved preference. If the correct choice is missing or ambiguous, stop and inspect the banner rather than clicking a fallback.
What the choice means
When a banner offers multiple options, compare their stated effects:
| Control | What to check |
|---|---|
| Necessary only, reject optional, or equivalent | Use this when the task requires the least permissive available choice. Confirm the wording applies to non-essential categories. |
| Preferences or configure | Open the settings and disable optional categories, then save the settings if the site provides that flow. |
| Accept all | This is not equivalent to necessary-only consent. Do not use it for this workflow. |
Button prominence, a selector containing the word “accept,” and a dismissed banner do not establish what preference was recorded.
Playwright workflow
- Start a new non-persistent browser context so the run does not inherit consent state from an earlier run.
- Open the target URL and wait for the page and consent interface to settle.
- Inspect the visible banner and accessible control names. Determine the site-specific control for necessary-only or rejecting non-essential cookies.
- Click only that control. If it is absent or unclear, stop instead of selecting another option.
- Verify the resulting choice using the site’s confirmation or preference interface. Inspect cookies as supporting diagnostic evidence where appropriate; cookie names alone may not reveal the full consent state.
- Capture the page after the choice and verification. Choose viewport or full-page capture according to the task.
Install Playwright with npm install playwright and install its Chromium browser with npx playwright install chromium. Save this as capture.mjs. Set TARGET_URL and NECESSARY_ONLY_SELECTOR to site-specific values; the selector must point to the actual necessary-only control, not an accept-all button.
import { chromium } from 'playwright';
const url = process.env.TARGET_URL;
const consentSelector = process.env.NECESSARY_ONLY_SELECTOR;
if (!url || !consentSelector) {
throw new Error('Set TARGET_URL and NECESSARY_ONLY_SELECTOR after inspecting the site banner.');
}
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext(); // isolated, non-persistent session
const page = await context.newPage();
try {
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 45000 });
// Give client-rendered consent UI time to appear. This is not proof that
// every page resource has finished loading.
const choice = page.locator(consentSelector);
await choice.waitFor({ state: 'visible', timeout: 15000 });
// Log the visible label for review before selecting the configured control.
console.log('Configured consent control:', await choice.innerText());
await choice.click();
// Replace this check with a site-specific confirmation where available.
// A hidden banner proves dismissal only; it does not independently prove
// which preference was stored.
await choice.waitFor({ state: 'hidden', timeout: 10000 });
console.log('Cookies after choice:', await context.cookies(url));
// Optional: add a site-specific assertion here, such as reopening settings
// and confirming optional categories remain disabled.
await page.screenshot({ path: 'screenshot.png', fullPage: true });
} finally {
await context.close();
await browser.close();
}
Playwright’s non-persistent browser contexts isolate browsing data and do not write it to disk. Its context API also provides cookie operations, while the Page API provides navigation and screenshot methods. These APIs do not interpret consent wording for you: the locator and meaningful verification remain site-specific. See the [Playwright BrowserContext documentation](https://playwright.dev/docs/api/class-browsercontext) and [Playwright Page documentation](https://playwright.dev/docs/api/class-page).
For accessibility-based selection, inspect the control first and use its actual accessible name, for example page.getByRole('button', { name: 'Reject non-essential cookies', exact: true }). Do not guess that name across sites. If several controls match, make the locator specific to the consent dialog and confirm it resolves to exactly one element before clicking.
Verification: what counts as evidence?
- Strongest practical check: the site’s own preference center or confirmation state shows optional categories disabled or the necessary-only preference saved.
- Useful supporting check: inspect the relevant consent cookie or storage entry before and after the choice, if you know how that site represents consent.
- Insufficient on its own: the banner disappeared, a click succeeded, or the screenshot looks unobstructed. Those observations do not show which choice was saved.
Some sites apply the choice by reloading, navigating, or updating client-side state. If so, follow the site’s flow and verify again after it settles. Keep the same browser context between consent and capture; a new context would lose the state you just established.
Screenshot options and page readiness
Consent selection and screenshot settings solve different problems. Full-page capture changes the captured area; viewport capture records only the visible viewport. Neither option changes cookie preferences.
- Use
fullPage: truewhen you need the page beyond the viewport. Long or dynamic pages may need additional readiness handling. - Use
fullPage: falsefor the current viewport. - Choose a viewport before navigation when responsive layout matters:
await page.setViewportSize({ width: 1440, height: 900 }). - For pages that load content after navigation, wait for a page-specific selector or a deliberate delay. Avoid assuming that network idle is available or meaningful on pages with continuous requests.
- Keep the browser context open through consent verification and capture. Close it afterward to discard the isolated session.
Playwright’s [Page API](https://playwright.dev/docs/api/class-page) documents screenshot options and navigation. Browserless also provides a [cookie-consent example](https://docs.browserless.io/examples/cookie-consent) that checks for a visible matching control before clicking and capturing. Its selectors need adjustment for the target banner framework, such as OneTrust or CookieBot; treat it as an implementation example, not a generic necessary-only solution.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Selector times out | The banner has not appeared, uses a different selector, is inside an iframe, or is absent because the site already has state. | Inspect the rendered page and frame structure. In a fresh context, identify the actual visible control and use a site-specific locator. |
| Several elements match | The selector is broad or matches hidden copies of the banner. | Scope the locator to the consent dialog and verify it matches one visible control before clicking. |
| The banner disappears but optional cookies remain | The clicked control may have accepted all, the site may store preferences elsewhere, or the choice may not have been saved. | Reopen the site’s preference center and inspect the saved categories. Correct the site-specific control and verification flow. |
| Consent appears on every run | A fresh context intentionally starts without the previous run’s state. | For a one-off isolated capture, make the choice each run. If persistence is required, save and reuse a browser state only where appropriate for your workflow, and understand that doing so changes the isolation behavior. |
| Screenshot contains the banner | The capture ran before the click or dismissal completed, or the banner reappeared after navigation. | Wait for the selected control’s action and the site’s resulting state; verify before capturing. |
| Click is intercepted or has no effect | An overlay, animation, iframe, or client-side handler prevents the intended interaction. | Inspect the live page, wait for the interface to settle, locate the correct frame or control, and avoid force-clicking until the cause is understood. |
| Page is incomplete | Navigation completion did not wait for the site’s later content or lazy-loaded sections. | Wait for a task-specific element or load condition before capture; scroll when the page requires it to load lazy content. |
Reliability, performance, and cost
A fresh context makes runs more repeatable because an earlier choice does not silently determine the banner state. It also means each run may need to make the choice again. Site-specific inspection and verification add steps, but they prevent the more costly failure of producing a screenshot under an unintended consent state.
Use bounded navigation and locator timeouts so a missing banner does not hang the job indefinitely. Record the target URL, selected control, verification result, and capture outcome in your own run logs, while avoiding unnecessary storage of sensitive page data. If the consent interface is ambiguous, treat the run as needing review instead of taking an unverified screenshot.
For UK sites, the Information Commissioner’s Office guidance on PECR says consent should be freely given, specific and informed, based on an unambiguous positive action, and that non-essential cookies should not be set before consent. This is UK guidance, not a universal legal conclusion or legal advice; see the [ICO guidance on cookies and similar technologies](https://ico.org.uk/for-organisations/direct-marketing-and-privacy-and-electronic-communications/guide-to-pecr/cookies-and-similar-technologies/?q=consent).
Or skip the browser setup
[ScreenshotNeo](https://screenshotneo.com) is a website screenshot API and MCP server. Its API accepts one GET request for a screenshot or PDF; see the [API documentation](https://screenshotneo.com/docs/). For example, this cURL request saves a WebP screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The equivalent Python request is:
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)
And in 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 import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
- Cookie and consent banners are accepted as a visitor; 60+ known consent platforms, newsletter popups, and chat widgets are removed before capture. Each step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for AI agents and MCP clients. - The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan.
ScreenshotNeo handles common cleanup automatically, but when your task specifically requires a documented necessary-only choice on a particular site, verify that site’s resulting preference as required by your workflow. [Create a free account](https://screenshotneo.com/account/sign-up/) for 1,000 screenshots a month with no card.
FAQ
Can I use one selector for every site’s necessary-only button?
No. Consent interfaces vary in framework, markup, wording, and behavior. Choose and verify a site-specific control.
Does a clean browser context automatically reject optional cookies?
No. It isolates the session; it does not make a consent choice. You still need to select the site’s necessary-only option and verify the result.
Does taking a full-page screenshot change the consent state?
No. Full-page and viewport settings affect the captured image area, not the site’s stored preference.
What if the site offers only “Accept” and “Manage preferences”?
Open preferences and look for a way to disable optional categories and save. If the effect remains unclear, do not assume “Accept” means necessary-only.
Is the ICO guidance applicable everywhere?
No. The cited material is UK PECR guidance. Requirements depend on jurisdiction and context.
A Playwright maintainer has also described cookie dialogs as site-specific because different sites implement them with different frameworks and approaches; see [Playwright issue #2566](https://github.com/microsoft/playwright/issues/2566). The practical rule remains: inspect the actual control rather than trusting a generic selector.


