Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Short answer: you cannot rely on an absolute pathname passed to cy.matchImageSnapshot() to choose where a baseline image is stored. The reviewed @simonsmith/cypress-image-snapshot documentation shows relative snapshot names, including nested names, and documents e2eSpecDir for arranging snapshots alongside your Cypress spec tree. Use those supported controls instead. If you need the absolute path of a Cypress screenshot artifact, read it from Cypress metadata rather than trying to calculate it.

What “absolute path” means in this setup

Three different paths are commonly confused:

What you are controlling Supported control What it affects
Image-snapshot baseline Relative name passed to matchImageSnapshot and the plugin’s e2eSpecDir The baseline snapshot tree maintained by the image-snapshot plugin
Cypress screenshot artifact cy.screenshot(name) and screenshotsFolder PNG/JPEG screenshots written by Cypress, not plugin baselines
Resolved pathname after saving onAfterScreenshot metadata or Cypress Node events Reports the path Cypress actually selected; it does not redirect output

An absolute string such as /var/tmp/baselines/home is not documented as a supported destination for matchImageSnapshot. Treating it as a guaranteed path can produce a wrong directory layout or behavior that changes between package forks and versions.

Use a relative snapshot name

Nested names are the documented approach

Pass a project-relative, slash-separated name:

cy.matchImageSnapshot('checkout/home');

The plugin README demonstrates this style with names such as some/dir/image. The name is interpreted within the plugin’s snapshot root, rather than as an operating-system pathname beginning at /.

Keep names stable

  • Use a deterministic name for the page or component under test.
  • Use forward slashes for nested folders so the name is portable across operating systems.
  • Do not include a drive letter, leading slash, .. traversal, or a full path copied from a local machine.
  • Include a state or viewport suffix when the same spec captures several legitimate baselines, for example account/dark/desktop.
describe('account page', () => {
  it('matches the desktop light theme', () => {
    cy.visit('/account');
    cy.matchImageSnapshot('account/light/desktop');
  });

  it('matches the desktop dark theme', () => {
    cy.visit('/account');
    cy.matchImageSnapshot('account/dark/desktop');
  });
});

Align the snapshot tree with your spec tree using e2eSpecDir

Why this option exists

Cypress 10 and later can remove a common ancestor from spec paths when it builds output directories. The resulting path can vary depending on which specs run together. The @simonsmith/cypress-image-snapshot README documents e2eSpecDir so the plugin can remove the configured E2E directory prefix and mirror the remaining spec structure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configuration example

In the plugin setup where you register the command, pass the E2E directory that matches the directory used by your specPattern:

addMatchImageSnapshotCommand({
  e2eSpecDir: 'cypress/e2e/'
});

With that setting, a relative name such as checkout/home remains a name inside the plugin’s snapshot hierarchy, while the spec-derived portion is organized consistently. The exact registration file differs between Cypress projects, so keep this option in the setup prescribed by the installed package version.

Check the installed fork before changing paths

The package name matters. The guidance above is for @simonsmith/cypress-image-snapshot. Older cypress-image-snapshot forks and other releases may expose different options or path rules. The current maintainer documentation says its tested Cypress versions are 15.x and 16.x, requires Cypress 15.10 or later for its Cypress.expose support, and recommends version 10.x with Cypress 13.x or 14.x. Verify your installed package and version in package.json, lockfile, and the package’s own README before relying on an option.

If you actually want to move Cypress screenshots

Change the base folder with screenshotsFolder

screenshotsFolder changes where Cypress writes screenshots created by cy.screenshot(). Its documented default is cypress/screenshots. It does not change the image-snapshot plugin’s baseline root.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  screenshotsFolder: 'artifacts/cypress-screenshots',
  e2e: {
    specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}'
  }
});

Use this when the requirement is “put ordinary Cypress screenshots under an artifacts directory,” not “put matchImageSnapshot baselines under an absolute pathname.” See the Cypress configuration reference for the current configuration name and default.

Use a nested relative screenshot name

cy.screenshot('checkout/failure');

Cypress combines the relative name with its screenshots folder and the spec-derived directory. A nested name creates nested folders; it is still not an absolute destination.

How to obtain the full path Cypress selected

Read props.path in onAfterScreenshot

If you need to log, attach, or process the actual file after Cypress saves it, use the callback metadata:

