# Hide cookie banners in screenshots: tested on 12 European sites

> How to take website screenshots without cookie consent banners: Puppeteer code that clicks accept, and what our API removed on 12 European sites.

Published 2026-11-08 · https://shareglint.com/en/guides/hide-cookie-banners-in-screenshots

A screenshot of a European website taken by a fresh browser shows the consent banner first: a dialog over half the page, a dimmed background and, often, scrolling switched off. For a thumbnail, a monitoring archive or a page in a report, that is the wrong picture. This page shows the two ways to get rid of it — accept or hide — with Puppeteer code, and what came out when we ran both on 12 real sites.

**How we tested.** On 2026-11-08 we captured the home pages of The Guardian, Le Monde, Der Spiegel, IKEA Germany, Booking.com, Cookiebot, Marca, Bild, Zalando, BBC, Wirtualna Polska and Onet at 1280×800, from a machine in Poland, so every site treated us as an EU visitor. Each site went through our API twice (banner option off and on) and once through the Puppeteer script below. Banners differ by country, by day and by A/B test; treat the counts as one snapshot, not a ranking of sites.

## Accept or hide?

There are two ways to remove a banner from a capture:

- **Click "accept".** The consent platform runs its own code: it stores the choice, removes the dialog and the dark overlay, and unlocks scrolling. The page then looks as it does for a visitor who has agreed — including the ads and trackers that consent switches on (after accepting on Marca, a game ad filled the top of the page).
- **Hide it with CSS.** `display: none` on the banner's container. Nothing else changes, but an overlay or a `overflow: hidden` on `<body>` may stay behind, and a full-page capture may then stop at the first screen.

In practice you do both: click where you can, hide what is left. Clicking "reject" works too where a site offers it on the first layer, but many sites put it one screen deeper, and a "pay or accept" site (Le Monde, Spiegel, Bild, Marca and The Guardian all had one) offers no free reject at all.

## Doing it yourself in Puppeteer

The script below tries the "accept all" buttons of the common consent platforms in every frame, falls back to matching button text, then injects CSS for whatever stays. It ran with Puppeteer 25 on 2026-11-08:

```javascript
import puppeteer from 'puppeteer';

// "Accept all" buttons of common consent platforms.
const ACCEPT = [
  '#onetrust-accept-btn-handler',                           // OneTrust
  '#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll', // Cookiebot
  '#CybotCookiebotDialogBodyButtonAccept',
  '#didomi-notice-agree-button',                            // Didomi
  '[data-testid="uc-accept-all-button"]',                   // Usercentrics
  '.qc-cmp2-summary-buttons button[mode="primary"]',        // Quantcast
  'button.sp_choice_type_11',                               // Sourcepoint (in an iframe)
];
// Text fallback for in-house banners.
const TEXT = /^(accept all( cookies)?|allow all|i agree|agree|alle akzeptieren|tout accepter|accepter et continuer|aceptar todo|acepto)/i;
// What to hide if clicking did not work.
const HIDE = '#onetrust-consent-sdk, #CybotCookiebotDialog, #didomi-host, #usercentrics-root, .qc-cmp2-container, [id^="sp_message_container"] { display: none !important; } html, body { overflow: auto !important; }';

async function acceptCookies(page) {
  for (const frame of page.frames()) {
    const clicked = await frame.evaluate((selectors, text) => {
      const visible = (el) => el && el.getBoundingClientRect().height > 0;
      for (const s of selectors) {
        const el = document.querySelector(s);
        if (visible(el)) { el.click(); return s; }
      }
      const button = [...document.querySelectorAll('button, a[role="button"]')]
        .find((b) => visible(b) && new RegExp(text, 'i').test(b.textContent.trim()));
      if (button) { button.click(); return button.textContent.trim(); }
      return null;
    }, ACCEPT, TEXT.source).catch(() => null);
    if (clicked) return clicked;
  }
  return null;
}

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto('https://www.theguardian.com/europe', { waitUntil: 'load' });
await new Promise((r) => setTimeout(r, 2000));   // banners arrive late
await acceptCookies(page);
await new Promise((r) => setTimeout(r, 1000));   // let the dialog close
await page.addStyleTag({ content: HIDE });
await page.screenshot({ path: 'guardian.jpg', type: 'jpeg' });
await browser.close();
```

Three details matter. Frames: Sourcepoint (The Guardian, BBC, Bild, Spiegel) draws its dialog in a cross-origin iframe, so a selector in the main frame finds nothing — `page.frames()` reaches it. Timing: most banners appear after `load`, so a fixed wait or a `waitForSelector` with a short timeout is needed. Text: the button text is in the page's language.

What this script got on the same 11 sites that showed a banner:

| Result | Sites |
|---|---|
| Banner gone | The Guardian, Le Monde, IKEA, Cookiebot, Marca, Bild, Der Spiegel (7) |
| Dialog gone, a cookie bar left at the bottom | BBC |
| Banner left: button text not in the list | Wirtualna Polska ("Akceptuję i przechodzę do serwisu"), Onet ("Przejdź do serwisu") |
| No page: the site answered "Site can't be reached right now" to default headless Chrome | Zalando |

