ScreenshotNeo

BlogHow-to

How to Test Cookie Consent Banner Screenshots in Cypress After Accepting Cookies

Set consent state deliberately, verify the banner is gone, and capture a repeatable Cypress screenshot. Learn when to click Accept, seed storage, or add visual comparison.

By the ScreenshotNeo team4 October 20267 min read

To capture a Cypress screenshot after cookie consent, make the consent state explicit, wait for the expected post-acceptance state, and call cy.screenshot() only after retryable assertions pass. Click the real Accept control when the test covers the consent flow. For unrelated visual tests that need a returning-visitor state, seed the application’s actual consent storage before visiting the page.

The examples below use placeholder selectors and cookie values. Replace them with the contract your application actually uses. Cypress clears cookies and web storage between tests by default when test isolation is enabled, so each test that depends on accepted consent needs its own setup. Cypress FAQ

1. Decide what the screenshot should prove

There are two useful test goals, and they need different setup:

  • Consent behavior: show the banner, click the actual acceptance control, verify the banner disappears and consent persists, then capture the accepted state.
  • Another page’s appearance for an accepted visitor: seed the known consent state directly, visit the page, verify the banner is absent, and capture it. This avoids repeating the consent interaction in every unrelated visual test.

Keep a separate first-visit checkpoint if the banner’s appearance matters. A screenshot is only a captured image; Cypress’s built-in screenshot command does not compare it with an approved baseline. For visual regression, use a comparison workflow or integration and review the baseline. Cypress visual testing guide

2. Test the real accept flow

Use stable selectors owned by your app, such as data-testid attributes. Assert the initial banner, perform the interaction, then assert both the resulting UI and the persisted state before capturing.

describe('cookie consent', () => {
  it('captures the page after accepting cookies', () => {
    cy.visit('/')

    cy.get('[data-testid="cookie-banner"]').should('be.visible')
    cy.get('[data-testid="accept-cookies"]').click()

    cy.get('[data-testid="cookie-banner"]').should('not.exist')
    // Placeholder: use your app's real cookie name and value.
    cy.getCookie('cookieConsent')
      .should('have.property', 'value', 'accepted')

    cy.screenshot('home-after-cookie-consent')
  })
})

If the banner remains in the DOM but is hidden, assert the behavior your UI actually provides, for example should('not.be.visible'), instead of not.exist. If consent is stored in local storage or session storage, verify that state instead of expecting a cookie. Cypress retries chained assertions while waiting for the expected state; those assertions make the capture checkpoint meaningful.

For a visual test concerned with page layout rather than the consent interaction, set the application’s real consent cookie before navigating to the page:

describe('returning visitor page', () => {
  beforeEach(() => {
    // Placeholder values: replace with the application's real consent contract.
    cy.setCookie('cookieConsent', 'accepted', {
      domain: 'localhost',
      path: '/',
    })
    cy.visit('/')
  })

  it('captures the page without the consent banner', () => {
    cy.get('[data-testid="cookie-banner"]').should('not.exist')
    cy.screenshot('returning-visitor')
  })
})

Set the correct domain for your test environment. Before cy.visit(), the browser is still at about:blank; without an explicit domain, a cookie command may target the spec hostname, usually localhost. Cookies also have path, secure, and same-site attributes that can affect whether the application sends or reads them. Cypress documents cookie access in cy.getCookies() and cy.getCookie().

If consent lives in local storage, seed only the application’s documented key and value in the appropriate origin before the app reads it. A reliable alternative is to visit a lightweight setup route on that origin, set storage with the application’s supported mechanism, then visit the page under test. Avoid guessing storage keys: a wrong value can hide a banner in a test fixture without representing a valid accepted state.

With Cypress test isolation enabled, cookies, local storage, and session storage are cleared before each test. Set up consent independently in each test or in a shared hook that runs for each test. This prevents order-dependent results. Cypress FAQ

cy.session() can cache and restore cookies and web storage when reusing a login or other setup is appropriate. Under test isolation, it clears the page, so call cy.visit() after restoring the session. Disabling test isolation solely to preserve consent lets tests affect one another and makes failures harder to reproduce. cy.session()

5. Capture a deliberate screenshot checkpoint

