ScreenshotNeo

BlogHow-to

How to Run Cypress Tests in Continuous Integration

Run Cypress tests in CI with reliable app startup, a complete GitHub Actions workflow, and guidance for secrets, Docker, parallel jobs, and troubleshooting.

By the ScreenshotNeo team4 October 202610 min read

To run Cypress tests in continuous integration (CI), install Cypress as a development dependency, start your application in the CI job, wait until it responds, and run npx cypress run. For GitHub Actions, Cypress’s maintained action can handle dependency installation, a build command, server startup, and test execution. A basic single-machine run does not require Cypress Cloud; its documented parallelization across machines does require a recorded run.

This guide shows a working GitHub Actions setup, then explains direct CLI workflows, other CI providers, recording, parallelization, Docker, configuration, troubleshooting, and cost and reliability tradeoffs. Cypress’s official guides cover providers including GitHub Actions, CircleCI, GitLab CI, Jenkins, and AWS CodeBuild. Cypress CI overview.

1. Install Cypress and run it locally

Add Cypress to the project as a development dependency with its package manager:

# npm
npm install --save-dev cypress

# Yarn
yarn add --dev cypress

# pnpm
pnpm add --save-dev cypress

# Bun
bun add --dev cypress

Commit the package manifest and lockfile so CI installs the same dependency versions as local development. Run Cypress in headless mode with:

npx cypress run

Equivalent commands are yarn cypress run, pnpm exec cypress run, and bunx cypress run. If your project has an npm script, such as "cy:run": "cypress run", use npm run cy:run in CI. The CLI is the same runner regardless of CI provider.

2. Run Cypress in GitHub Actions

The Cypress-maintained cypress-io/github-action can install dependencies, build the app, start it, wait for readiness, and execute tests. Save a workflow such as .github/workflows/cypress.yml:

name: Cypress

on:
  push:
  pull_request:

jobs:
  cypress:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Run Cypress
        uses: cypress-io/github-action@v7
        with:
          build: npm run build
          start: npm start
          wait-on: 'http://127.0.0.1:3000'
          browser: chrome

Replace the build command, start command, and readiness URL with those for your project. If your application is already built or does not need a build step, omit build. If it listens on a different port, update wait-on and set Cypress’s base URL to match. The example uses the documented action major version; verify the current action tag and runner images when adopting it, or pin a specific release tag if your workflow requires tighter version control. Cypress’s GitHub Actions guide.

Why the readiness check matters

Starting a server is asynchronous. A command such as npm start & followed immediately by npx cypress run can launch the tests before the application is accepting requests. Use a readiness check instead of a fixed delay: a delay may waste time when startup is fast and still fail when it is slow. The action’s wait-on input waits for the URL before running Cypress.

Choose a browser

Set the action’s browser input to a browser available in the selected runner or container, for example chrome, firefox, or edge. Cypress documents browser availability by GitHub-hosted runner operating system; those images and installed versions can change. Check the current runner image documentation before depending on a particular browser. For consistent browser versions, use a controlled Docker image as described below.

3. Run Cypress with direct CLI steps

If you prefer to manage installation and server orchestration yourself, install dependencies, build the app, start it, wait for it, then invoke Cypress. One common approach uses concurrently and wait-on:

npm install --save-dev cypress concurrently wait-on

Add a script to package.json and adjust the app commands and URL for your project:

{
  "scripts": {
    "ci:e2e": "concurrently -k -s first \"npm:start\" \"wait-on http://127.0.0.1:3000 && cypress run\"",
    "start": "your-app-start-command"
  }
}

Then run:

npm run ci:e2e

Replace your-app-start-command with the application’s actual command. The -k option stops the other process when one command exits, so the server does not keep the CI job alive after Cypress finishes. Check the installed concurrently version’s CLI syntax if you change its options.

Alternatively, let your CI provider start the app as a background service and add a provider-specific readiness check before npx cypress run. The sequence is the same across providers, even though YAML syntax and service orchestration differ.

