ScreenshotNeo

BlogGuides

Cypress 14: What’s New and How to Upgrade

Cypress 14 changes cross-origin testing, runtime and platform requirements, and component-testing support. Use this checklist and code to plan your upgrade.

By the ScreenshotNeo team4 October 202610 min read

Cypress 14.0.0 was released on January 16, 2025. The upgrade changes more than the package version: it changes how tests move between origins, raises runtime and platform minimums, and updates component-testing requirements. Start by checking your Node.js version, operating system, browsers, component-testing stack, test code, Cypress configuration, scripts, and CI image. Then update the package and address the changes that apply to your project.

Most important behavior change: Cypress 14 no longer injects document.domain by default. If a test visits one origin and then interacts with another, use cy.origin() for commands on the second origin. For the complete official change list, see the Cypress migration guide and the Cypress changelog.

What changed in Cypress 14

Area Change What to check
Cross-origin tests document.domain is no longer injected by default. Wrap commands for each second origin in cy.origin().
Node.js Node.js 18 or newer is required to install Cypress; Node.js 16 and 21 are no longer supported. Check the Node version used by local installs, CI, and package-manager jobs.
Linux and macOS Linux binaries require glibc 2.28 or newer; macOS 11 (Big Sur) is the minimum. Check runner images, developer machines, and container base images.
Browsers Official support covers the latest three major versions of Chrome, Firefox, and Edge. Check pinned CI browser versions as well as local browsers.
Component testing Webpack 4 and Vite 4 are no longer supported by the respective Cypress dev servers; Angular 18 is the minimum. Check framework, bundler, dev-server, config module format, and mount imports.
Deprecated APIs and scripts Several options, commands, and undocumented backend calls should be removed or updated. Search source, configuration, package scripts, and CI definitions.

These are Cypress 14 requirements. Cypress has had later major releases since 14, so a team upgrading today should follow the official migration guides sequentially and check the requirements for its intended destination version rather than treating Cypress 14 as the current latest release.

Before you upgrade: inventory the project

  1. Record the starting point. Check the Cypress version and package manager in the lockfile and project scripts. Note whether the project runs end-to-end tests, component tests, or both.
  2. Check the install runtime. Cypress uses the system Node.js version to install its package. Its bundled Node runtime is separate; upgrading that bundled runtime is not a substitute for meeting the installation requirement.
  3. Check operating systems and browsers. Include local machines, containers, hosted runners, and any browser versions pinned in CI.
  4. Identify component-testing dependencies. Record framework, bundler, Cypress dev-server package, and whether the Cypress config is CommonJS, ESM, or TypeScript.
  5. Search for migration targets. Look for cross-origin visits, deprecated options, old component CLI commands, browser launch handlers, and unsupported internal calls.
  6. Plan the verification run. Decide which install, component, end-to-end, and CI commands represent the project’s normal checks. Their exact names depend on your repository.

For example, use your repository’s preferred search tool to find old APIs and commands:

rg -n "resourceType|experimentalFetchPolyfill|experimentalSkipDomainInjection|open-ct|run-ct|Cypress\.backend|before:browser:launch" .

Upgrade the Cypress dependency

Update Cypress with the package manager already used by the project, and commit the resulting lockfile change. For npm, an explicit Cypress 14 install looks like this:

npm install --save-dev cypress@14

For Yarn or pnpm, use that package manager’s normal add or upgrade command and preserve the repository’s lockfile workflow. Do not mix package managers during the upgrade. Confirm the installed package version with:

npx cypress version

If your goal is to move to a version newer than Cypress 14, use the official migration guide one major version at a time and verify each intermediate change. Cypress’s migration index includes guides for later majors.

Update tests that cross origins

An origin is determined by scheme, hostname, and port. A change to any of those creates a different origin. Under Cypress 14, commands that interact with the second origin must run inside cy.origin(), even if both hosts share a superdomain.

