Cypress Screenshot Folder: Default Path, Configuration, Cleanup, and CI
Cypress saves screenshots in cypress/screenshots by default. Learn how to change the folder, preserve artifacts, name files, and debug CI captures.
Direct answer: Cypress saves screenshots under cypress/screenshots by default. Set screenshotsFolder in your Cypress configuration to use another directory. Call cy.screenshot() for manual captures in both cypress open and cypress run. Cypress also captures failed tests automatically during cypress run. Before a run, Cypress clears the screenshot folder by default because trashAssetsBeforeRuns defaults to true.
The documented behavior is covered in the Cypress configuration reference, the cy.screenshot() API, and the screenshots and videos guide.
Default folder and what Cypress puts there
The default root is:
cypress/screenshots
That folder receives screenshots created by cy.screenshot() and automatic failure screenshots from cypress run. The root is configurable, while the generated path below it depends on the specs and test names that ran.
Change the screenshot folder
Set screenshotsFolder in your Cypress configuration file. Cypress supports JavaScript, TypeScript and other configuration formats documented for your installed version.
JavaScript configuration
const { defineConfig } = require('cypress');
module.exports = defineConfig({
screenshotsFolder: 'artifacts/cypress/screenshots',
e2e: {
baseUrl: 'http://localhost:3000',
setupNodeEvents(on, config) {
return config;
}
}
});
TypeScript configuration
import { defineConfig } from 'cypress';
export default defineConfig({
screenshotsFolder: 'artifacts/cypress/screenshots',
e2e: {
baseUrl: 'http://localhost:3000'
}
});
Use a path relative to the project root when you want the artifacts to stay with the checkout. For a machine-specific location, use the path format supported by your operating system and Cypress version.
Take a screenshot manually
Manual screenshots work in both interactive and headless modes.
describe('checkout', () => {
it('captures the confirmation page', () => {
cy.visit('/checkout');
cy.get('[data-cy=pay-button]').click();
cy.get('[data-cy=confirmation]').should('be.visible');
cy.screenshot('checkout/confirmation');
});
});
The name replaces the default suite and test name. Names can include subdirectories, so checkout/confirmation creates a nested path under the configured screenshot folder. If Cypress encounters the same filename more than once, it adds a numbered suffix unless you pass overwrite: true in the screenshot options.
Capture an element instead of the viewport
cy.get('[data-cy=invoice]').screenshot('invoices/latest');
Element screenshots are useful for focused visual evidence. Ensure the element is visible and stable before capturing it.
Use screenshot options
cy.screenshot('dashboard', {
blackout: ['[data-cy=customer-email]', '.private-value'],
overwrite: true,
capture: 'viewport',
scale: false,
disableTimersAndAnimations: true
});
Option names and supported values can vary by Cypress release. Check the API reference for the version installed in your project.
Automatic screenshots after failures
When you run Cypress with cypress run, Cypress automatically captures a screenshot after a test fails. This automatic behavior does not occur in cypress open. Disable it with screenshotOnRunFailure: false:
const { defineConfig } = require('cypress');
module.exports = defineConfig({
screenshotOnRunFailure: false
});
Failure screenshots use the generated test name with (failed) appended. Manual screenshots continue to work when automatic failure capture is disabled.
Why screenshot paths can look different between runs
Cypress builds a path beneath screenshotsFolder from the spec path and test name. It removes the longest common ancestor shared by the specs included in that run. Consequently, the same test can appear at a different relative depth when you run one spec versus a group of specs. Treat the configured folder as the stable root and avoid scripts that depend on one fixed nested path.
A typical layout might look like:
cypress/screenshots/
checkout.cy.js/
checkout -- confirmation.png
account.cy.js/
profile -- saves changes.png
The exact names and nesting depend on your spec filenames, suite names, test names and the set of specs selected.
Prevent Cypress from deleting old screenshots
Before cypress run, Cypress clears the contents of the screenshots, videos and downloads folders by default. This is controlled by trashAssetsBeforeRuns.
const { defineConfig } = require('cypress');
module.exports = defineConfig({
trashAssetsBeforeRuns: false
});
With the setting disabled, previous files remain and new captures are added. Plan your naming and retention policy so stale artifacts do not get mistaken for the current run. Cleanup behavior differs by operating system: Linux removes contents directly, while macOS and Windows move items to the system trash or Recycle Bin.
Interactive mode versus run mode
| Behavior | cypress open |
cypress run |
|---|---|---|
Manual cy.screenshot() |
Available | Available |
| Automatic screenshot after failure | No | Yes, by default |
| Clears asset folders before execution | No | Yes, by default |
Use open mode while developing and inspecting a specific state. Use run mode in CI when you need automatic failure evidence and reproducible artifact collection.
Keep screenshots out of source control
Cypress describes screenshots as generated artifacts. Unless your review process intentionally versions visual baselines, add the folder to .gitignore:
cypress/screenshots/
cypress/videos/
cypress/downloads/
If your team stores evidence centrally, upload the folder as a CI artifact after the run. Cypress also documents Cypress Cloud as an optional way to store screenshots and videos with test results.
CI workflow checklist
- Set a deterministic
screenshotsFolder, such asartifacts/cypress/screenshots. - Run
cypress runso failed tests produce automatic screenshots. - Upload the configured folder after the test command, even when tests fail.
- Choose
trashAssetsBeforeRuns: falseonly when preserving prior runs is intentional. - Include the commit, browser and spec selection in your CI artifact metadata.
- Remove or protect screenshots containing customer data, tokens or personal information.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| No screenshot after a failed test | The test ran in cypress open, or automatic capture was disabled. |
Use cypress run and check that screenshotOnRunFailure is not false. |
| Old files disappeared | trashAssetsBeforeRuns is true (the default). |
Set it to false when retention is required, or upload artifacts before the next run. |
| Script cannot find a screenshot | The generated subpath changed after running a different set of specs. | Search below the configured root, or use an explicit screenshot name and stable artifact discovery. |
| Duplicate files have suffixes | The same name was captured more than once. | Use unique names or pass overwrite: true when replacement is safe. |
| Screenshot is blank or incomplete | The page or element was captured before it became stable. | Wait for a visible assertion, network completion or the required application state before calling cy.screenshot(). |
| Expected folder is empty in CI | The config file was not loaded, the working directory differs, or the artifact upload path is wrong. | Print the resolved project directory, confirm the active Cypress config, and upload the exact configured folder. |
| Sensitive data appears in an image | The screenshot includes private fields or authenticated content. | Use screenshot blackout options where supported, mask data in the test fixture, restrict artifact access and apply retention limits. |
Performance and reliability considerations
- Capture only what you need. Element or viewport screenshots generally create smaller artifacts than full-page captures.
- Wait on application state. Assertions such as
should('be.visible')reduce race conditions caused by capturing during transitions. - Control artifact volume. A screenshot on every step increases disk use and CI upload time. Capture checkpoints and failures that help diagnosis.
- Use stable names. Explicit names make downstream uploads and retention jobs easier, while unique names prevent accidental overwrites.
- Keep cleanup intentional. The default pre-run cleanup prevents stale evidence but means an upload step must run before the next invocation.
- Account for path variability. Do not hard-code a spec subdirectory when your CI matrix runs different spec subsets.
Or skip the browser setup
If you need a screenshot of a URL rather than a Cypress test artifact, ScreenshotNeo provides a website screenshot API. It removes cookie and consent banners, newsletter popups and chat widgets before capture; bot checks, blank pages and failed loads are not billed. Its response identifies the page verdict and billing status with X-Page-Verdict and X-Billed headers. ScreenshotNeo also provides an MCP server so Claude, Cursor and other MCP clients can call take_screenshot, get_page_info and capture_pdf.
See the ScreenshotNeo API docs for request options. The basic call returns an image response:
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
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://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo supports full-page captures, CSS selector element captures, dark mode, device presets, custom viewports, retina scale, PDFs, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous jobs, bulk capture and usage reporting. Caching lets you choose a TTL; cache hits are not billed. Plans include 1,000 free shots each month with no card, then Starter at $5 for 3,000 shots; every feature is available on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
FAQ
Does Cypress create the screenshot folder automatically?
Cypress writes screenshots beneath the configured folder and preserves the folder itself when cleaning assets. The default root is cypress/screenshots.
Can I take screenshots while using Cypress open?
Yes. Manual cy.screenshot() works in both open and run modes. Automatic failure screenshots are a run-mode feature.
Why did my screenshot move after changing the spec command?
Cypress removes the longest common ancestor shared by the specs in that run, so the relative path beneath the root can change.
Should generated screenshots be committed?
Usually no. Treat them as build artifacts unless your project deliberately versions visual evidence or baselines.
How do I preserve screenshots from several CI runs?
Upload each run’s configured screenshot folder with a run-specific artifact name. Set trashAssetsBeforeRuns: false only when local retention is part of your workflow.


