Recommended Free Tools
Use Cypress’s run-mode failure screenshots and let @badeball/cypress-cucumber-preprocessor attach them to its report. Run the feature suite with cypress run, keep screenshotOnRunFailure enabled, enable the preprocessor’s HTML output and attachments.addScreenshots, then verify that the generated HTML actually renders the image. A file in cypress/screenshots alone does not prove that the report contains an attachment.
What “failed-step screenshot” means in Cypress BDD
There are two separate artifacts:
- Cypress’s screenshot file: a PNG written when a test fails during
cypress run. - The BDD report attachment: an image reference or inline image that the preprocessor places in its JSON/HTML report.
The built-in screenshot is taken for the failed test (and therefore the browser state at failure), not by a guaranteed post-step callback. The preprocessor’s documentation specifically says its AfterStep() hook does not run when the step itself fails. Do not rely on that hook as your capture mechanism.
Prerequisites and version checks
- Cypress configured for end-to-end tests.
@badeball/cypress-cucumber-preprocessorinstalled and registered.- A feature-file pattern such as
cypress/e2e/**/*.feature. - A lockfile you can inspect when report behavior differs from the current documentation.
Configuration names have changed across releases, so use the keys documented for the version pinned in your project. The names below are the current documented shape: html.enabled, html.output, json.enabled, json.output, and attachments.addScreenshots. Equivalent Cypress environment keys are htmlEnabled, htmlOutput, jsonEnabled, jsonOutput, and attachmentsAddScreenshots.
Configure the Cypress Cucumber preprocessor
Register the plugin in cypress.config.js
The integration must be installed in setupNodeEvents. This example also wires the esbuild preprocessor used to bundle feature files:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute#1 Best Overall
const { defineConfig } = require("cypress");
const {
addCucumberPreprocessorPlugin,
} = require("@badeball/cypress-cucumber-preprocessor");
const { createBundler } = require("@bahmutov/cypress-esbuild-preprocessor");
const {
createEsbuildPlugin,
} = require("@badeball/cypress-cucumber-preprocessor/esbuild");
module.exports = defineConfig({
e2e: {
specPattern: "cypress/e2e/**/*.feature",
async setupNodeEvents(on, config) {
await addCucumberPreprocessorPlugin(on, config);
on(
"file:preprocessor",
createBundler({
plugins: [createEsbuildPlugin(config)],
})
);
return config;
},
},
});
This registration is necessary even if Cypress itself is already producing files in the screenshots directory. Without the preprocessor plugin, the BDD report generator has no opportunity to add those files as report attachments.
Enable HTML output and screenshot attachments
Set the report options in the preprocessor configuration file or in the location required by your installed release. A representative configuration shape is:
{
"html": {
"enabled": true,
"output": "reports/cucumber.html"
},
"json": {
"enabled": true,
"output": "reports/cucumber.json"
},
"attachments": {
"addScreenshots": true
}
}
If your version uses Cypress environment variables instead, the corresponding values are:
module.exports = defineConfig({
e2e: {
env: {
htmlEnabled: true,
htmlOutput: "reports/cucumber.html",
jsonEnabled: true,
jsonOutput: "reports/cucumber.json",
attachmentsAddScreenshots: true,
},
},
});
Do not blindly combine both forms. Choose the configuration mechanism documented by the package version in your lockfile, and make sure the output directory exists or is created by the reporter.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsKeep Cypress failure screenshots enabled
Cypress captures a screenshot automatically when a failure occurs in cypress run. The screenshotOnRunFailure setting defaults to true. Make that explicit if a shared configuration might override it:
Rank #2
module.exports = defineConfig({
e2e: {
screenshotOnRunFailure: true,
screenshotsFolder: "cypress/screenshots",
},
});
The default screenshot directory is cypress/screenshots. If you change screenshotsFolder, use the new location when checking artifacts and when diagnosing missing report images.
You can also control the setting at runtime with Cypress’s screenshot defaults, but a project-level configuration is easier to audit in CI:
Cypress.Screenshot.defaults({
screenshotOnRunFailure: true,
});
Failure screenshots are not automatically taken by interactive cypress open. To test this workflow, run the same feature in headless or headed run mode with the CLI.
Run the suite and inspect both artifacts
- Start a run, for example
npx cypress run, or target a feature with your project’s normal Cypress command. - Intentionally allow a step to fail in a disposable branch or test fixture.
- Check
cypress/screenshots(or your configured folder) for a new image. - Open the generated HTML at the configured output path and confirm the image is visible there, not merely present on disk.
- Open the JSON report as well. The preprocessor’s feature tests expect an image attachment for a failed test; JSON is a useful way to distinguish a capture problem from an HTML-rendering problem.
A typical filename is based on the spec and test name with a (failed) suffix. If retries are enabled, each failed attempt can produce another file with an attempt suffix such as (attempt 2). Treat multiple images as expected evidence of separate attempts, not duplicate capture bugs.
Why a failed screenshot may not appear in the HTML
The run used cypress open
Interactive mode does not provide the automatic run-failure screenshot behavior. Reproduce the failure with cypress run.
Rank #3
screenshotOnRunFailure was disabled
Search project configuration, environment overrides, and support code for screenshotOnRunFailure: false or a call to Cypress.Screenshot.defaults that disables it.
The plugin was never registered
Confirm that addCucumberPreprocessorPlugin(on, config) runs inside setupNodeEvents and that the returned config is returned. Also confirm that the feature-file bundler is registered.
Free tools Windows power users keep installed
One-click scans. No signup required.
HTML output or attachments are disabled
Check html.enabled (or htmlEnabled) and attachments.addScreenshots (or attachmentsAddScreenshots). A screenshot on disk with no report attachment usually points to this layer.
The report is written somewhere else
Verify the exact html.output, json.output, and screenshotsFolder paths. CI jobs often publish a different workspace directory than local runs.
The HTML renderer differs from the installed release
The preprocessor’s documentation and tests can evolve on its master branch. Compare the generated JSON and the package version in your lockfile. If JSON contains the image attachment but HTML does not display it, treat that as a renderer/version compatibility issue rather than a Cypress capture failure.
Rank #4
The test failed before the browser produced a usable page
Blank pages, navigation failures, and browser crashes can result in an empty or unhelpful image. First establish whether Cypress wrote an artifact; then investigate the underlying application failure. Do not add an AfterStep() workaround expecting it to run after the failed step—the documented hook behavior rules that out.
Retries, report size, and CI reliability
Retries
Every failed attempt can create its own screenshot. Keep the attempt suffixes when triaging flaky tests; deleting them in a post-processing step can remove the evidence needed to identify which attempt failed.
Attachment size
The preprocessor release notes describe screenshots and videos as base64-encoded inline report attachments and call video support rudimentary. Inline encoding makes a report self-contained but can make HTML and JSON large, especially with full-page images or many retries. Archive reports deliberately and set CI artifact-retention limits appropriate to your project.
Deterministic CI output
- Use a clean, known
screenshotsFolderfor each job. - Publish the HTML, JSON, and screenshot directories together when troubleshooting.
- Keep the Cypress and preprocessor versions pinned.
- Run one failing fixture after upgrades to verify that the HTML still renders attachments.
Choosing an implementation strategy
| Approach | Best evidence it provides | Important limitation |
|---|---|---|
| Built-in Cypress failure screenshot plus preprocessor attachment | Browser state at a failed test, with JSON/HTML report integration | Capture occurs for the failed test; it is not a guaranteed post-failed-step hook |
| Custom hook or attachment code | Can add domain-specific data or a deliberately timed capture | The preprocessor’s AfterStep() does not run when the step itself fails, so generic Cucumber recipes may not work |
| External reporter | Potentially different layouts, storage, or CI integrations | Compatibility, embedding behavior, and artifact links must be validated against your Cypress and preprocessor versions |
For the documented Cypress BDD path, start with the built-in screenshot and preprocessor attachment settings. Add custom reporting only when you have a concrete requirement that this path cannot satisfy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your goal is simply to capture a page or diagnostic view outside the Cypress run, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
The same endpoint supports PNG, JPEG, WebP, or PDF output. For a one-call capture, 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
There is a free allowance of 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it.
Frequently needed variations
Capture a screenshot only for selected failures
Leave the global failure capture enabled for reliable diagnostics, then filter or publish only selected attachments in your CI report step. Disabling the global setting and attempting to recreate it in a failed-step hook is less reliable because the failing hook may never execute.
Need the exact failed step rather than the final failed test state?
The documented automatic mechanism gives you the failed test’s browser state. If an exact step boundary is mandatory, design an explicit capture before the risky command or use a custom attachment strategy whose execution semantics you have verified with the installed preprocessor version.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Can the report link to files instead of embedding them?
Do not assume that behavior. The preprocessor release notes describe inline base64 attachments, and HTML rendering can vary by version. Inspect the generated JSON and HTML rather than inferring storage from the existence of a PNG file.
Frequently Asked Questions
Does this work with Cypress component testing?
The documented setup targets Cypress end-to-end feature files registered through setupNodeEvents. Confirm component-testing support separately for your preprocessor version.
Should I delete screenshots after the HTML report is generated?
Keep them until you have verified the report and completed CI artifact collection; inline attachments and external file references can differ by version.
Why are there several screenshots for one scenario?
Retries can generate one artifact per failed attempt, with an attempt suffix in the filename.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Is an After() hook required?
No. Cypress run-mode failure capture plus the preprocessor’s screenshot-attachment option is the primary documented path. Hook behavior should only be added for a requirement the built-in path does not cover.
Quick Recap
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.




