How to upload Cypress screenshots to GitHub Actions artifacts
Capture Cypress failure screenshots in CI and upload them as GitHub Actions artifacts, with workflow examples, configuration tips, and fixes for common issues.
To upload Cypress screenshots to GitHub Actions, run Cypress and then use actions/upload-artifact to upload the screenshots directory. Cypress captures screenshots automatically when tests fail during cypress run; the default folder is cypress/screenshots.
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cypress run
uses: cypress-io/github-action@v7
- name: Upload Cypress screenshots
uses: actions/upload-artifact@v7
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore
After the workflow runs, open the GitHub Actions run and download the cypress-screenshots artifact. The example uses the current action versions reflected in the cited documentation; check the action documentation for compatibility, especially if you use GitHub Enterprise Server.
1. How the upload works
The Cypress GitHub Action runs your tests. When a test fails in cypress run, Cypress saves a screenshot by default. The upload step packages files from the configured screenshots folder as a workflow artifact. Uploading an empty folder can happen on a passing run, so if-no-files-found: ignore avoids an unnecessary warning.
Artifacts are attached to the workflow run, so you can download them later for debugging or share them with someone who can access that run. Deleting the workflow run also deletes its artifacts.
2. Set up the workflow
Use a complete workflow file
Save a workflow such as .github/workflows/cypress.yml. Adapt the trigger and dependency setup to your project. This example assumes the Cypress GitHub Action can install dependencies and invoke Cypress in the repository.
name: Cypress
on:
push:
pull_request:
jobs:
cypress:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cypress run
uses: cypress-io/github-action@v7
- name: Upload Cypress screenshots
uses: actions/upload-artifact@v7
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore
Keep the upload step after the Cypress step. If your workflow already checks out code, installs dependencies, or configures the Cypress action, retain those steps and add the upload step afterward.
Upload only when the job fails
To avoid running the upload on successful jobs, add if: failure() to the upload step:
- name: Upload Cypress screenshots after failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore
GitHub Actions normally skips later steps after a failure. The explicit condition lets this step run when an earlier step failed. Consider the workflow context: failure() applies to the job’s preceding steps, so a failure in setup can also trigger the upload. The empty-file behavior still matters if the failure happened before Cypress created screenshots.
3. Configure Cypress’s screenshot output
Cypress’s default screenshot folder is cypress/screenshots. If your project sets screenshotsFolder, make the artifact path match it.
const { defineConfig } = require('cypress')
module.exports = defineConfig({
screenshotsFolder: 'artifacts/cypress/screenshots',
})
With that setting, use path: artifacts/cypress/screenshots in the upload step. A path mismatch is the most common reason an artifact contains no screenshots.
Cypress captures screenshots on test failure during cypress run by default. You can disable that behavior with screenshotOnRunFailure: false, but then there may be no failure screenshots to upload.
const { defineConfig } = require('cypress')
module.exports = defineConfig({
screenshotOnRunFailure: true,
})
Cypress clears the screenshots folder before a run by default. If you intentionally need to preserve files that were already in that folder, set trashAssetsBeforeRuns: false. In most CI jobs, a clean directory helps ensure the artifact contains screenshots from the current run rather than leftovers.
4. Choose what to upload and how long to keep it
| Choice | Configuration | When it helps |
|---|---|---|
| Upload every run | Leave the upload step unconditional; use if-no-files-found: ignore |
Useful when screenshots can be created by custom capture calls even on passing runs. |
| Upload after a failure | Add if: failure() |
Reduces empty or unnecessary artifacts in workflows where screenshots are primarily for debugging failures. |
| Empty folder behavior | ignore, warn, or error |
Use ignore for expected passing runs; use error only when an artifact is required for correctness. |
| Artifact lifetime | Set retention-days |
Match the time needed for debugging while respecting repository or organization policy. |
For example, to request a 14-day retention period:
- name: Upload Cypress screenshots
uses: actions/upload-artifact@v7
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore
retention-days: 14
GitHub documents a 90-day default artifact and log retention period. Repository, organization, or enterprise settings can impose different limits; individual artifacts can request a retention period within those applicable settings. Verify your repository policy before relying on a specific expiry date.
5. Add Cypress videos separately if needed
Cypress video recording is disabled by default unless configured. If you enable it, upload videos as a separate artifact so their size and retention are managed independently.
- name: Upload Cypress videos
if: always()
uses: actions/upload-artifact@v7
with:
name: cypress-videos
path: cypress/videos
if-no-files-found: ignore
always() allows the upload step to run regardless of earlier step outcomes. Use it deliberately: it can also execute after cancellation or other unsuccessful paths, and an empty-folder policy should reflect that. Check the Cypress action documentation for its separate video artifact example and current guidance.
6. Find and download the artifact
- Open the repository’s Actions tab.
- Select the workflow run for the commit or pull request.
- Find Artifacts on the run summary page.
- Download
cypress-screenshotsand inspect the extracted files.
Artifact access follows GitHub’s access controls for the repository and workflow run. Deleting the run removes its associated artifacts.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No artifact appears | The upload step did not run, or the configured path does not exist. | Confirm the upload step follows Cypress and check that the workflow path matches screenshotsFolder. |
| Artifact exists but is empty or missing expected files | Tests passed, screenshot-on-failure is disabled, or screenshots were written elsewhere. | Check Cypress’s failure behavior, screenshotOnRunFailure, and the configured output folder. Use a custom screenshot call if you need captures on passing tests. |
| Upload warns that no files were found | No test failure created screenshots, or Cypress did not reach the test run. | Set if-no-files-found: ignore when an empty result is normal. Investigate setup failures if a screenshot was expected. |
| Old files are unexpectedly removed | Cypress cleans the screenshot folder before the run. | Set trashAssetsBeforeRuns: false only if preserving existing contents is intentional; otherwise rely on the clean per-run output. |
| Old screenshots appear in the artifact | Files may have been copied into the output directory during the run, or cleanup was disabled. | Use a dedicated output directory and inspect whether trashAssetsBeforeRuns is false. |
| Upload action fails on GitHub Enterprise Server | GitHub documents that actions/upload-artifact v4 and later are not currently supported on GHES. |
Follow the upload-artifact documentation’s GHES version guidance; do not assume the latest major version works on GHES. |
| Artifact expires sooner than expected | Repository or organization retention policy can constrain the requested lifetime. | Review Actions artifact and log retention settings and the artifact’s retention configuration. |
8. Performance, reliability, and cost
Artifact upload adds work proportional to the files being uploaded. Failure-only screenshots usually keep the artifact focused; enabling videos or uploading full run output can increase transfer time and storage use. Keep screenshots in their own artifact when you want a short retention period or a smaller download.
For reliability, use the actual configured Cypress output path, make the no-files-found behavior intentional, and avoid depending on artifacts beyond the configured retention window. Uploading an artifact does not change whether Cypress tests pass or fail; it preserves files produced by the run.
GitHub’s artifact usage is subject to the plan and repository storage policies applicable to your account. Set retention to the shortest period that still supports your debugging workflow and confirm current quotas and policy in GitHub settings.
9. Or skip the browser setup
If you need screenshots of live web pages outside Cypress, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. For this Cypress artifact workflow, Cypress still captures your test browser; ScreenshotNeo is an option for separate page captures.
Here is a runnable cURL example. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan.
Sign up for 1,000 free screenshots a month with no card.
10. FAQ
Does Cypress take screenshots automatically in GitHub Actions?
Yes, when running cypress run, Cypress captures screenshots for failed tests by default. The workflow still needs an upload step to preserve them as artifacts.
Can I upload screenshots when tests pass?
Yes, if your tests or support code explicitly create screenshots on passing runs. The default failure capture alone will not produce them on a fully passing run.
How long are GitHub Actions artifacts available?
GitHub documents 90 days as the default, but repository and higher-level settings may change the effective retention. An artifact’s requested retention can also be configured.
Can I upload screenshots and videos together?
Yes, by using a path that includes both directories, but separate artifacts make downloads and retention choices easier to manage. Cypress video capture must first be enabled.
Primary references
- Cypress screenshots and videos — capture behavior, folder cleanup, and video configuration.
- Cypress configuration reference — screenshot folder and failure-capture settings.
- Cypress GitHub Action — workflow examples for uploading screenshots and videos.
- actions/upload-artifact documentation — inputs, no-file behavior, and GHES compatibility.
- GitHub: storing workflow data as artifacts — artifact retention and usage.
- GitHub: removing workflow artifacts — artifact deletion with workflow runs.