For example, https://www.cypress.io and https://docs.cypress.io are different origins. A test can visit the first site, navigate to the documentation site, and perform the second site’s interactions in an origin block:

describe('cross-origin navigation', () => {
  it('opens the docs and checks the page', () => {
    cy.visit('https://www.cypress.io');
    cy.contains('a', 'Documentation').click();

    cy.origin('https://docs.cypress.io', () => {
      cy.location('hostname').should('eq', 'docs.cypress.io');
      cy.get('body').should('be.visible');
    });
  });
});

Use the actual destination origin in each block. If a test moves across multiple origins, place the commands for each destination inside the corresponding cy.origin() callback. Review the official cy.origin() documentation for its callback constraints and supported patterns.

Transition option: injectDocumentDomain

injectDocumentDomain is a deprecated transition aid. Cypress documents it as a temporary way to reduce the need for cy.origin() between subdomains, with compatibility caveats; it can break sites and Cypress warns when it is enabled. Prefer migrating tests to explicit origin blocks and removing the option. Consult the configuration reference if you need to understand an existing setting before removing it.

Update deprecated APIs, browser hooks, and scripts

  • cy.intercept() and resourceType: audit uses of the deprecated resourceType option. Do not build new behavior around it; check the migration guide for supported interception patterns for your case.
  • experimentalFetchPolyfill: remove this option. Use cy.intercept() for fetch handling.
  • experimentalSkipDomainInjection: remove it; skipping domain injection is now the default behavior.
  • Browser launch hook: the second argument to before:browser:launch is launchOptions, not an array. Browser arguments are in launchOptions.args. Update handlers that treated the second argument as the arguments array.
  • Component-testing CLI: replace cypress open-ct with cypress open --component and cypress run-ct with cypress run --component in scripts and CI.
  • Undocumented backend calls: remove Cypress.backend('firefox:force:gc') and Cypress.backend('log:memory:pressure'). The migration guide gives no replacement for these calls.
  • Electron before navigation: do not call fetch or XMLHttpRequest from about:blank before navigating. Use cy.request() or visit a page first.

Use the migration guide as the authority for replacement behavior where a deprecated option has no direct drop-in equivalent.

Check component-testing compatibility

  • Webpack: Cypress 14’s webpack dev server no longer supports Webpack 4; use Webpack 5 or newer.
  • Vite: @cypress/vite-dev-server no longer supports Vite 4; use Vite 5 or newer. The Vite dev-server package is ESM-only. If your Cypress config is CommonJS, move it to an ESM context or a TypeScript config that works with your setup.
  • Angular: the component-testing minimum is Angular 18. Update the mount import from cypress/angular to @cypress/angular.
  • Vue 2: Cypress no longer bundles the Vue 2 component-testing harness. Cypress describes @cypress/vue2 as a separately installable, temporary deprecated workaround for projects that have not moved to Vue 3.
  • JIT compilation: just-in-time component compilation is the default through justInTimeCompile. It does not apply with Vite. For another supported setup, set justInTimeCompile: false if you need to disable it.

Check the framework and dev-server combination your project actually uses before changing configuration. Avoid copying a component configuration from another project without confirming its bundler, module format, and framework version.

Angular mount import

Update the mount import in Angular component tests as shown by the migration:

// Before
import { mount } from 'cypress/angular';

// After
import { mount } from '@cypress/angular';

Verify the upgrade in local development and CI

  1. Install dependencies from the updated lockfile in a clean environment.
  2. Confirm the Cypress package version and that the Cypress binary launches.
  3. Run component tests and end-to-end tests separately so a failure is easy to locate.
  4. Run tests that cover each cross-origin transition, including authentication or third-party flows your suite exercises.
  5. Run the same checks on the CI OS images and browser versions used for release builds.
  6. Review failures for outdated runtime, platform, browser, framework, bundler, config-module, or test-code assumptions before changing timeouts or adding retries.

