ScreenshotNeo

BlogHow-to

How to Take a Full-Page Screenshot in Cypress

Capture an entire page with Cypress, handle sticky headers and lazy content, and troubleshoot screenshots in CI. Includes a one-call ScreenshotNeo option.

By the ScreenshotNeo team4 October 20269 min read

Use cy.screenshot('page-full', { capture: 'fullPage' }) after the page reaches the state you want to save. Cypress scrolls the application under test from top to bottom and stitches the captures into one image. fullPage is also the documented default for a normal cy.screenshot() call, but specifying it makes the intended capture scope explicit. Cypress screenshot API documentation.

cy.visit('/article')
cy.get('main article').should('be.visible')
cy.screenshot('article-full-page', { capture: 'fullPage' })

1. Capture an entire page

Put the screenshot command after the test has reached the content and state that matter. The selector assertion below is an example; use an assertion that checks the page-specific content or state your test needs.

describe('article screenshot', () => {
  it('saves the full article page', () => {
    cy.visit('/article')
    cy.get('main article').should('be.visible')
    cy.screenshot('article-full-page', {
      capture: 'fullPage',
    })
  })
})

This is a manual screenshot and works in both cypress open and cypress run. Cypress also automatically takes a screenshot when a test fails in cypress run, but not in cypress open. Cypress screenshots and videos guide.

2. Choose the capture area

The capture option controls which area Cypress saves:

Value What it captures When to use it
fullPage The application from top to bottom, captured while scrolling and stitched together. Save the entire page in one image.
viewport The application area in the current viewport. Save only what is currently visible in the app.
runner The browser viewport including the Cypress Command Log. Include Cypress runner context; failure screenshots are coerced to this mode.

For a normal full-page screenshot, the shortest form is cy.screenshot(), because fullPage is the documented default. Use a name and explicit mode when you want a predictable artifact and a clear record of intent:

cy.screenshot('checkout-summary', { capture: 'fullPage' })
cy.screenshot('visible-checkout', { capture: 'viewport' })
cy.screenshot('checkout-with-runner', { capture: 'runner' })

See the screenshot command options for current API details.

3. Set the viewport for the layout you want

Viewport dimensions and capture mode solve different problems. cy.viewport() controls the application’s rendered viewport and responsive layout. capture: 'fullPage' selects a capture that covers the page from top to bottom. Increasing viewport height does not select full-page capture.

Cypress documents a default viewport of 1000 by 660 pixels until you change it, and restores the default between tests. Set the viewport when the screenshot should represent a particular responsive breakpoint:

cy.viewport(1280, 800)
cy.visit('/article')
cy.get('main article').should('be.visible')
cy.screenshot('article-desktop-full', { capture: 'fullPage' })

For a mobile layout, select the dimensions your test is meant to exercise, then use the same full-page capture mode:

cy.viewport(390, 844)
cy.visit('/article')
cy.get('main article').should('be.visible')
cy.screenshot('article-mobile-full', { capture: 'fullPage' })

Choose the viewport based on the layout under test. A full-page capture can be very tall, so the screenshot’s output dimensions can differ substantially from the viewport dimensions.

4. Make page content ready before capture

Cypress disables JavaScript timers and CSS animations by default during screenshot capture. That helps reduce movement, but it does not guarantee that every network request, lazy-loaded image, or application-specific section has finished loading. Wait for the state your screenshot requires before calling cy.screenshot().

cy.visit('/article')
cy.get('main article').should('be.visible')
cy.get('[data-testid="article-body"]').should('contain.text', 'Conclusion')
cy.get('img[data-critical="true"]').should('be.visible')
cy.screenshot('article-ready', { capture: 'fullPage' })

Use selectors and assertions that reflect the application, rather than relying on a fixed delay as a general readiness check. If lower sections or images load only when scrolled into view, account for that behavior in the test and verify the resulting artifact. Cypress synchronizes with its renderer as best it can, but application state may change around capture; a screenshot represents the state reached by the test, not proof that every late-rendering detail appeared. The API documentation describes screenshot synchronization and limitations.

5. Prevent repeated sticky and fixed elements

Full-page mode scrolls and stitches captures. A position: fixed or position: sticky header can therefore appear more than once in the stitched image. Cypress documents temporarily changing a sticky header to position: absolute as a workaround:

cy.get('.sticky-header').invoke('css', 'position', 'absolute')
cy.screenshot('page-full', { capture: 'fullPage' })
cy.get('.sticky-header').invoke('css', 'position', null)

This is a targeted workaround, not a universal fix. Check that the temporary style does not change the page in a way that invalidates the screenshot. Restore the style after capture, and use a selector specific to the element you need to adjust. Cypress’s documented sticky-header example shows the same approach.

6. Name, locate, and retain screenshot files

A named manual screenshot is stored in the screenshots folder, relative to the spec path. A path in the screenshot name can create nested folders. The default folder is cypress/screenshots.

cy.screenshot('article/full-page', { capture: 'fullPage' })

Useful screenshot options include:

