ScreenshotNeo

BlogHow-to

How to Enable Screenshots in Cypress

Use cy.screenshot() for manual captures and configure Cypress to save screenshots automatically when tests fail in run mode.

By the ScreenshotNeo team1 October 20266 min read

Use cy.screenshot() for a manual screenshot. Cypress also captures a screenshot automatically when a test fails during cypress run because screenshotOnRunFailure is enabled by default. Failure screenshots are not automatically taken in cypress open.

The default output directory is cypress/screenshots. The examples below show how to capture named screenshots, configure failure behavior, preserve artifacts, choose a capture mode, and avoid screenshots of unstable page states.

1. Take a screenshot manually

Add the command to any Cypress test:

describe('checkout', () => {
  it('shows the payment form', () => {
    cy.visit('/checkout')
    cy.get('[data-cy="payment-form"]').should('be.visible')
    cy.screenshot('checkout-payment-form')
  })
})

With no name, Cypress chooses a name based on the test. Supplying a name makes the artifact easier to find:

cy.screenshot('login-page')

Files are written below cypress/screenshots. A name containing path segments creates nested folders relative to that directory, so cy.screenshot('auth/login-page') is useful for organizing larger suites.

Manual screenshots work in both cypress open and cypress run. The command is asynchronous: Cypress queues it and captures the page when the command executes, so the rendered state can differ from the instant the command was called. See the cy.screenshot() API for version-specific option details.

2. Enable screenshots when tests fail

For headless or CI runs, keep the documented default explicit in cypress.config.js:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  screenshotOnRunFailure: true,
  screenshotsFolder: 'cypress/screenshots',
})

Now run the suite:

npx cypress run

When a test fails, Cypress saves a failure screenshot automatically. This behavior applies to cypress run; interactive cypress open does not automatically capture a screenshot for every failure.

To disable automatic failure screenshots:

module.exports = defineConfig({
  screenshotOnRunFailure: false,
})

You can also set shared screenshot defaults through Cypress.Screenshot.defaults(). Keep project configuration in cypress.config.js when the setting should apply to every run.

3. Configure the output folder and artifact cleanup

Change the destination with screenshotsFolder:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  screenshotsFolder: 'artifacts/cypress-screenshots',
  screenshotOnRunFailure: true,
})

Cypress clears configured asset folders before a run by default because trashAssetsBeforeRuns defaults to true. That cleanup includes nested files, not only image files. If a later process needs previous screenshots, disable cleanup:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  screenshotsFolder: 'artifacts/cypress-screenshots',
  trashAssetsBeforeRuns: false,
})

Generated screenshot folders are commonly added to .gitignore because they are regenerated artifacts. In CI, archive the folder as a build artifact or review screenshots in the service your pipeline uses. Cypress documents CI screenshot review through Cypress Cloud, but the storage and retention policy depend on your CI setup.

4. Choose the capture mode and options

cy.screenshot() supports three capture modes:

Mode What it captures Typical use
viewport The current application viewport Focused UI or visual regression snapshots
fullPage The application from top to bottom Long pages and documentation views
runner The browser viewport including the Cypress Command Log, with documented exceptions Debugging a failed test

Failure screenshots use runner mode. Manual captures can supply options such as a capture mode, clipping rectangle, blackout selectors, overwrite behavior, and before/after callbacks. For example:

cy.screenshot('dashboard-full', {
  capture: 'fullPage',
  blackout: ['[data-sensitive]', '.account-number'],
  overwrite: true,
})

Option names and supported values can vary by Cypress version. Check the current screenshot command reference before standardizing a shared helper.

5. Stabilize the page before capturing

A screenshot command does not freeze the application at the line where it appears. Wait for the state you want and verify it with a functional assertion first:

cy.visit('/reports')
cy.get('[data-cy="report-table"]').should('be.visible')
cy.get('[data-cy="loading"]').should('not.exist')
cy.get('[data-cy="report-row"]').should('have.length.greaterThan', 0)
cy.screenshot('reports-loaded')

This avoids snapshots of loading spinners, intermediate React renders, or animations. Cypress recommends confirming updates with functional assertions before visual snapshots; otherwise a visual test can fail because it captured a transient render. If the page has a known animation, wait for the state change rather than relying only on an arbitrary delay.

6. Preserve and inspect screenshots in CI

  1. Run Cypress in run mode: npx cypress run.
  2. Upload cypress/screenshots (or your configured folder) as a CI artifact, even when the test command exits nonzero.
  3. Use a unique CI workspace or set trashAssetsBeforeRuns: false when a later job must inspect earlier output.
  4. Keep screenshots out of source control unless they are intentional review fixtures.

For local debugging, open the interactive runner with npx cypress open and add an explicit cy.screenshot() where you need a capture. The automatic failure setting is aimed at run mode and does not turn every interactive failure into a file.

7. Troubleshooting

Symptom Cause Fix
No screenshot after a failed test The test ran in cypress open, or failure capture was disabled Use npx cypress run and set screenshotOnRunFailure: true.
Screenshot is in an unexpected directory screenshotsFolder was changed, or the name contains path segments Check the resolved Cypress config and inspect the configured folder.
Older screenshots disappeared trashAssetsBeforeRuns is true Set it to false when retaining prior artifacts is required.
Image shows a spinner or half-rendered page Capture ran before the UI stabilized Wait on a selector and assert the final state before calling cy.screenshot().
Two captures overwrite each other The same explicit name was reused Use unique names per state or pass overwrite: true intentionally.
Full-page image is unexpectedly large fullPage captures the entire document Use viewport, clip a region, or capture a specific state instead.
Sensitive data appears in an artifact The page contains secrets or personal data Use blackout selectors, test fixtures, or a sanitized environment before capture.

8. Performance, reliability and cost notes

  • Manual screenshots add browser work, so capture only states that help debug or verify behavior.
  • fullPage captures generally require more rendering and produce larger files than viewport captures.
  • Stable selectors and assertions reduce flaky visual artifacts more effectively than fixed sleeps.
  • Failure screenshots are most valuable in CI because they preserve the browser state at the point of failure; upload them even when the test job fails.
  • Cypress screenshots are local test artifacts. Your storage, CI retention and artifact-transfer costs depend on your pipeline configuration.

9. Or skip the browser setup

If you need a screenshot of a URL outside a Cypress test, ScreenshotNeo provides a single GET request that returns PNG, JPEG, WebP or PDF. The API accepts the URL directly, and the ScreenshotNeo docs list all options.

cURL

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

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://cypress.io"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://cypress.io'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', buffer);

ScreenshotNeo removes cookie banners, newsletter popups and chat widgets before the shot. Bot checks, blank pages and failed loads are never billed, and response headers identify the page verdict and whether the request was billed. Its MCP server lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.

10. FAQ

Does Cypress take screenshots automatically?

Yes, on failed tests during cypress run when screenshotOnRunFailure is enabled. It does not automatically save one for every failure in cypress open.

What is the command for a manual screenshot?

Use cy.screenshot(), optionally with a filename and capture options.

Where are Cypress screenshots saved?

By default, in cypress/screenshots. Set screenshotsFolder to change it.

Why did Cypress delete my previous screenshots?

Asset folders are cleared before runs by default. Set trashAssetsBeforeRuns: false when previous contents must remain.

Can I capture only part of the page?

Yes. The screenshot API supports clipping and other capture options; consult the versioned API reference for the exact option shape.