ScreenshotNeo

BlogHow-to

Visual Regression Testing with TestCafe

Use TestCafe to capture screenshots, then add the baseline comparison workflow needed to catch visual changes. Includes configuration, Percy, limitations, and troubleshooting.

By the ScreenshotNeo team4 October 20269 min read

TestCafe can capture screenshots of a browser window or a selected element, but its screenshot actions do not by themselves perform visual regression testing. To detect visual changes, capture a page under repeatable conditions and compare the new image with an approved baseline, either with your own image-diff workflow or a visual testing integration such as Percy. TestCafe documents screenshot capture and artifact settings, but not native baseline comparison or visual-diff assertions. TestCafe’s screenshot and video guide also states that screenshots and videos cannot be taken of remote browsers.

1. Capture screenshots with TestCafe

Install TestCafe in a project that already has Node.js and a supported local browser available:

npm install --save-dev testcafe

Create tests/visual.test.js. This runnable example captures a full-window image and an element image. Replace the example URL and selector with the page and region your test owns.

import { Selector } from 'testcafe';

fixture`Visual capture`
  .page`https://example.com`;

test('capture page and main content', async t => {
  await t.takeScreenshot();
  await t.takeElementScreenshot(Selector('main'));
});

Run it in a local browser, for example:

npx testcafe chrome tests/visual.test.js

takeScreenshot() captures the current window. takeElementScreenshot() captures the selected element. These are useful artifacts for inspection or as inputs to a separate comparison step; neither action decides whether a rendering differs from an accepted baseline.

2. Configure artifact paths and failure capture

TestCafe runner screenshot settings let you control where images are saved, how their names are formed, and whether screenshots are taken when a test fails. The documented settings include path, takeOnFails, pathPattern, pathPatternOnFails, fullPage, and thumbnails. fullPage defaults to false.

import createTestCafe from 'testcafe';

const testcafe = await createTestCafe();
try {
  const runner = testcafe.createRunner();
  await runner
    .src('tests/visual.test.js')
    .browsers('chrome')
    .screenshots({
      path: 'artifacts/screenshots',
      takeOnFails: true,
      pathPattern: '${DATE}_${TIME}/${TEST}/${BROWSER}/${FILE_INDEX}.png',
      pathPatternOnFails: '${DATE}_${TIME}/${TEST}/${BROWSER}/failed_${FILE_INDEX}.png',
      fullPage: true,
      thumbnails: false
    })
    .run();
} finally {
  await testcafe.close();
}

Save this as a project script, such as run-visual.js, and run it with node run-visual.js. Runner settings can also be placed in TestCafe configuration. Check the runner and configuration documentation for the exact syntax supported by the TestCafe version in your project. Path patterns can include run date and time, test, browser or operating system, and screenshot index. Keep the output naming scheme stable enough for your artifact collection process.

takeOnFails is for failure evidence. A failed assertion may cause TestCafe to save a screenshot that helps diagnose the failure; this is not a baseline comparison and does not detect a visual-only change when the functional assertions pass.

3. Make visual comparisons repeatable

A useful comparison requires two images of the same intended state: a current capture and an approved baseline. The comparison process must report meaningful differences and provide a way for a person or policy to accept or reject an update. TestCafe’s capture features supply images; your comparison tool or code owns baseline storage, image comparison, thresholds, and review.

  1. Choose stable pages and states. Use deterministic test data, fixed routes, and a known application state. Avoid pages whose content changes on every run unless the variable region is handled deliberately.
  2. Control rendering inputs. Keep browser, operating system, viewport, device scale, fonts, locale, and page state consistent between baseline and current captures. This is implementation guidance for reliable image comparison; TestCafe does not automatically stabilize every rendered page.
  3. Wait for the intended state. Wait for a meaningful selector or application condition before capture. A fixed delay can help with a known animation, but it can also make runs slower and still fail to guarantee readiness.
  4. Choose the capture area. Use an element screenshot when only one component matters. Use a full-page capture when changes across the document matter, and confirm how your chosen comparison workflow handles long pages.
  5. Compare and review. Feed the new image and matching baseline to a visual-diff workflow. Review differences before replacing baselines so genuine regressions are not silently accepted.

Browser rendering can produce small differences from fonts, animation, dynamic data, timestamps, ads, and asynchronous content. Keep those inputs controlled where possible. If a region is intentionally variable, handle it in the comparison system rather than assuming TestCafe will filter it.

4. Add a managed comparison workflow with Percy

Percy publishes a TestCafe client library for visual regression testing. Its example uses percySnapshot; snapshots are uploaded when tests run under percy exec with the project’s PERCY_TOKEN. The repository example reports snapshots as disabled when Percy is not running. Review the Percy TestCafe client repository for current package and command requirements before integrating it.

import { Selector } from 'testcafe';
import percySnapshot from '@percy/testcafe';

fixture`Visual comparison`
  .page`https://example.com`;

test('snapshot the page', async t => {
  await t.expect(Selector('main').exists).ok();
  await percySnapshot(t, 'Example home page');
});

Install and run the package using the current instructions in its repository. The general workflow is to provide the project token securely in the environment and invoke the test command through Percy’s CLI, commonly in the form percy exec -- npx testcafe chrome tests/visual.test.js. Do not commit a real token to source control. Verify the current package name, CLI version, and supported TestCafe versions before adopting that command, because service and package requirements can change.

Applitools describes a visual testing service that compares builds against approved baselines and evaluates rendered results, but the reviewed source does not establish a TestCafe-specific integration. Do not assume compatibility based on a general service description; confirm a current integration guide for your exact stack before choosing it. See Applitools Eyes.