Option Purpose Practical note
capture Selects fullPage, viewport, or runner. Failure screenshots are coerced to runner.
clip Clips the final image to a specified rectangle. Use when you need a bounded output region; it does not change which page state is ready.
scale Controls screenshot scaling. Consult the API documentation for accepted values and effects.
overwrite Controls whether a screenshot with a duplicate name overwrites an existing file. Choose based on whether repeat runs should replace or preserve a named artifact.
blackout Blacks out matching selectors in supported captures. Applies to viewport captures and does not apply to runner captures; check documented behavior for your mode.
disableTimersAndAnimations Controls timer and CSS animation disabling during capture. Defaults to true.
onBeforeScreenshot / onAfterScreenshot Callbacks around screenshot capture. Use them only when the documented callback behavior fits the task.

Check the current command reference before depending on an option’s exact argument format. Cypress also warns that cy.screenshot() yields its subject, but it is unsafe to chain commands after it when those commands rely on that subject. Keep dependent assertions before the screenshot command.

7. Run captures reliably in CI

Manual cy.screenshot() calls run in both open and run modes. Automatic failure screenshots apply to cypress run. By default, before cypress run, Cypress clears the contents of the screenshots folder, including nested folders.

To preserve prior assets, Cypress provides trashAssetsBeforeRuns: false:

// cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  trashAssetsBeforeRuns: false,
})

This setting applies to assets in the configured screenshots, videos, and downloads folders. Consider those effects when changing it. For CI, make screenshot collection an explicit artifact step in the workflow, and ensure the job retains the screenshots directory after Cypress exits.

8. Troubleshoot common problems

Symptom Likely cause What to do
The screenshot shows only the visible area. The capture mode is viewport, or a wrapper/configuration changed the expected options. Pass { capture: 'fullPage' } explicitly and confirm you are invoking Cypress’s screenshot command.
The sticky header or floating control appears repeatedly. Full-page mode scrolls and stitches captures while fixed or sticky elements remain attached to the viewport. Try the documented temporary position: absolute change for the specific element, then verify the result.
Text, images, or lower page sections are missing. Capture happened before the application-specific content was ready, or content is lazy-loaded. Add assertions for the required content and loading state; account for scroll-triggered behavior. Timers and animation handling alone do not wait for all requests.
The page layout is at the wrong breakpoint. The viewport is not set to the dimensions the test intends to exercise. Set cy.viewport(width, height) before capture. Remember viewport sizing and full-page capture are separate controls.
The named screenshot cannot be found after a run. The output is under the configured screenshots folder, relative to the spec path, or the CI job did not retain the directory. Check cypress/screenshots, the configured folder, and the path implied by the spec and screenshot name; retain the folder as a CI artifact.
Old screenshots disappear after cypress run. Cypress clears the screenshots folder before a run by default. Set trashAssetsBeforeRuns: false if retaining previous files is required, accounting for its effects on screenshots, videos, and downloads.
A failure screenshot does not match the requested full-page mode. Cypress coerces failure screenshots to runner. Use a manual screenshot command after a successful readiness check when the required artifact is a full-page image.
A chained command behaves unexpectedly after capture. The screenshot command yields its subject, and Cypress marks chaining commands that rely on it as unsafe. Put assertions and subject-dependent actions before the screenshot.

9. Performance, reliability, and cost

A full-page screenshot must cover the page beyond the current viewport, so large or long pages can take more work to capture and produce larger image files than viewport-only captures. Cypress’s documented full-page process scrolls and stitches captures; avoid capturing a whole page when the test only needs a viewport or a smaller clipped region.

For reliable artifacts, make readiness checks specific, set the intended responsive viewport, and handle sticky elements only when they distort the output. Cypress documents no per-screenshot charge in the cited command documentation; any infrastructure or CI cost depends on how and where you run your test workflow. The dossier does not provide numeric timing or cost benchmarks, so measure your own suite if capture duration or artifact storage is a concern.

10. When visual regression is the real goal

A screenshot file is an artifact; visual regression testing adds baseline comparison, review, and approval workflows. Cypress lists integrations and services including Chromatic, Happo, LambdaTest SmartUI, Percy, Sauce Labs Visual, SmartBear VisualTest, and Wopee.io. Its integration overview says Happo supports full-page and component screenshots across browsers and screen sizes. These services are optional; they are not required to call cy.screenshot().

Compare services based on full-page versus component or region support, available browsers and viewport sizes, how teams review and approve visual differences, and fit with the existing Cypress tests. The source material does not establish current pricing or partner terms. See Cypress’s visual testing overview for the integrations it documents.

11. Or skip the browser setup

If you need a screenshot of a public page outside a Cypress test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns an image or PDF, and the ScreenshotNeo API documentation covers the available options.

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}`);
  • Cookie banners and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers report the page verdict and whether the request was billed.
  • An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000.

Create a free ScreenshotNeo account for 1,000 screenshots a month, with no card required.

12. FAQ

Does full-page mode change the app’s viewport?

No. The viewport controls the responsive layout; full-page mode selects the capture area.

Can Cypress take a full-page failure screenshot?

Failure screenshots are coerced to runner capture. Add a manual full-page screenshot after the page is ready when you need that artifact.

Do I need a visual testing service to save a full-page screenshot?

No. cy.screenshot() saves the image. A visual testing service is relevant when you also need baseline comparison and review.

Why is a full-page image so tall?

It includes the page from top to bottom rather than only the viewport. Use viewport capture or clipping if the complete page is not needed.