ScreenshotNeo

BlogComparisons

Cypress Screenshot Testing vs Selenium Screenshots for Website QA

Compare Cypress and Selenium screenshot capture for QA, with runnable examples and guidance on building a reliable visual regression workflow.

By the ScreenshotNeo team4 October 202610 min read

Cypress and Selenium can both capture screenshots during browser tests. Cypress uses cy.screenshot() and can automatically save a failure screenshot during cypress run. Selenium WebDriver can capture the current browsing context or an element. Neither capture command alone gives you a visual regression test: you still need an approved baseline, an image comparison step, and a way to review and accept intentional changes.

Choose Cypress when your application already has Cypress tests and you want capture and failure artifacts inside that runner. Choose Selenium when your suite already uses WebDriver and you want screenshots through its language bindings. For either tool, make the page state and rendering environment repeatable before relying on image diffs.

1. Screenshot capture and visual regression are different jobs

A screenshot is an image artifact. A visual regression workflow checks whether a new image differs from an approved image in a way that matters.

  1. Capture: put the application into a known state and save a page or element image.
  2. Compare: compare the new image with a baseline, using a local plugin or a visual testing service.
  3. Review: inspect the diff. If the change is expected, deliberately approve a new baseline; otherwise fix the regression.

Cypress explicitly says its built-in screenshot command does not compare images. The cited Selenium screenshot documentation describes capture methods, not baseline management or image comparison. So “the test saved a screenshot” does not mean “the test detected a visual regression.” Cypress visual testing guide · Selenium screenshot documentation

Need What to add
Debug a failed interaction Capture a useful failure artifact and retain it in CI.
Catch unexpected visual changes Capture at deliberate checkpoints, compare to baselines, and review diffs.
Validate appearance across browsers or viewport widths Run captures in each required environment, or use an integration that provides those rendering and review capabilities.

2. Cypress screenshots: manual capture and failure artifacts

Use cy.screenshot() for a manual checkpoint. Cypress also captures a screenshot automatically when a test fails in cypress run; that automatic failure capture does not happen in cypress open. By default, files go in cypress/screenshots. Cypress screenshots and videos

Runnable Cypress example

This JavaScript example assumes Cypress is installed and the application is available at http://localhost:3000. Save it as cypress/e2e/checkout.cy.js and run it with npx cypress run --spec cypress/e2e/checkout.cy.js.

describe('checkout appearance checkpoint', () => {
  it('captures the confirmation state', () => {
    cy.viewport(1280, 800)
    cy.visit('http://localhost:3000/checkout')

    cy.get('[data-testid="checkout-ready"]').should('be.visible')
    cy.get('[data-testid="place-order"]').click()
    cy.get('[data-testid="order-confirmation"]').should('be.visible')

    // Saves an artifact. This line does not compare against a baseline.
    cy.screenshot('checkout-confirmation')

    // Element capture is also supported:
    cy.get('[data-testid="order-confirmation"]').screenshot('confirmation-panel')
  })
})

Replace the example selectors with stable selectors in your app. If you need an actual visual assertion, replace or supplement the capture line with the command provided by your chosen visual-diff plugin or service; command names and baseline setup differ by integration.

Useful Cypress settings and behavior

Setting or behavior Effect
screenshotsFolder Sets the output directory. Default: cypress/screenshots.
screenshotOnRunFailure Controls automatic failure screenshots during cypress run; the documented default is true.
trashAssetsBeforeRuns Defaults to clearing assets in the downloads, screenshots, and videos folders before a run. Set it to false if your workflow must preserve those files between runs.
cy.screenshot(name) Uses a named image path under the screenshots folder. Duplicate names get numbered unless you use the documented overwrite option.
element.screenshot(name) Captures an element instead of the whole application view.

For example, in cypress.config.js:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  screenshotsFolder: 'artifacts/cypress-shots',
  screenshotOnRunFailure: true,
  trashAssetsBeforeRuns: false,
})

Be deliberate with trashAssetsBeforeRuns: false: stale images can be mistaken for artifacts from the latest run. Cypress documents screenshot settings in its configuration reference and naming behavior in the screenshot API reference.

3. Selenium screenshots: page and element capture

The Selenium WebDriver API exposes screenshots for the current browsing context and elements. Its documentation describes the command result as Base64-encoded image data; language bindings offer ways to save that image. Selenium does not prescribe how your test framework retains failure artifacts, so add that behavior at the test-runner or project level if you need it.

