Capturing Screenshots in Cypress
Cypress automatically captures a screenshot whenever a test fails during cypress run, saving it to the cypressscreenshotsFolder (cypress/screenshots by default) named after the spec and test title, which is invaluable for debugging CI failures you cannot watch live. You can also trigger screenshots manually at any point with cy.screenshot('checkout-step-2'), which is useful for capturing UI states that are not tied to a failure, such as documenting each step of a multi-step wizard for a visual audit or design review.
Cricket analogy: It's like a stadium's DRS system automatically capturing replay footage the moment a wicket appeal happens, so umpires can review exactly what occurred without needing to have watched live.
Configuring Screenshot Behavior
cy.screenshot() accepts an options object controlling capture scope: { capture: 'viewport' } captures only the visible browser viewport (the default), 'fullPage' scrolls and stitches the entire scrollable page, and 'runner' captures the whole Cypress Test Runner UI including the command log. You can also scope a screenshot to a single element by chaining it off a cy.get(), like cy.get('.checkout-summary').screenshot('summary-panel'), and control overwriting behavior with the overwrite: true option combined with the global screenshotOnRunFailure and trashAssetsBeforeRuns config settings, which by default clears the screenshots folder before each run to avoid accumulating stale images.
Cricket analogy: It's like choosing between a tight shot of just the batter's stance versus a wide panoramic shot of the whole ground, depending on whether you need detail or full context.
Visual Regression with Plugins
Cypress does not include pixel-diffing out of the box, but third-party plugins like cypress-image-snapshot, cypress-image-diff-js, or hosted services like Percy and Applitools add this capability by comparing each new screenshot against a stored baseline image and failing the test if the pixel difference exceeds a configured threshold. Because minor rendering differences (font anti-aliasing, animation timing, sub-pixel positioning) are common even on identical code, these tools typically expose a failureThreshold or similar tolerance percentage, and it is standard practice to disable CSS animations and wait for network-idle state via cy.intercept() aliases before capturing, to keep visual diffs meaningful instead of noisy.
Cricket analogy: It's like Hawk-Eye comparing a ball's tracked trajectory against a stored reference model of the stumps, needing a tolerance margin because sensor readings are never pixel-perfect.
// cypress/e2e/visual/checkout.cy.js
describe('Checkout visual regression', () => {
beforeEach(() => {
cy.intercept('GET', '/api/cart').as('getCart');
cy.visit('/checkout');
cy.wait('@getCart');
// Disable animations so diffs aren't noisy
cy.get('body').invoke('attr', 'style', '* { transition: none !important; animation: none !important; }');
});
it('matches the baseline for the summary panel', () => {
cy.get('.checkout-summary').screenshot('checkout-summary', { overwrite: true });
});
it('matches the full page baseline using an image-diff plugin', () => {
cy.matchImageSnapshot('checkout-full-page', {
capture: 'fullPage',
failureThreshold: 0.02,
failureThresholdType: 'percent',
});
});
});By default, trashAssetsBeforeRuns: true clears the cypress/screenshots folder at the start of every cypress run, so only artifacts from the most recent run are kept — useful in CI where each run should produce a clean, unambiguous set of failure screenshots.
Visual diffs are highly sensitive to non-deterministic rendering: web fonts loading asynchronously, CSS animations mid-transition, or dynamic timestamps in the UI will produce false-positive failures. Stabilize the page (wait for network-idle aliases, freeze or mock dates, disable animations) before capturing a screenshot intended for pixel comparison.
- Cypress automatically screenshots any failed test during cypress run and saves it under cypress/screenshots.
- cy.screenshot() can be called manually at any point, and can be scoped to a single element via cy.get().screenshot().
- The capture option controls scope: 'viewport' (default), 'fullPage', or 'runner'.
- Cypress does not do pixel-diffing natively; plugins like cypress-image-snapshot or services like Percy add visual regression comparison.
- Visual regression tools use a failureThreshold tolerance to avoid failing on trivial rendering noise.
- Disable animations and wait for network-idle state before capturing to keep visual diffs meaningful.
- trashAssetsBeforeRuns clears old screenshots at the start of each run to keep CI artifacts unambiguous.
Practice what you learned
1. When does Cypress automatically capture a screenshot without any explicit cy.screenshot() call?
2. Which cy.screenshot() capture option stitches together the entire scrollable page?
3. Does Cypress include pixel-diffing visual regression comparison out of the box?
4. Why do visual regression tools expose a failureThreshold setting?
5. What is a recommended practice before capturing a screenshot intended for pixel comparison?
Was this page helpful?
You May Also Like
Component Testing
Understand how Cypress Component Testing mounts individual UI components in a real browser for fast, isolated, high-fidelity assertions.
Testing File Uploads
Learn how Cypress's built-in selectFile() command tests file inputs and drag-and-drop uploads, and how to verify the resulting network request.