cy.screenshot('checkout/failure', {
  onAfterScreenshot: (element, props) => {
    // props.path is the resolved pathname on the machine running Cypress
    cy.log(`Saved screenshot: ${props.path}`);
  }
});

The callback reports the resolved location; it does not move the file. The Cypress screenshot API documents the callback metadata and nested naming behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Node-side screenshot events for automation

For CI processing, use Cypress’s Node events that receive screenshot details, including the resolved path. This is preferable to reconstructing a path from the spec filename. Cypress can strip the longest common ancestor across the specs in a run, so a path you calculate locally may differ when one spec is run alone versus as part of a larger set. The path rules and resolved-path guidance are described in Writing and organizing Cypress tests.

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on) {
      on('after:screenshot', (details) => {
        console.log(`Cypress wrote: ${details.path}`);
        return details;
      });
    }
  }
});

Keep the event handler observational. Changing details.path after the fact does not turn it into a new output destination unless you explicitly copy or move the file yourself.

Recommended decision path

  1. Need a visual-regression baseline? Use cy.matchImageSnapshot('relative/name'). Do not pass an absolute pathname as if it were a documented destination.
  2. Need the baseline tree to follow your specs? Set e2eSpecDir to the directory represented in your E2E configuration.
  3. Need ordinary Cypress screenshots somewhere else? Set screenshotsFolder, then use a relative name with cy.screenshot().
  4. Need to know where a file landed? Read props.path in onAfterScreenshot or consume the Node event details.
  5. Using an older fork? Inspect that exact package’s README, types, and implementation before assuming any of these options exist.

Troubleshooting path problems

Symptom Likely cause Fix
An absolute-looking name creates an unexpected folder The plugin documents relative names, not absolute destinations Replace it with a relative nested name and configure e2eSpecDir if spec alignment is needed.
Baselines are not under the configured screenshotsFolder screenshotsFolder controls Cypress screenshots, not plugin baselines Leave the settings separate; use the image-snapshot plugin’s documented snapshot configuration.
The same spec appears in different directories in CI Cypress removed a different longest common ancestor because the set of executed specs changed Use e2eSpecDir for the plugin tree, and read the resolved path from metadata instead of reconstructing it.
e2eSpecDir has no visible effect The value does not match the directory portion of your E2E spec pattern, or the installed fork does not support it Compare the option with the package README and your actual specPattern; confirm the installed package and version.
A callback logs an empty or wrong path The code is logging a guessed path or running before the screenshot callback Log props.path inside onAfterScreenshot, or use the Node screenshot event after Cypress reports completion.
Configuration works locally but not in CI Absolute paths differ by runner, operating system, workspace, or container Keep names relative and portable; treat the reported path as environment-specific and publish it as a CI artifact if needed.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Path portability and maintenance

Commit baselines by logical name

Visual baselines are easiest to review when their names describe the test state rather than a developer’s home directory. Relative names also avoid hard-coding Windows drive letters or Unix mount points into a repository.

Do not infer paths from one run

Cypress’s common-ancestor stripping means that the same spec can have a different resolved directory when the run includes a different collection of specs. For tooling that uploads or compares files, consume the path Cypress provides at runtime.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate artifact retention from baseline naming

Use screenshotsFolder and CI artifact settings for temporary screenshots. Use the image-snapshot plugin’s relative names and e2eSpecDir for committed visual-regression baselines. Keeping those concerns separate prevents a screenshot artifact setting from appearing to “break” baseline generation.

Or skip the browser setup

If your goal is simply to obtain a clean screenshot from a URL rather than maintain Cypress baselines, ScreenshotNeo makes one HTTP request. It accepts the cookie or consent banner as a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and bills only clean shots. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; the response identifies the result with X-Page-Verdict and X-Billed headers. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

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)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for request options. Every plan includes its features: full-page and element capture, device and retina settings, dark mode, PDF output, custom CSS and JavaScript, waiting and blocking controls, headers, cookies, user-agent, authorization, timezone and geolocation, transparent backgrounds, resizing, caching with a chosen TTL, signed links, asynchronous jobs with webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. The parameter names used by other screenshot APIs also work for easier migration.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; higher plans are Growth ($15/15,000), Pro ($39/60,000), Scale ($99/250,000), and Business ($249/1,000,000). Yearly billing provides two months free. Create a free ScreenshotNeo account to start without a card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.