Runnable Selenium example in Python

Install the Selenium Python binding with python -m pip install selenium, make a page and driver available, then save this as screenshot_qa.py. The example uses Selenium Manager through webdriver.Chrome(); browser and driver availability still depend on your environment.

from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

options = webdriver.ChromeOptions()
options.add_argument('--headless=new')
options.add_argument('--window-size=1280,800')

driver = webdriver.Chrome(options=options)
try:
    driver.get('http://localhost:3000/checkout')
    wait = WebDriverWait(driver, 15)
    confirmation = wait.until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid="order-confirmation"]'))
    )

    # Save the current browsing context.
    driver.save_screenshot('checkout-page.png')

    # Save only the selected element.
    confirmation.screenshot('confirmation-panel.png')
finally:
    driver.quit()

The script captures a page and element after waiting for the target state. It does not perform image comparison. Add your selected comparator and baseline review workflow separately.

Equivalent Selenium capture in JavaScript

For teams already using the JavaScript Selenium binding, the following saves the current screenshot and a selected element screenshot. Install the binding with npm install selenium-webdriver and make a compatible browser available.

const fs = require('node:fs/promises')
const { Builder, By, until } = require('selenium-webdriver')
const chrome = require('selenium-webdriver/chrome')

;(async () => {
  const options = new chrome.Options().addArguments('--headless=new', '--window-size=1280,800')
  const driver = await new Builder().forBrowser('chrome').setChromeOptions(options).build()

  try {
    await driver.get('http://localhost:3000/checkout')
    const confirmation = await driver.wait(
      until.elementLocated(By.css('[data-testid="order-confirmation"]')),
      15000
    )
    await driver.wait(until.elementIsVisible(confirmation), 15000)

    const pageBase64 = await driver.takeScreenshot()
    await fs.writeFile('checkout-page.png', pageBase64, 'base64')

    const elementBase64 = await confirmation.takeScreenshot(true)
    await fs.writeFile('confirmation-panel.png', elementBase64, 'base64')
  } finally {
    await driver.quit()
  }
})().catch(error => {
  console.error(error)
  process.exitCode = 1
})

The screenshot APIs exist across Selenium language bindings; use the official documentation for the binding and version your project runs. Selenium WebDriver screenshot examples

4. Cypress vs Selenium for website QA

QA consideration Cypress Selenium
Capture API cy.screenshot(); supports application and element capture. WebDriver screenshot methods for the current browsing context and elements.
Automatic failure screenshot Documented for cypress run; not automatic in cypress open. The cited screenshot API documents explicit capture. Failure artifact behavior depends on your test framework or implementation.
Image comparison built in to capture command No. Add a visual-testing plugin or service. The cited docs establish capture methods, not baseline comparison. Add a comparison workflow.
Best fit Existing Cypress suites that benefit from runner-integrated screenshots and failure artifacts. Existing WebDriver suites, especially where the team already uses Selenium’s language bindings and infrastructure.
Baseline and review Choose and configure a plugin or service. Choose and configure a comparison and review process.

Neither tool is universally more accurate or faster based on the cited documentation. The deciding factors are your existing automation stack, language, CI environment, and how you want to compare and review images.

5. Make screenshot comparisons reliable

Visual diffs are useful only when unrelated variation is controlled. The same page can render differently because of browser versions, operating systems, fonts, viewport, changing data, animation, or timing. Cypress recommends consistent environments and fixed viewports for visual comparisons. Cypress visual testing reliability guidance

  1. Fix the viewport and browser: set the same viewport for baseline creation and comparison, and pin the browser or CI image where practical.
  2. Wait for the intended state: assert that key content is visible and loaded before capturing; avoid arbitrary sleeps when a meaningful selector or application condition is available.
  3. Control data and time: use stable fixtures or stubbed responses, and freeze time when dates or timers appear in the UI.
  4. Remove animation variance: disable animation in a test stylesheet or ensure the captured state is settled.
  5. Choose snapshot scope intentionally: element snapshots reduce unrelated diffs; full-page screenshots are useful when page layout itself is the subject.
  6. Review before updating baselines: approving a new baseline without inspecting the change can hide a real defect.

Third-party content such as ads, live widgets, and animated media may remain unpredictable. Where your chosen comparison tool supports masking or ignoring regions, use that narrowly. Raising a whole-page difference threshold can conceal meaningful changes.

6. CI artifacts, performance, reliability, and cost