cy.screenshot() saves a named screenshot under the configured screenshots folder, which defaults to cypress/screenshots. It supports capture options including viewport, full-page, and runner captures. Capture is asynchronous, so queue it after assertions establish the state; do not infer that the page is ready just because the command has been queued. cy.screenshot()

// Consistent viewport and a full-page capture
cy.viewport(1280, 800)
cy.get('[data-testid="cookie-banner"]').should('not.exist')
cy.screenshot('accepted-home', {
  capture: 'fullPage',
  overwrite: true,
})

Choose a fixed viewport for comparable screenshots. Wait for content that affects the image, such as a page heading or a loaded image, with an assertion on that content. For content driven by a network request, control the response with a Cypress route alias and wait for it, then assert the rendered result. Avoid arbitrary sleeps when a state assertion can express readiness.

6. Add visual regression comparison when needed

A generated PNG alone does not fail a test when pixels change. If the requirement is to catch unintended visual changes, add an image comparison integration or another baseline review workflow. Keep the rendering environment and viewport consistent, control variable network data, and choose intentional checkpoints. An element-level snapshot can avoid unrelated failures caused by changes elsewhere on a full page. Cypress’s visual testing guide lists integrations, including Percy by BrowserStack, and explains the comparison workflow. Visual testing in Cypress

7. Common errors and fixes

Symptom Likely cause Fix
Banner reappears in each test Test isolation clears cookies and web storage. Click Accept in the test that covers the flow, or seed the real consent state in each test’s setup.
Seeded cookie is missing after navigation Cookie was assigned to the wrong domain, path, or security context. Set the intended application domain and path; inspect the cookie with cy.getCookie() after visiting.
Banner remains after clicking Accept The click did not reach the real control, or the app is still updating. Use the actual stable selector, then assert the banner’s expected absent/hidden state and the app’s persisted consent value.
Cookie assertion fails although banner disappears The application stores consent in local storage, session storage, or another mechanism. Inspect the app’s consent implementation and assert its actual persisted state.
Screenshot intermittently contains a loading state Capture occurs before async content has settled. Wait for a meaningful rendered element or controlled network response, then capture.
Screenshot exists but visual changes do not fail CI cy.screenshot() captures but does not compare against a baseline. Add a visual comparison integration or baseline review step.
Tests pass individually but fail in a suite Tests rely on consent state left by another test. Make setup per-test and avoid shared mutable browser state.

Cypress offers cy.clearAllCookies() when a test specifically needs to clear cookies, but under normal test isolation you should not need to preserve or manually clean consent across unrelated tests.

8. Performance, reliability, and cost

  • Performance: direct state seeding avoids repeating the banner interaction in every unrelated screenshot test. Keep at least one functional test that exercises the real flow.
  • Reliability: use app-owned selectors, the actual storage contract, fixed viewport dimensions, controlled network data, and assertions for the state that matters. Avoid relying on test order or arbitrary delays.
  • Cost: Cypress’s built-in screenshot command writes images as part of the test workflow. If you add a hosted visual comparison service, check that service’s current pricing and limits; no pricing is implied here.

Or skip the browser setup

If you need a clean screenshot of a consented page outside a Cypress interaction test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns an image or PDF. Its capture flow accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers say which page verdict and billing status applied. AI agents can use its MCP tools to take screenshots, get page information, and capture PDFs. It includes 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000. See the ScreenshotNeo website and API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
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 Bun.write('shot.webp', res)

These calls capture the target URL; they do not replace a Cypress test that must prove your app’s Accept interaction and storage behavior. Create a free account for 1,000 screenshots a month with no card at ScreenshotNeo sign-up.

FAQ

Does cy.screenshot() accept cookies?

No. The test must establish consent by clicking the app’s control or by setting the app’s real persisted state before capture.

No. Exercise the real flow in a functional test; seed accepted state for unrelated tests that need a returning-visitor fixture.

Does the screenshot command verify the image?

No. It captures an image. Add a visual comparison workflow when changes should be evaluated against a baseline.

Can I reuse a session between tests?

cy.session() can restore cookies and web storage, but with isolation enabled you still need to visit the page after restoring it.