The top pick for capturing clean, consent-managed website screenshots with Playwright is a combination of Chromium with a persistent context and a custom route handler that blocks known CMP scripts, paired with a pre-seeded localStorage state that accepts or rejects cookies automatically. This approach gives you deterministic, repeatable screenshots without waiting for network timeouts or fighting with dynamic banners, and it works across most major CMPs including OneTrust, Cookiebot, and Quantcast Choice.
What to Look For
When evaluating Playwright settings for CMP screenshots, the criteria that actually matter are:
- Determinism: The screenshot should look the same every run, regardless of network latency, A/B testing, or CMP script updates. This means controlling network requests, timeouts, and viewport size.
- Consent state control: You need to be able to capture both the “before consent” (banner visible) and “after consent” (banner dismissed, content loaded) states. The settings must allow you to toggle this easily.
- Speed: CMP scripts often delay page load. Blocking them or stubbing them out can cut screenshot time by 30-50%, which matters when you’re capturing hundreds of pages.
- Reliability: CMPs frequently change their DOM structure or use randomized IDs. Your settings should be resilient to these changes, using stable selectors or network-level interception rather than fragile CSS paths.
- Compatibility: The setup should work across all major browsers (Chromium, Firefox, WebKit) and with Playwright’s test runner, codegen, or standalone scripts.
Option 1: Playwright with Persistent Context and Pre-Set Cookies
Strengths: This is the most reliable way to get a consistent “after consent” state. By launching a persistent context with a user data directory, you can pre-set the CMP’s consent cookies (e.g., CookieConsent for Cookiebot, OptanonConsent for OneTrust) to values that indicate “all accepted” or “all rejected.” Playwright’s browser.newContext({ storageState: 'state.json' }) loads these cookies before any script runs, so the CMP banner never appears. This method is fast because no network requests are blocked—the CMP scripts run but immediately see the consent cookie and hide the banner.
Trade-offs: You need to know the exact cookie names and values for each CMP you target. These can change, and some CMPs use multiple cookies or localStorage. You also need to generate the storage state by manually accepting/rejecting cookies once, then saving it. This approach is less useful if you need to capture the banner itself, since the banner is suppressed.
Best for: Teams that need clean, banner-free screenshots for documentation, marketing, or visual regression testing, and are willing to invest in setting up storage states for a known set of CMPs.
Option 2: Route Interception to Block CMP Scripts
Strengths: Using page.route() to abort requests to known CMP script URLs (e.g., **/cookiebot.js, **/consent.js, **/one-trust.js) is a quick and dirty way to prevent the banner from ever rendering. It’s easy to implement, doesn’t require pre-seeding any state, and works for both “banner visible” (by not blocking) and “banner hidden” (by blocking) states. This method is also resilient to CMP DOM changes because you’re not relying on selectors.
Trade-offs: Blocking scripts can break other page functionality that depends on the CMP (e.g., analytics, personalized content). Some CMPs use inline scripts or dynamic URLs that are hard to block comprehensively. Also, this method doesn’t simulate the real user experience of interacting with the banner—it just removes it, which might not be what you want for screenshots that need to show the banner.
Best for: Quick, ad-hoc screenshots where you just need the page content without a banner, and you don’t care about the consent state being “real.” Good for development and debugging.
Option 3: Playwright’s Auto-Waiting and Fixed Timeouts
Strengths: Playwright’s default auto-waiting waits for elements to be stable, which helps ensure the CMP banner is fully rendered before you screenshot. By setting a generous timeout in the goto() call (e.g., 30 seconds) and using waitForSelector() on the banner element, you can reliably capture the “banner visible” state. This is the simplest approach—no extra configuration, just standard Playwright usage.
Trade-offs: It’s slow because you’re waiting for all resources to load, including CMP scripts that might be slow. It’s also fragile if the CMP’s banner appears after a delay or uses animations—you might need to add a fixed wait (e.g., page.waitForTimeout(2000)) which is a known anti-pattern. If the CMP fails to load, your screenshot might miss the banner entirely.
Best for: Small projects with a handful of screenshots, where speed isn’t critical and you need to capture the actual banner as it appears to users.
Option 4: Emulating Consent via localStorage Injection
Strengths: Many CMPs store consent state in localStorage (e.g., cookieConsent key). You can use page.addInitScript() to set those localStorage values before any page script runs. This is similar to the cookie approach but uses localStorage, which some CMPs prefer. It’s deterministic and fast, and you can easily switch between “accepted” and “rejected” states by changing the script.
Trade-offs: The exact localStorage keys and values are CMP-specific and can change. Some CMPs encrypt or obfuscate their state, making this method impossible. You also need to know the structure of the consent object (e.g., { necessary: true, analytics: false }) to craft the right injection.
Best for: Teams that already work with a specific CMP and can inspect its localStorage format. Good for automated visual testing where you want to test both consent states.
Option 5: Using Playwright’s Built-in Device and Viewport Settings
Strengths: CMP banners often behave differently on mobile vs. desktop. Playwright’s devices presets (e.g., iPhone 13, Pixel 5) automatically set viewport size, user agent, and device scale factor. This is essential for capturing accurate mobile screenshots, especially since many CMPs show a full-screen overlay on mobile. The settings are easy to apply and ensure your screenshots match real device dimensions.
Trade-offs: Device presets don’t control CMP behavior—you still need to handle consent state separately. Also, some presets have odd viewport sizes that might crop content unexpectedly. You’ll need to adjust your screenshot clipping or full-page capture settings accordingly.
Best for: Teams that need screenshots for both desktop and mobile versions of a site, and want to use realistic device emulation without manually configuring viewport and user agent.
Option 6: Combining Network Throttling and Wait for Network Idle
Strengths: For capturing the “banner visible” state, you might want to ensure the CMP script has loaded but the banner is still shown. Using page.goto(url, { waitUntil: 'networkidle' }) ensures all network requests have finished, so the banner should be fully rendered. Combined with a slow network throttle (via context.setOffline or CDP’s Network.emulateNetworkConditions), you can simulate a slow connection and capture the banner before it auto-dismisses (if it does). This gives a realistic screenshot of what a user sees on a slow connection.
Trade-offs: Waiting for network idle can be very slow on pages with many requests, and some CMPs use long-polling or websockets that prevent network idle from ever firing. Throttling is also not available in all browsers (it’s Chromium-only via CDP). This method is more complex and less reliable than others.
Best for: Advanced users who need to capture the banner in a realistic network scenario, such as for performance testing or user experience research.
How to Choose
Start by clarifying your use case: are you capturing the banner (consent prompt) or the clean page after consent? For banner screenshots, use Option 3 (auto-waiting) with a fixed timeout, or Option 6 if you need network realism. For clean screenshots, use Option 1 (persistent context with cookies) or Option 4 (localStorage injection) for the most reliable results. If you’re on a tight budget (time or money), Option 2 (route blocking) is the quickest to implement but may miss edge cases. Your budget also matters: if you have many pages, invest in Option 1 to avoid slow waits. Finally, consider your team’s skill level—Option 1 requires understanding CMP internals, while Option 3 is beginner-friendly.
Frequently Asked Questions
1. Why does my screenshot sometimes miss the CMP banner?
The banner might load after your screenshot triggers. Use waitForSelector() on the banner’s element (e.g., #onetrust-banner-sdk) before taking the screenshot, and set a timeout of at least 10 seconds.
2. Can I use the same settings for all CMPs?
No. Each CMP has different cookie names, script URLs, and DOM structures. You’ll need to adapt your settings per CMP, though route blocking can be generic if you block common CMP script patterns.
3. What’s the best way to capture a full-page screenshot with a CMP?
Use page.screenshot({ fullPage: true }), but be aware that the CMP banner might only appear in the initial viewport. If you need the banner in the full-page shot, you may need to scroll to the top first and take a non-full-page screenshot.
4. How do I handle CMPs that use iframes?
Some CMPs (like Quantcast) load their banner in an iframe. You’ll need to use frameLocator() to interact with the iframe, or block the iframe’s URL if you don’t need it.
5. Is it better to block CMP scripts or to set consent cookies?
Blocking is faster and simpler, but it might break other scripts that depend on the CMP. Setting consent cookies is more realistic and doesn’t break functionality, but requires more setup. For visual regression testing, blocking is usually sufficient.
6. Can I use Playwright’s codegen to record CMP interactions?
Yes, playwright codegen can record your clicks on the banner, and you can then replay those steps in your test. However, the generated code may be brittle if the CMP’s selectors change.
Bottom Line
For most teams, the best practical setup is a combination: use persistent context with pre-set consent cookies for clean screenshots, and auto-waiting with a fixed timeout for banner screenshots. If you’re just starting out, begin with route blocking to get quick results, then refine to cookie-based states as you scale. Remember to test your settings across browsers and update them whenever the CMP changes.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Compressed Zipped Folder Access Denied? Fix It
- IPTV TV Boxes: How to Choose the Right Streaming Device
- Custom Races in Assetto Corsa: Server Setup Guide
- Dueling Grounds Events Schedule: Full Guide
- Evaluating Co-Packaged Optics Switches for AI Data Centers
- RTX 5080 Best Settings for 1440p & 4K Gaming