4. Configure the base URL and CI environment

Tests often use a base URL so test files can call cy.visit('/') instead of repeating a full address. Configure it in Cypress or through the CI environment. Cypress configuration values can generally be overridden with CYPRESS_-prefixed environment variables; for example:

# In a CI workflow environment block
CYPRESS_BASE_URL: http://127.0.0.1:3000

Other documented examples include CYPRESS_REPORTER and environment overrides for timeout and viewport settings. Keep machine-specific values in the CI environment rather than assuming a local hostname or port. Make sure the URL passed to the readiness check and the configured Cypress base URL point to the same running application.

5. Record results in Cypress Cloud (optional)

A normal cypress run can run without Cypress Cloud. Cloud recording is optional for ordinary single-machine CI, and is needed for Cypress’s documented distribution of specs across multiple CI machines. Recording also provides a Cloud run report and run context, which can help with debugging.

Configure the project for Cypress Cloud, create a record key, and store that key in your CI provider’s secret store. Pass it to the process as CYPRESS_RECORD_KEY, then run with --record:

# Example shell invocation after the CI secret is exposed as an environment variable
npx cypress run --record

For the GitHub Action, provide the secret through the job or step environment:

- name: Run Cypress
  uses: cypress-io/github-action@v7
  env:
    CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

Do not commit the key into the workflow or expose it in logs. Cypress documents the record key as an operating-system environment variable; it is not read from cypress.env.json or the Cypress configuration env block. See the Cypress CLI reference for recording options.

6. Parallelize specs across CI machines

Cypress’s documented cross-machine parallelization requires a recorded run. Configure multiple CI workers to join the same recorded run, and Cypress Cloud distributes spec files among those machines. The exact matrix syntax depends on your CI provider; Cypress’s GitHub Actions guide demonstrates separating install and build work from matrix workers, preserving the build artifact, and having each worker record and parallelize.

Before adding workers, confirm that:

  • Each worker runs the same commit and compatible Cypress configuration.
  • Workers use the same built application artifact when the tests depend on a build.
  • The record key is available as a protected CI secret.
  • Workers use consistent Node.js, Cypress, and browser versions when version differences could affect results.

More workers can reduce elapsed time, but they use more CI capacity and require a compatible shared recorded run. Treat worker count as a capacity and cost decision; documentation examples are configurations, not guaranteed speedups. See Cypress Cloud parallelization documentation.

7. Use Docker for a controlled environment

Cypress publishes Linux Docker images with Cypress and browser dependencies. A container can make the Node.js and browser environment more consistent when hosted runner images change. Select an image tag that fits the project’s Node.js and browser needs, and verify the published tags and versions when implementing the workflow.

On GitHub Actions, jobs that specify a container image must use a Linux runner. Cypress’s GitHub Actions documentation also calls out a non-root user setting for Firefox in its example. Confirm the image’s user and browser requirements before copying a container configuration. A container adds image maintenance to the workflow, so compare that upkeep with using the provider’s standard runner.

8. Choose a CI setup

Choice Useful when Tradeoff
Provider runner and maintained Cypress action You use GitHub Actions and want installation, app startup, readiness, and test execution coordinated for you. Less setup to own; action and hosted runner versions still change.
Provider runner and direct CLI You need to control each install, build, service, and test step. More workflow setup and process cleanup are your responsibility.
Cypress Docker image You want a controlled Linux environment with a selected browser and Cypress setup. You must select and maintain compatible image versions.
Serial tests on one machine You want the simplest CI run or do not need cross-machine distribution. All specs run on one worker; no Cloud recording is required for this basic setup.
Cloud-recorded parallel workers Elapsed time justifies additional CI workers and Cloud orchestration. Requires recording, consistent worker inputs, and additional CI capacity.

