How to Run Cypress Tests with Jenkins
Build a reliable Jenkins pipeline for Cypress: install locked dependencies, wait for your app, run tests, and retain results and screenshots.
Run Cypress in Jenkins by checking out your project, installing its locked dependencies with npm ci, starting the application, waiting until it is ready, and then running npx cypress run. Save Cypress screenshots and videos as Jenkins build artifacts so failures can be investigated. Start with one worker; add Cypress Cloud recording and parallel workers only after the serial pipeline is reliable.
1. Prepare the Jenkins agent
The agent needs a supported Node.js version, the project’s package manager, and the operating system libraries required by the browser Cypress launches. Cypress can run on many CI virtual machines without extra dependencies, but Linux agents may lack libraries or an X11 environment. Check Cypress’s current CI guidance and Linux prerequisites for the installed version.
For a repeatable environment, use a pinned Cypress Docker image. The image families serve different purposes: cypress/base includes a Linux base and Cypress prerequisites; cypress/browsers adds browsers; cypress/included includes a fixed Cypress version; and cypress/factory supports custom combinations. Choose a tag that matches the intended Node, Cypress, and browser versions, and use the same image on all parallel agents. Image contents and available tags change, so confirm the current image documentation before selecting one.
Jenkins installations provision agents in different ways. The pipeline below uses a generic agent and shell steps; it does not assume a particular Docker or Node plugin. Adapt the agent declaration and checkout configuration to your Jenkins setup.
2. Add a Jenkins pipeline
This example assumes a Node application with a committed package-lock.json, an npm script named start, and a health endpoint at /health on port 3000. Change the startup command and readiness URL to match your app. It uses curl to wait for readiness, avoiding a race between server startup and Cypress.
pipeline {
agent any
environment {
CI = 'true'
CYPRESS_CACHE_FOLDER = "${WORKSPACE}/.cache/Cypress"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install dependencies') {
steps {
sh 'node --version'
sh 'npm --version'
sh 'npm ci'
}
}
stage('Start application') {
steps {
// Replace this with the command that starts your app.
sh 'npm start > app.log 2>&1 &'
sh '''
for attempt in $(seq 1 60); do
if curl --fail --silent http://127.0.0.1:3000/health >/dev/null; then
echo "Application is ready"
exit 0
fi
sleep 2
done
echo "Application did not become ready; recent server log:"
tail -100 app.log || true
exit 1
'''
}
}
stage('Cypress') {
steps {
sh 'npx cypress run'
}
}
}
post {
always {
archiveArtifacts artifacts: 'cypress/screenshots/**/*,cypress/videos/**/*,app.log',
allowEmptyArchive: true
}
}
}
The shell command uses a triple-quoted Jenkins string so the shell receives the background operator. In a Jenkinsfile, do not put shell comments inside a sh command unless they are part of the shell script; the explanatory comment above is for the example reader. If Jenkins reports a syntax error around the multiline command, check that the Jenkinsfile’s quoting matches the version of Groovy and pipeline syntax supported by your installation.
Cypress’s CI overview describes the basic setup as installing dependencies and running Cypress. For a Node project, npm ci installs from the lockfile, while npx cypress run runs the suite headlessly. Keep the lockfile committed and run the same commands locally when diagnosing CI-only failures.
3. Wait for the application correctly
Starting the app in the background and immediately launching Cypress is race-prone: tests may start before the server is listening. A fixed delay can still be too short on a busy agent and wastes time when startup is fast. Poll a health endpoint, readiness URL, or other signal that represents a usable app. The example retries for up to two minutes, then fails with a useful log excerpt.
If the application needs a database or other services, start those dependencies before the readiness check, and make the check verify the app can serve the pages the tests need. Ensure the app process remains alive for the duration of the test run. The exact process-management approach depends on how the app and agent are launched.
4. Choose the browser and retain test output
Without a browser flag, Cypress uses its default browser behavior for the installed environment. To choose a browser explicitly, install it on the agent or use an image that includes it, then specify its name:
npx cypress run --browser chrome
Cypress documents Chrome-family browsers and Firefox; WebKit support is experimental. Confirm the browser is available and supported by the version of Cypress in the project. Pin the image or agent browser versions when reproducibility matters.
Configure Cypress screenshots, videos, and any reporter output according to the project’s needs, then archive those paths in Jenkins. The pipeline’s post { always { ... } } block attempts to archive screenshots, videos, and the application log whether tests pass or fail. allowEmptyArchive prevents a missing optional artifact from masking the test result. Add reporter output paths if the project writes JUnit XML or another report format.
5. Cache for faster repeat builds
Cypress recommends caching its global binary cache (typically under ~/.cache on Linux) and the package manager’s cache, such as ~/.npm for npm. Avoid reusing node_modules across builds: it can become stale or inconsistent with the lockfile and agent environment. Jenkins cache mechanisms vary by installation, so configure the cache directories using the facilities available to your agents.
Cache keys should account for the operating system and relevant dependency or Cypress version inputs. When changing Node, browser, or Cypress versions, invalidate or separate the corresponding cache to avoid carrying incompatible binaries forward.
6. Optional: parallelize with Cypress Cloud
First establish a passing serial run. Cypress Cloud parallelization distributes whole spec files among workers, so the suite needs multiple spec files to make useful use of multiple agents. Parallel execution requires recording to Cypress Cloud; confirm the organization’s Cloud project settings and current terms before enabling it.
Provision multiple Jenkins workers and run a command like this on each worker:
npx cypress run --record --parallel --group "jenkins" --ci-build-id "$BUILD_TAG"
Use the same shared build identifier on all workers participating in one CI build. Cypress identifies Jenkins BUILD_NUMBER as a known CI build identifier; BUILD_TAG is another example that can be supplied with --ci-build-id when a distinct shared identifier is useful. Keep the recorded run settings, project configuration, and build ID consistent across workers. Consult the Cypress parallelization guide for the current setup details.
Parallelization adds agent capacity and Cypress Cloud recording requirements. It does not guarantee a particular speedup: actual wall time depends on spec count and duration, worker availability, and setup overhead. Compare total build time and resource use before increasing worker count.
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Cypress starts before the app responds | The pipeline starts Cypress immediately after launching the server, or readiness checks the wrong URL. | Poll a health or readiness endpoint and fail with the server log if the retry limit expires. |
| Cypress fails to launch on Linux | Missing system libraries, browser dependencies, or Xvfb support. | Read the startup error, install the documented Linux prerequisites, or use a suitable pinned Cypress image. |
npm ci fails |
The lockfile is missing, out of sync with package.json, or created by an incompatible setup. |
Commit a consistent lockfile and use the intended Node/npm version. Reproduce with npm ci locally. |
| Different agents produce different results | Agents use different Node, browser, Cypress, or operating system versions. | Pin the Docker image or agent toolchain and use identical settings across workers. |
| Parallel workers show separate or incomplete runs | Recording is disabled, the workers use different build IDs, or project settings differ. | Enable recording, provide the same --ci-build-id to all workers, and verify shared project configuration. |
| Cached build behaves inconsistently | Reused dependencies or Cypress binaries do not match the current environment. | Do not cache node_modules; cache the npm and Cypress binary caches, and invalidate them after relevant version changes. |
| Artifacts are missing after a failure | The archive path does not match the configured Cypress output path, or the test failed before creating files. | Check Cypress output configuration and Jenkins workspace paths; archive logs and reports too when available. |
8. Performance, reliability, and cost considerations
- Repeatability: use a committed lockfile and pin Node, Cypress, and browser versions. Keep parallel workers on the same environment.
- Build time: install with
npm ci, cache package-manager and Cypress binary caches, and avoid unnecessary fixed sleeps. Add workers only when the suite has enough spec files and CI capacity. - Reliability: wait on application readiness, capture logs, and retain screenshots, videos, and reports for failures. Make the health check reflect actual app readiness.
- Cost: Jenkins compute use depends on the agent provider and worker duration. Parallel workers can reduce elapsed time while using more concurrent capacity; Cypress Cloud recording has separate service terms that should be checked for your organization.
Or skip the browser setup
For a screenshot of a deployed page, ScreenshotNeo provides a screenshot API and MCP server; it does not replace Cypress interaction or assertion tests. Make one request with a URL, using an API key from your account. 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
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers report the page verdict and billing status.
- An MCP server lets AI agents use screenshot, page-info, and PDF-capture tools.
- The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Can Jenkins run Cypress headlessly?
Yes. npx cypress run runs tests from the command line in CI. Ensure the agent has the required browser dependencies.
Do I need Cypress Cloud to run Cypress in Jenkins?
No for a serial run. The Cloud recording requirement applies to Cypress’s documented parallel distribution across workers.
Can a screenshot API replace Jenkins browser tests?
No. A screenshot API captures a page image; Cypress tests can interact with the application and assert behavior. Use each for its intended task.


