How to Hide Cookie Banners Before Taking a Chromium Screenshot
Hide a cookie banner in a Chromium screenshot with Playwright or Puppeteer CSS, choose selectors that match the page, and troubleshoot common edge cases.
To hide a cookie banner in a Chromium screenshot, apply CSS that sets the banner to display: none when capturing the page. With Playwright, the screenshot-time style option keeps the change focused on the screenshot:
await page.screenshot({
path: 'page.png',
style: `
#cookie-banner,
.cookie-banner,
[role="dialog"][aria-label*="cookie" i] {
display: none !important;
}
`,
});
These selectors are examples, not universal cookie-banner selectors. Inspect the target page and replace them with selectors that match its rendered banner. This changes the capture presentation; it does not record consent, accept or reject cookies, or establish legal compliance. See the Playwright Page API and the Puppeteer addStyleTag API.
1. Hide a banner with Playwright
Here is a complete runnable Node.js example. It launches Chromium, visits a page, applies capture-only CSS, saves a screenshot, and closes the browser. Install the package with npm install playwright and install its browser with npx playwright install chromium.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({
path: 'page.png',
fullPage: true,
style: `
#cookie-banner,
.cookie-banner,
[role="dialog"][aria-label*="cookie" i] {
display: none !important;
}
`,
});
} finally {
await browser.close();
}
})();
Use the screenshot-time style option for a one-off capture. Playwright applies this stylesheet while taking the screenshot, which is useful when the page itself should otherwise remain untouched. The option can also hide other dynamic elements. For a viewport-only image, omit fullPage or set it to false.
Find a selector that matches
- Open the page in Chromium’s developer tools and inspect the banner element.
- Choose a specific ID, class, or attribute selector that identifies the visible banner.
- Use the selector in the CSS and confirm it does not also match page content you want to keep.
- Capture again and inspect the output, especially if the banner appears after a delay.
A selector such as .cookie-banner is only useful if that class exists on the target page. Consent platforms and sites use different markup, and the sources do not establish one selector that works everywhere.
2. Inject CSS before the screenshot
If later steps in your flow need the banner hidden too, or you want to install CSS before several capture actions, inject a style element with page.addStyleTag():
await page.addStyleTag({
content: '.actual-cookie-banner { display: none !important; }',
});
await page.screenshot({ path: 'page.png', fullPage: true });
Replace .actual-cookie-banner with a selector found on the page. This injected stylesheet affects the current page after it is added, rather than being scoped to the screenshot call.
Puppeteer version
Puppeteer also supports stylesheet injection through Page.addStyleTag(). Install it with npm install puppeteer; the package downloads a compatible browser by default.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 1000 });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.addStyleTag({
content: '.actual-cookie-banner { display: none !important; }',
});
await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
await browser.close();
}
})();
For Puppeteer, use the same selector-inspection process: the sample selector is a placeholder and must match the page.
3. Choose between hiding, injecting, and masking
| Method | Use it when | Effect |
|---|---|---|
Playwright screenshot style |
The CSS is needed only for one screenshot. | Applies CSS during screenshot capture. |
page.addStyleTag() |
The page flow needs the CSS before capture or across capture steps. | Adds a stylesheet to the page. |
Playwright screenshot mask |
You want to cover a matched element with a colored rectangle. | Paints over the element; it does not remove its layout footprint. |
Masking is not equivalent to hiding. If the banner occupies space, a mask can leave that space in the layout; display: none removes the element from layout while the capture style applies. Screenshot controls also include output path, image type, caret behavior, scale, and full-page capture. Use only the options needed for the intended image.
4. Handle timing and unusual page structures
Banner appears after navigation
A delayed consent interface may be inserted after the initial document loads. Wait for the page state your capture needs before taking the screenshot. If you inject a stylesheet earlier, CSS can apply when a matching element is later added, provided the element is in the DOM scope reached by that stylesheet. With screenshot-time styles, ensure the page has reached the point where the banner would otherwise be visible before capturing.
Banner is inside an iframe or shadow root
Whether a selector reaches an iframe or shadow-root interface depends on the page structure and the browser API behavior. A page-level selector should not be assumed to match content in a separate frame or shadow tree. Inspect the actual implementation and use the relevant frame or DOM-specific approach if supported by the automation API. There is no universal workaround established for every consent implementation.
Banner removal changes page layout
display: none removes the matched element from layout, which may let content move into the newly available space. That is usually appropriate for an overlay, but a banner integrated into the document flow can cause the page to reflow. If the goal is only to conceal pixels while preserving geometry, a mask may be more suitable, with the tradeoff that it covers rather than removes the element.
5. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The banner remains visible. | The example selector does not match the page, or the banner is rendered in another DOM context. | Inspect the live element, update the selector, and check iframe or shadow-root boundaries. |
| The banner disappears only sometimes. | It is created asynchronously or appears after a delay. | Wait until the relevant page state is present before capture and confirm the selector matches the final markup. |
| Other page content disappears. | The selector is too broad and matches unrelated elements. | Use a more specific ID or scoped selector and inspect all matched elements before capture. |
| The screenshot has a blank area where the banner was. | A mask covered the banner, or the banner reserved space outside the hidden element. | Use a hiding rule for an overlay, or inspect the surrounding container and layout behavior. |
| The screenshot looks unchanged after adding CSS. | The stylesheet was added after the screenshot, the wrong page object was used, or the selector is wrong. | Await addStyleTag(), apply it to the page being captured, and verify the selector in the rendered DOM. |
| The site still behaves as if consent was not given. | Visual hiding does not submit a choice or save a consent preference. | Handle consent through the site’s actual consent interface when the workflow requires a real choice; do not treat CSS hiding as consent. |
6. Performance, reliability, and cost
For a single capture, screenshot-time CSS is a small, direct change and avoids adding a separate interaction to click or dismiss the banner. Its reliability depends on selector accuracy and timing: site markup can change, and delayed, framed, or shadow-root content needs separate consideration. Keep selectors specific and review captures when target sites change.
Browser automation has setup and runtime costs: a Chromium process must be installed and launched, pages must load, and screenshots consume compute and time. Reuse a browser process for batches of captures where appropriate, close pages and browsers when finished, and choose a wait condition that does not wait indefinitely on pages with ongoing network activity. The research sources provide no benchmark or cost figures, so actual performance and hosting cost depend on the workload and environment.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF, and its documented capture options include full-page screenshots, CSS selectors, custom CSS and JavaScript, waits, and browser settings. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
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)
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 require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for the free plan.
8. FAQ
Does hiding a cookie banner accept cookies?
No. CSS changes what appears in the screenshot; it does not establish a consent choice.
Can I use one selector for every website?
No universal selector is established by the documentation. Identify the banner selector on each target page.
Should I use full-page capture?
Use it when the output should include the full scrollable document. Omit it for a viewport screenshot.
Can I keep the banner’s space but conceal its contents?
A screenshot mask covers the matched element with a colored rectangle and does not remove its layout footprint. Choose it when covering is the intended result.


