The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Most Cypress “full-page” failures come from using the wrong capture mode, a page that does not actually scroll, sticky elements being stitched repeatedly, or a browser window that is too small for the configured viewport. Start by identifying the symptom, then apply the matching fix. Cypress’s fullPage mode scrolls the application and stitches multiple images; it is not the same as a viewport capture or a failure screenshot that includes the Test Runner.
First, verify which screenshot Cypress took
Cypress documents three capture modes in cy.screenshot():
| Mode | What appears | Typical use |
|---|---|---|
viewport |
The current application viewport only | A screen-sized state |
fullPage |
The application from top to bottom, captured while scrolling and stitching | A long document |
runner |
The whole browser viewport, including the Cypress Command Log | Debugging the test runner |
Use an explicit application capture when you need a full page:
cy.visit('/page')
cy.get('[data-cy=page-ready]').should('be.visible')
cy.screenshot('page-full', { capture: 'fullPage' })
Replace the readiness selector with one your application renders. The query and assertion retry while the page becomes ready; cy.screenshot() itself does not retry chained assertions.
Why a failure screenshot looks different
Automatic screenshots after a failed test are coerced to runner, so they can contain the Command Log instead of an application-only full-page image. Cypress takes these automatic failure screenshots during cypress run, not in cypress open. The screenshotOnRunFailure setting defaults to true; use a manual command in open mode.
Fix repeated headers and floating controls
Full-page capture works by scrolling from top to bottom and stitching screenshots. A fixed or sticky element can therefore appear in several stitched sections. Cypress’s documented workaround temporarily changes the element to absolute positioning:
cy.get('.sticky-header').invoke('css', 'position', 'absolute')
cy.screenshot('page-full', { capture: 'fullPage' })
cy.get('.sticky-header').invoke('css', 'position', null)
Use your real selector and restore the exact original style if it was not the browser default. Because a test can fail between the mutation and cleanup, put restoration in a cleanup strategy appropriate to your suite. Changing positioning can alter layout, so confirm that the resulting image still represents the intended page.
Fix clipping: inspect the page’s real scroll container
A full-page option cannot capture content that the document never exposes through scrolling. Check these items in the browser:
- Measure the rendered document and compare
document.documentElement.scrollHeightwithwindow.innerHeight. - Find the element that actually scrolls. Some dashboards place overflow on a nested panel while
htmlandbodyremain viewport-sized. - Inspect the saved image dimensions and compare them with the intended page height.
- Look for
html, body { height: 100vh; width: 100vw; overflow: hidden; }and CSS-grid layouts that intentionally remove top-level scrollbars.
Cypress GitHub issue #25516 reports clipping in a scalable CSS-grid interface using 100vw/100vh, with Cypress 12.2.0, Node 18.12.0 and Windows 10 Pro. It is a version-specific reproduction report, not proof that every grid page or current Cypress release fails, and the issue content does not establish a general resolution.
When the page uses an inner scroller
If the application’s design requires scrolling inside a panel, decide what “full page” means. Cypress’s application capture follows the document while stitching; it does not automatically expand every nested virtualized list. For a panel, capture that element with the appropriate element-focused screenshot behavior in your Cypress version, or change the test fixture so the document itself can scroll. Do not add arbitrary waits until you have confirmed the scroll container.
Fix blurry or unexpectedly small images
Increasing viewportWidth and viewportHeight changes the application’s internal viewport, but the Test Runner may scale its iframe down to fit the available browser window. The Cypress explanation is covered in its high-resolution article. Make more physical display area available:
- In
cypress open, enlarge the browser window or narrow/close the Command Log. - In CI, inspect the browser launch size and the X server or display dimensions available to the job.
- Compare the configured viewport, actual browser window, iframe display area and saved file dimensions rather than assuming one setting controls all four.
The article gives historical examples of CI browsers around 1280×720 and smaller Linux displays. Treat those as examples from that article, not universal limits for current runners.
Make sure the captured state is ready
Screenshot capture is asynchronous and Cypress documents an approximate 100 ms capture interval. During that period, an animation, timer, route transition or lazy-loaded image can change the state. Cypress also renders the Command Log asynchronously, so a failure message may not yet be visible in the image.
- Wait on an application-level readiness signal, such as a stable element or completed network-driven state.
- Assert the content you need before calling
cy.screenshot(). - Check the screenshot option
disableTimersAndAnimations, which defaults totrue. It prevents JavaScript timers and CSS animations while the image is taken, so an animated page can differ from its ordinary appearance. - If you need the complete sequence around a failure, enable video for
cypress run. Video is disabled by default, is not recorded incypress open, and can show transitions that a single image cannot.
Timer patch bypass and SSR hydration
Cypress patches macrotimer functions so it can pause them during capture. The error reference at Common error messages notes that scripts retaining references to the unpatched timers can prevent that pause and produce unpredictable behavior. Investigate this only when the symptom points to timer interference.
The same reference describes a specific React 18+ server-side-rendering hydration condition: place the data-cy-bootstrap marker first in <head>, or ensure other scripts use defer or async. That is a scoped hydration remedy, not a universal screenshot fix.
Rank #4
Find screenshots that seem to be missing
Cypress writes screenshots to screenshotsFolder, which defaults to cypress/screenshots. Read the terminal output for the exact path and check that your CI job uploads it.
- Local runs: verify the configured folder and filename after the command completes.
- Repeated
cypress runjobs: remember thattrashAssetsBeforeRunsdefaults totrue, clearing screenshots before a run. Set it tofalsewhen preserving existing assets is intentional. - CI: export the folder through your provider’s artifact mechanism or view captures in Cypress Cloud, as described in Capture screenshots and videos in Cypress.
A practical diagnostic sequence
- Open the image and classify it: viewport-only, repeated sticky content, clipped height, low resolution, wrong state, or absent file.
- Confirm the command and mode. Use
{ capture: 'fullPage' }for an application image; do not judge that mode from an automatic failure screenshot. - Assert a stable readiness marker immediately before capture.
- Inspect document height and the element with overflow scrolling.
- Temporarily neutralize sticky/fixed elements, then restore them safely.
- Compare configured viewport and actual browser/display dimensions.
- Check timer/animation settings only if timing is implicated.
- Verify the output folder, cleanup setting and CI artifact upload.
Common symptoms and targeted fixes
| Symptom | Likely cause | Action |
|---|---|---|
| Only the visible screen appears | viewport capture or failure screenshot |
Run an explicit fullPage capture; inspect the command mode. |
| Header repeats down the image | Sticky/fixed element is present in each stitched segment | Temporarily set that selector to position: absolute and restore it. |
| Bottom content is cut off | No top-level scroll, nested scroller, or layout clipping | Inspect scroll height, overflow ownership and saved dimensions. |
| Image is blurry | Runner iframe scaled to fit a smaller window/display | Increase browser/display size and compare actual output dimensions. |
| Expected text is absent | Capture raced a transition, timer, animation or Command Log render | Assert readiness; review timer/animation behavior; use video for sequence-level evidence. |
| File disappears between runs | trashAssetsBeforeRuns: true |
Change the setting when retention is required and upload CI artifacts. |
Or skip the browser setup
If you need a dependable website image outside the Cypress test runner, ScreenshotNeo provides a GET-based screenshot API and an MCP server. It accepts 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 disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status.
One call returns PNG, JPEG, WebP or PDF. The API supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper/margins/page ranges, custom CSS and JavaScript, clicks, waits, request/resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, selectable-TTL caching, signed image links, asynchronous webhooks, 100-URL bulk calls and a usage API. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.
See the ScreenshotNeo API documentation for parameter details.
Best Value
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}`);
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsWhen capture works but comparison is the real goal
cy.screenshot() creates an image; it does not compare images. If you need visual regression review, Cypress’s visual-testing guide discusses integrations designed for image comparison. Choose that tooling only after fixing capture dimensions, state and artifact handling.
Frequently Asked Questions
Does Cypress fullPage capture the Cypress Command Log?
No. An explicit application capture with capture: 'fullPage' captures the application. Automatic failure screenshots are coerced to runner and include the Cypress UI.
Why does my full-page screenshot repeat a sticky header?
Cypress scrolls and stitches sections, so fixed or sticky elements can appear in each section. Temporarily change the element’s position during capture and restore it safely afterward.
Does cy.screenshot() compare the image with a baseline?
No. It saves an image; visual comparison requires a separate integration.
Free tools Windows power users keep installed
One-click scans. No signup required.
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.