Artifacts and storage

  • Upload screenshots from failed tests as CI artifacts if developers need to inspect them after the job ends. Confirm retention and access rules fit your team’s needs, especially if pages contain user or account data.
  • Use stable names that identify the spec, state, viewport, and relevant variant. Keep generated images out of source control unless your baseline workflow intentionally versions them.
  • For Cypress, account for the default cleanup of asset folders before cypress run. For Selenium, implement capture and artifact retention through your runner or test hooks.

Runtime and reliability

Captures add work and produce files; full-page images and large suites can increase artifact volume. The research sources provide no controlled speed comparison between Cypress and Selenium, so benchmark your own suite if runtime is a decision criterion. Reduce avoidable work by capturing deliberate checkpoints instead of every intermediate state, and prefer focused element snapshots when they answer the QA question.

Do not treat a screenshot as proof that the whole page loaded correctly. Assert the expected state before capture, and distinguish an application failure from an unstable rendering environment. Retries can produce multiple artifacts; Cypress documents attempt suffixes for screenshots in retried tests. Review the final attempt and earlier failures together when diagnosing flakiness.

Cost

Capture through the browser automation library uses your existing test infrastructure; storage, CI minutes, and any separate comparison service may have their own costs. Cypress’s visual testing guide distinguishes open-source plugins, where you manage baselines and review, from hosted services that handle comparison and review. The dossier does not establish current prices or terms for named third-party products, so check their own documentation before choosing one. Cypress documented visual testing options

7. Troubleshooting common screenshot problems

Symptom Likely cause Fix
No automatic Cypress screenshot in interactive mode Failure screenshots are automatic in cypress run, not cypress open. Call cy.screenshot() explicitly while debugging interactively, or inspect the run artifact.
Cypress screenshot folder looks empty or old files disappeared cypress run clears asset folders before a run by default. Inspect the configured screenshotsFolder; set trashAssetsBeforeRuns: false only if preserving files is intended.
Screenshot exists but visual test passes despite a visible change Capture alone does not compare images. Add a visual comparison command or service and verify that the checkpoint is included in its workflow.
Baseline diffs on every run Changing data, viewport, fonts, browser, animation, time, or asynchronous rendering. Stabilize those inputs and compare in the same environment with a fixed viewport.
Selenium cannot locate the element to capture The page has not reached the expected state, the selector is wrong, or the element is inside a frame or different browsing context. Wait for a meaningful condition, verify the selector, and switch to the appropriate frame or window before locating it.
Selenium screenshot file is not a valid image Base64 output was written as plain text or decoded incorrectly. Use the binding’s screenshot save method, or write the returned Base64 data with Base64 decoding as in the JavaScript example.
Failure artifact is missing in Selenium Screenshot capture on failure is not supplied by the cited capture API itself. Add an after-failure hook in your test framework that captures before quitting the driver, then upload the artifact from CI.
Element screenshot is clipped or unexpected The element was offscreen, not visible, covered, or captured before layout settled. Wait for visibility, scroll or bring it into view when needed, and verify the final rendered state before capture.

8. Or skip the browser setup

If your immediate need is a website screenshot rather than an assertion inside an existing UI test, ScreenshotNeo provides a screenshot API and MCP server. Its one-request API can return an image or PDF, and its browser setup is handled by the service. 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}`)
await Bun.write('shot.webp', res)

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed, and response headers identify the page verdict and billing status. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. This API is useful for taking screenshots, while baseline comparison remains a separate visual-testing workflow.

Sign up for ScreenshotNeo and get 1,000 screenshots a month free, with no card.

9. Frequently asked questions

Does Cypress save a screenshot when a test passes?

Only when your test or another configured workflow explicitly captures one. Automatic Cypress screenshots are for failures during cypress run.

Can Selenium capture just one element?

Yes. Selenium WebDriver documents element screenshot methods in addition to screenshots of the current browsing context.

Should every test have a visual snapshot?

No. Snapshot meaningful states that a reviewer can interpret. Too many low-value snapshots create review noise and baseline maintenance.

Do I need both functional assertions and image comparisons?

They answer different questions. Functional assertions verify behavior and state; image comparison checks rendered appearance. A focused suite can use both where each adds coverage.

Can I compare screenshots from different operating systems?

You can, but rendering differences may create noise. For pixel-based baselines, generate and compare in the same controlled environment unless the purpose is specifically to test cross-environment rendering.

Sources