5. TestCafe screenshot limitations and design choices

  • Remote browsers: TestCafe’s screenshot and video guide says remote browser screenshots are unsupported. If your execution environment is remote, plan a supported local browser capture context or verify an alternative capture route before designing the visual check.
  • Full page versus window: full-page behavior is configurable and defaults to off. Long documents may be more expensive to capture and compare, and content below the fold can load differently from visible content. Use full-page capture only when that coverage is useful.
  • Capture versus assertion: screenshot actions save visual evidence. They do not provide a difference threshold, baseline approval workflow, or regression assertion on their own.
  • Artifacts and naming: choose paths that preserve enough run, test, browser, and index information to identify an image. Avoid overwriting evidence from parallel or repeated runs.
  • Scope: component screenshots reduce unrelated page noise; full-page screenshots cover broader layout changes. Select the scope based on what the test is intended to protect.

6. cURL, Python, and Node.js for a one-off reference capture

These examples capture a URL as an image for manual inspection or an external workflow. They are not TestCafe tests and do not compare against a baseline. TestCafe itself is a Node.js browser automation framework, so the JavaScript example above is the relevant in-framework code; cURL, Python, and plain Node.js can be useful for a separate reference capture.

cURL

curl -L 'https://example.com' -o page.html

This downloads HTML, not a rendered screenshot. A browser renderer is required to produce a page image. If you need a screenshot image from a URL without maintaining browser capture setup, see the ScreenshotNeo option below.

Python

from pathlib import Path
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1280, "height": 800})
    page.goto("https://example.com", wait_until="networkidle")
    page.screenshot(path="shot.png", full_page=True)
    browser.close()

Install Playwright and its Chromium browser following the official Python setup guide. This is an alternative browser capture workflow, not a TestCafe integration.

Node.js

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'shot.png', fullPage: true });
await browser.close();

Install Playwright and its browser as described in the official Node.js setup guide. These scripts only create an image. Add a separate baseline comparison step to make them visual regression checks.

7. Or skip the browser setup

For a one-call URL screenshot, ScreenshotNeo provides a screenshot API and MCP server. For example, this cURL request saves a WebP screenshot:

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

See the ScreenshotNeo API documentation for request options. ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the page verdict and billing status in headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for AI agents using Claude, Cursor, or another MCP client. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots.

ScreenshotNeo captures a URL but does not replace the baseline comparison and approval step described above. Sign up for 1,000 free screenshots a month, with no card required.

8. Troubleshooting

Symptom Likely cause Fix
No screenshot appears The output path is different from the expected working directory, or the test did not reach its capture action. Check the runner screenshot path, inspect the test result, and verify that the capture action executed.
Screenshot is only the visible window Full-page capture is disabled; the runner option defaults to false. Enable fullPage where appropriate and verify the resulting image dimensions.
Test fails but no failure screenshot is saved Failure capture is not enabled or the configured failure path is invalid. Set takeOnFails: true and check pathPatternOnFails and filesystem permissions.
Image changes on every run Dynamic page data, timing, browser, viewport, fonts, animation, or third-party content differs. Stabilize page state and rendering inputs, wait for the intended state, and control known variable content in the comparison workflow.
Remote browser capture fails TestCafe documents that it cannot capture screenshots or videos of remote browsers. Run the screenshot check in a supported local browser context or investigate a separate capture route.
Percy reports snapshots disabled or none uploaded The test was not run under the Percy CLI, or its project token is unavailable. Follow the repository’s current percy exec setup and provide PERCY_TOKEN securely to the process.
Visual change passes unnoticed The test only captures screenshots; no comparison assertion or managed review step is configured. Add a baseline comparison workflow and make its result part of the CI outcome.

9. Performance, reliability, and cost

Every capture adds browser work and produces an artifact that must be stored or uploaded. Full-page images and large suites can increase capture time, artifact volume, and comparison work. Capture only pages and regions that protect important behavior, and avoid redundant snapshots of identical state.

For reliable results, keep browser and viewport settings consistent, wait for a meaningful ready condition, use deterministic data, and preserve run identifiers in artifact names. Treat baseline updates as reviewed changes. A screenshot workflow is only as dependable as its input state and its comparison policy.

TestCafe is the capture layer in this setup; comparison costs depend on whether you maintain image storage and diff logic yourself or use a managed service. The research sources do not establish current Percy or Applitools prices, so verify pricing and service terms directly before choosing. ScreenshotNeo’s stated pricing is Free for 1,000 shots a month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing gives two months free, and every feature is on every plan. These are screenshot API prices, not prices for baseline comparison.

10. Frequently asked questions

Does TestCafe have built-in visual regression assertions?

The cited TestCafe screenshot documentation describes capture and artifact configuration, not baseline comparison assertions. Add a comparison workflow or an integration.

Can I use TestCafe screenshots for baselines?

Yes. Save repeatable captures and pair them with matching approved images in a separate comparison and review process.

Is Percy documented for TestCafe?

Yes. Percy’s public TestCafe client repository demonstrates percySnapshot and documents running snapshots with its CLI and project token. Check its current requirements before setup.

Can TestCafe take screenshots from a remote browser?

Its screenshot guide says it cannot take screenshots or videos of remote browsers.

Does ScreenshotNeo compare screenshots against baselines?

The product facts in this article describe URL capture and related API features, not baseline comparison. Keep a separate visual-diff system for regression decisions.