How to Change the Screenshot Path in Cypress Configuration
Set Cypress’s screenshotsFolder option to choose where manual and test failure screenshots are saved. Learn how nested paths, cleanup, and custom relocation work.
Set screenshotsFolder in your Cypress configuration file to change the base directory for screenshots. It applies to images created with cy.screenshot() and automatic failure screenshots during cypress run. Cypress’s documented default is cypress/screenshots. Cypress configuration reference
1. Change the base screenshot directory
Edit the Cypress configuration file at your project root. For a CommonJS JavaScript configuration, set the option at the top level:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
screenshotsFolder: 'artifacts/cypress-shots',
})
For an ES module or TypeScript configuration, use the same option in the exported configuration object:
import { defineConfig } from 'cypress'
export default defineConfig({
screenshotsFolder: 'artifacts/cypress-shots',
})
Use the path form appropriate to the operating system and project conventions. A relative path such as artifacts/cypress-shots is resolved as a project path. Cypress creates output as needed when it writes screenshots. This is a base directory: the final image can be placed in additional directories based on the spec file and screenshot name.
Make a manual screenshot
Once the configuration is saved, a normal cy.screenshot() writes below the configured base folder:
describe('account page', () => {
it('captures the account page', () => {
cy.visit('/account')
cy.screenshot('account-page')
})
})
With the example configuration, the output is under artifacts/cypress-shots. The precise nested path depends on the spec path and run context. The screenshot name can add more path segments, as shown below.
2. Understand the final file path
screenshotsFolder selects the root, not always the complete filename path. Cypress adds a path based on the spec file, and a slash-separated name passed to cy.screenshot() creates nested directories beneath that spec-related path. Cypress removes the shared ancestor among specs when forming generated asset paths, so a spec’s nested path can change when the set of specs included in a run changes. cy.screenshot() documentation
| Setting or call | What it controls | Example result shape |
|---|---|---|
screenshotsFolder |
Base directory for screenshots | artifacts/cypress-shots/… |
cy.screenshot('account-page') |
Screenshot name beneath the spec-related path | …/account-page.png |
cy.screenshot('actions/login') |
Name with nested directories | …/actions/login.png |
| Automatic failure capture | Screenshot Cypress takes for a failed test in cypress run |
Saved below the same configured base |
For example, a spec named login.cy.js and a manual screenshot named actions/login can yield a path shaped like artifacts/cypress-shots/login.cy.js/actions/login.png. Treat that as an illustrative shape, not a fixed path: Cypress’s shared-ancestor calculation can affect the spec-relative portion.
3. Know what Cypress clears before a run
Before cypress run, Cypress clears the contents of the screenshots folder by default. It preserves the folder itself but removes its files and nested directories. This behavior applies to the configured screenshotsFolder. The clearing occurs for cypress run, not cypress open. Cypress screenshots and videos guide
If existing generated assets must remain, set trashAssetsBeforeRuns: false:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
screenshotsFolder: 'artifacts/cypress-shots',
trashAssetsBeforeRuns: false,
})
This setting affects the contents of Cypress’s downloads, screenshots, and videos folders before a run, not just screenshots. Keep old artifacts only when you have a reason to retain them; otherwise, the default cleanup helps ensure the folder represents the current run.
4. Choose between a base folder and custom relocation
| Approach | Use it when | Where it is configured |
|---|---|---|
screenshotsFolder |
You want a project-wide base output directory | Cypress config |
after:screenshot |
You need custom Node-side handling after each screenshot is written, such as moving a file | setupNodeEvents in Cypress config |
Choose screenshotsFolder for the ordinary directory change. Use after:screenshot when you specifically need post-capture file handling. If the event handler moves the file, return its new absolute path so Cypress is told where the screenshot ended up. The handler runs in Node and cannot call Cypress browser commands such as cy. after:screenshot event documentation
Example: move each screenshot after capture
This JavaScript configuration demonstrates the event shape. It moves captured files to a separate directory and returns the new path. Create the destination directory before moving the file:
const { defineConfig } = require('cypress')
const fs = require('node:fs/promises')
const path = require('node:path')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on) {
on('after:screenshot', async (details) => {
const destinationDir = path.resolve('artifacts/relocated-shots')
await fs.mkdir(destinationDir, { recursive: true })
const destination = path.join(destinationDir, path.basename(details.path))
await fs.rename(details.path, destination)
return { path: destination }
})
},
},
})
In a project that enables both E2E and component testing, register Node events under the testing type that produces the screenshots. The example uses the E2E configuration. Avoid basename collisions if different specs can produce screenshots with the same filename; preserve or recreate a unique relative path when that matters. For cross-device moves, rename may fail if source and destination are on different filesystems; copy the file and then remove the source instead.
5. Troubleshoot screenshot paths
| Symptom | Likely cause | What to do |
|---|---|---|
Images still appear under cypress/screenshots |
The option is missing, misspelled, or placed in the wrong configuration object or file. | Set top-level screenshotsFolder in the config Cypress loads, then restart the Cypress process. |
| The final path has unexpected subfolders | Cypress includes the spec-relative path, and the screenshot name may include slash-separated directories. | Inspect the complete path under the configured base; check both spec location and the argument to cy.screenshot(). |
| A spec’s generated path changes between runs | The common ancestor used across included specs changes the relative asset path. | Do not assume the spec-relative segment is invariant across different spec selections. Find artifacts under the configured base. |
| Old screenshots disappear after a run | trashAssetsBeforeRuns defaults to true and clears folder contents before cypress run. |
Set trashAssetsBeforeRuns: false if retaining prior contents is required. |
| No automatic failure image appears in interactive mode | Cypress does not automatically capture failure screenshots during cypress open. |
Use cypress run for automatic failure captures, or call cy.screenshot() manually. |
| The event handler reports a missing file after moving | The handler moved the file but did not return the updated location, or the returned path is not absolute. | Return { path: absoluteDestination } from after:screenshot. |
The event handler cannot call cy |
after:screenshot runs in Node, outside the browser test context. |
Use Node filesystem APIs in the handler; keep browser interactions in the test. |
6. Performance, reliability, and artifact handling
- Keep output predictable: choose a repository-relative folder such as
artifacts/cypress-shotsso local runs and CI use the same layout. - Account for cleanup: default cleanup gives each
cypress runa fresh artifact directory. Disable it only if retaining earlier artifacts is part of your workflow. - Preserve uniqueness: spec-relative directories and descriptive screenshot names help prevent different tests from overwriting or confusing outputs.
- Keep event handlers simple: filesystem work after every screenshot adds work to the capture path. Move files only if the build or artifact workflow needs it, and return the updated absolute path.
- Plan CI collection around the configured base: configure the CI artifact step to collect the new directory. Cypress configuration changes where files are written; it does not configure your CI provider’s artifact upload.
- Control storage growth: retained screenshots consume workspace or artifact storage. Decide how long prior runs need to remain and apply retention in the artifact system.
7. Or skip the browser setup
If your goal is to capture a website rather than collect Cypress test artifacts, ScreenshotNeo provides a website screenshot API. It is made by Yorker Media. A single GET request can return a screenshot or PDF; see the ScreenshotNeo 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
Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers indicating the page verdict and billing status. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Learn about ScreenshotNeo, then sign up for 1,000 free screenshots a month with no card.
FAQ
Does changing screenshotsFolder also move videos or downloaded files?
No. Cypress has separate configuration options for videos and downloads. screenshotsFolder is for screenshots.
Can I use a TypeScript Cypress config?
Yes. Set screenshotsFolder in the object passed to defineConfig, just as in the JavaScript example.
Does Cypress take failure screenshots in cypress open?
No. Automatic failure screenshots apply to cypress run. In interactive mode, request a screenshot explicitly with cy.screenshot().
Which setting should I use to change where screenshots normally go?
Use screenshotsFolder. Use after:screenshot when you need custom handling of files after capture.