These are setup tradeoffs, not benchmark claims. Choose based on how much workflow orchestration you want to maintain, browser consistency needs, and available CI capacity.

9. Troubleshooting common CI failures

Symptom Likely cause Fix
cy.visit() cannot reach the app, connection refused, or tests start too early The server process has started but is not ready, or Cypress points at a different host or port. Add a readiness check such as wait-on; make its URL match the app’s listen address and Cypress base URL.
CI exits while the server is still running, or the job hangs after tests The background server process was not coordinated with the test command or shut down afterward. Use the action’s start and wait-on options, or use a process manager that terminates the server when Cypress exits.
Cypress is not found The dependency was not installed, the wrong package manager command ran, or dependencies were installed in a different directory. Install from the committed lockfile in the project directory and invoke Cypress through the package manager, such as npx cypress run.
Browser launch fails in a container The image lacks the required browser dependencies, the chosen browser is unavailable, or the container user does not meet browser requirements. Choose a compatible Cypress image and browser; check the image’s user requirements, including the documented Firefox non-root consideration.
Parallel mode fails or workers do not share specs The run is not recorded, the record key is missing, or workers are not joining the same recorded run. Configure Cypress Cloud recording, expose CYPRESS_RECORD_KEY as a CI secret, and enable parallelization for each worker.
Parallel jobs behave differently Workers use different build artifacts, browser versions, environment values, or commits. Build once and distribute the same artifact; align worker images, versions, configuration, and commit.
The workflow cannot read the record key The key was placed in Cypress’s config env or a file rather than the process environment, or the CI secret is unavailable to that event. Set CYPRESS_RECORD_KEY as an operating-system environment variable from a CI secret, and check the provider’s secret availability for the triggering event.
Workflow stops after a runner or action update A hosted image, browser, or action version changed. Check current provider and Cypress version guidance; pin action or container versions when the project needs tighter control.

10. Performance, reliability, and cost

Performance

First remove avoidable waiting: use a readiness check instead of a long fixed sleep, and avoid rebuilding the same artifact on every parallel worker when your CI design can build once and share it. Parallelization can reduce elapsed time by distributing specs, but the result depends on the suite and worker capacity; no fixed speedup follows from a worker count.

Reliability

Use a lockfile-based install and control Node.js, Cypress, browser, and container versions where consistency matters. Wait for the application’s actual readiness endpoint, ensure parallel workers use the same build and configuration, and keep secrets in the CI secret store. Provider runner images and browser availability can change, so review those details when a workflow begins failing after an infrastructure update.

Cost

CI usage and any Cloud plan are separate considerations. A single-machine CLI run does not require Cypress Cloud recording; parallelized Cloud runs do. Additional workers consume additional CI capacity, so compare the saved elapsed time with the provider’s worker usage and the team’s Cloud requirements. The research sources do not establish universal prices or performance savings; consult the relevant providers for current terms.

Or skip the browser setup

If your CI job needs a screenshot artifact from a page, ScreenshotNeo can capture it with one GET request instead of installing and managing a browser for that capture. 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 banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000. This API captures website screenshots; it does not run or replace Cypress test suites.

Sign up for 1,000 free screenshots a month, with no card required.

Frequently asked questions

Can Cypress run in any CI provider?

Cypress documents support and setup guidance for providers including GitHub Actions, CircleCI, GitLab CI, Jenkins, and AWS CodeBuild. The commands remain the Cypress CLI; the workflow syntax and server orchestration vary by provider.

Do I need Cypress Cloud just to run tests in CI?

No. You can run a basic single-machine job with cypress run. Cloud recording is needed for Cypress’s documented parallelization across multiple machines.

Can I use a different browser in CI?

Yes, if the selected runner or container provides that browser and Cypress supports the configuration. Check the current runner or image documentation because available browser versions can change.

Should I use a fixed sleep before Cypress starts?

A readiness check is more dependable. It waits for the application to respond and avoids relying on a guessed startup duration.

Sources