Keep CI browser and OS versions reproducible where stable runs matter. Cypress 14’s stated browser support is the latest three major versions of Chrome, Firefox, and Edge, so a pinned runner can fall outside that range even when a developer’s automatically updated browser works.

Troubleshooting Cypress 14 upgrades

Symptom Likely cause Fix
Cypress installation fails or the package is unsupported. The system Node.js version used for installation is below 18 or is Node.js 21. Use a supported Node.js version (18 or newer, excluding the unsupported 21 version) in the install environment and rerun the package-manager install.
The Cypress binary will not run on a Linux runner. The distribution is based on glibc older than 2.28. Move to a compatible Linux image and rebuild or refresh the runner environment.
Cypress will not run on a Mac. The machine is using macOS older than 11 (Big Sur). Run on macOS 11 or newer.
A test fails after visiting another subdomain or port. The test interacts with a different origin outside cy.origin(). Wrap commands for the destination origin in a block using its exact scheme, hostname, and port.
A site breaks or Cypress warns about domain injection. The deprecated injectDocumentDomain transition option is enabled. Remove it and migrate cross-origin interactions to cy.origin(), unless a documented project-specific constraint requires the temporary workaround.
Component tests fail during bundling or dev-server startup. The project uses Webpack 4, Vite 4, an incompatible Angular version, or a module format unsupported by the Vite dev-server package. Check the Cypress 14 minimums, update the relevant stack, and use an ESM or TypeScript config for the ESM-only Vite dev server.
Component test scripts report an unknown command. A script still calls open-ct or run-ct. Use cypress open --component or cypress run --component.
A browser launch hook behaves as if arguments are missing. The hook treats its second parameter as an array. Read arguments from launchOptions.args.
A request from Electron fails before the first visit. fetch or XMLHttpRequest was called from about:blank. Use cy.request() or visit a page before making the browser request.

When a failure does not fit these patterns, compare the full Cypress error and stack against the migration guide and changelog before changing test logic. The cause may be a separate application or dependency change exposed by the upgrade.

Performance, reliability, and cost considerations

Cypress 14’s release notes describe component-testing performance improvements, but the dossier does not provide a benchmark. Measure your own component suite before and after the upgrade using the same runner, browser, and test selection. The release also adds compatibility with newer framework and dev-server versions, so a dependency-stack change can affect results independently of Cypress itself.

For reliability, focus on origin handling and the reproducibility of CI browsers and operating-system images. A local pass does not establish that a pinned CI browser or older Linux image meets Cypress 14’s supported requirements. Upgrade majors sequentially, keep the lockfile consistent, and use the same verification commands in local development and CI.

Cypress is installed through the project’s package manager; this migration has no per-screenshot or per-test price stated in the cited materials. Budget engineering time for dependency compatibility, test updates, and CI image changes. If your project captures website screenshots as a separate workflow, ScreenshotNeo is an alternative service described below.

Or skip the browser setup

If your goal is to capture a website screenshot rather than test browser behavior, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It returns an image or PDF from one GET request. Its capture options include full-page screenshots, element selection, viewport and device presets, custom CSS and JavaScript, waits, request blocking, and more. 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
  • Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses include X-Page-Verdict and X-Billed headers.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots; yearly billing gives two months free.

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

FAQ

Does Cypress 14 require cy.origin() for subdomains?

Yes, when a test moves between origins and interacts with the second one. Different hostnames are different origins even when they share a superdomain.

Can I keep using injectDocumentDomain?

It is a deprecated transition option with compatibility caveats. The recommended migration is to use explicit cy.origin() blocks.

Is Cypress 14 the latest Cypress major?

No. The migration index cited here includes later majors. For a current upgrade, follow the official migration guides sequentially and check the destination version’s requirements.

Does the Node.js requirement refer to the runtime bundled with Cypress?

The Node.js 18-or-newer requirement applies to installing the Cypress package with the system Node.js version. Cypress bundles a separate runtime.

References