None of these is hard to fix one by one — add the Polish texts, the BBC bar's selector, a normal user agent. That is the real cost of doing it yourself: the list grows with every site you capture, and vendors change their markup. Two shortcuts exist. The [EasyList Cookie List](https://easylist.to/) is a maintained filter list of banner elements, usable through an ad-blocking library. DuckDuckGo's [autoconsent](https://github.com/duckduckgo/autoconsent) (MPL-2.0) is a library of per-platform rules that click through consent pop-ups, choosing opt-in or opt-out, and runs in a Chrome extension or a Playwright-driven headless browser; DuckDuckGo's own browser apps use it.

## The same sites through our API

Our screenshot API does the same in one option. `block_cookie_banners` first clicks "accept" for the consent platforms it knows (OneTrust, Cookiebot, Didomi, Usercentrics, Quantcast, TrustArc, Sourcepoint) in every frame, then tries "accept" buttons by their text (English, German, French, Spanish, Italian, Polish, Dutch, Swedish, Portuguese, Czech and Hungarian) inside elements that call themselves cookie or consent banners, and hides what is left using the EasyList Cookie List, unlocking scrolling afterwards:

```bash
curl -X POST "https://shareglint.com/v1/screenshots?wait=true" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.theguardian.com/europe", "block_cookie_banners": true, "format": "jpeg"}'
```

What came out on the 12 sites:

| | Without the option | With `block_cookie_banners` |
|---|---|---|
| Sites showing a cookie banner | 11 of 12 (Booking.com showed none to us) | 1 of 12 in the first run (Marca), 0 after the fix below |
| Median render time | 5.0 s | 9.4 s |
| Other pop-ups on the picture | — | Spiegel: a subscription offer; Booking.com: a sign-in box |

Marca's banner is a "pay or accept" box whose button reads "Acepto y continúo gratis", which the text matching did not recognise in the first run. Clicking it ourselves fixed the capture: `"click_selector": ["button[action-name=\"agreeAll\"]"]`. We added the phrase to the text matching the same day, and a second capture of Marca with only `block_cookie_banners` came out clean. That is the general workaround for any banner the option misses: name its button in `click_selector`. The subscription offer and the sign-in box are not consent banners and are not touched by the option; hide them with `hide_selectors` once you know their selector (right-click → Inspect in Chrome shows it).

The extra four seconds are the price of waiting: the capture watches for consent-platform traffic and waits for late banners and for the page to settle after the click. Sites without any banner pay a little of it too (example.com: 1.8 s without the option, 6.0 s with).

## Options that go with it

- `block_ads` hides ads and blocks ad requests; on its own it also turns on `block_cookie_banners`. Useful together with "accept", which switches ads on.
- `block_trackers` blocks analytics and tracking requests (EasyPrivacy).
- `hide_selectors` takes a list of CSS selectors to hide; `click_selector` one selector or a list, clicked in order before the capture.
- `full_page` with `lazy_load` for the whole page; after an "accept" the page scrolls again.

A viewport screenshot is 1 render of the quota, a full page 2, and the same URL with the same options within 24 hours is returned from cache for free. The option list is in the [screenshot API](https://shareglint.com/en/screenshot-api) docs; [bulk screenshots](https://shareglint.com/en/guides/bulk-website-screenshots) shows how to run it over a list of URLs.

## Limits, honestly

- **Banners change.** A site that is clean today may ship a new dialog tomorrow; the filter lists catch up, but not the same day.
- **Country matters.** We captured as a visitor from Poland. Outside the EU many of these sites show a smaller banner or none, so the same URL can give a different picture from another country.
- **Accepting is accepting.** The capture session agrees to the site's cookies, so the picture shows the consented page. Nothing is stored between captures: each one connects to a fresh browser, so the banner is accepted again every time.
- **Pages behind a login** are out of reach for the API; for those, run your own Puppeteer with the session cookies.

## FAQ

### How do I take a screenshot without the cookie banner?

Either accept the banner before the capture (click its "accept all" button, as a visitor would) or hide it with CSS. Clicking is cleaner: the platform removes its own overlay and unlocks scrolling. Hiding is the fallback for banners you cannot click. With our API, set "block_cookie_banners": true and both happen for you.

### Why does my Puppeteer screenshot still show the cookie banner?

Usually one of three reasons: the banner loads a second or two after the load event, it sits in an iframe (Sourcepoint draws its dialog in one, so page.$ in the main frame finds nothing), or it is an in-house banner whose button text your script does not know. In our test, a short script missed both Polish news sites for the last reason.

### Does hiding cookie banners also remove other pop-ups?

No. Subscription offers, sign-in prompts and newsletter boxes are not consent banners. In our test Der Spiegel showed a subscription offer and Booking.com a sign-in box after the cookie banner was gone. Hide those with their own selector (hide_selectors) or close them with click_selector.

### Is it slower to remove cookie banners?

Yes, a little: the capture waits for banners that arrive late and for the page to settle after the click. On our 12 sites the median render time was 5.0 s without the option and 9.4 s with it.
