ScreenshotNeo

BlogHow-to

How to screenshot a page with animations disabled in Playwright

Use Playwright’s `animations: 'disabled'` option for stable page and element screenshots. Learn what it changes, where it falls short, and how to troubleshoot visual differences.

By the ScreenshotNeo team4 October 20266 min read

To capture a Playwright page screenshot without CSS animations, CSS transitions, or Web Animations affecting the image, pass animations: 'disabled' to page.screenshot():

await page.screenshot({ path: 'page.png', animations: 'disabled' });

For one element, pass the same option to its locator screenshot call:

await page.locator('.target').screenshot({ path: 'element.png', animations: 'disabled' });

Playwright fast-forwards finite animations to completion and cancels infinite animations to their initial state for the capture; infinite animations resume afterward. This option does not freeze timers, video, canvas, changing data, or every other source of page movement. See the official Page API and Locator API for method details.

1. Choose the right screenshot API

API Use it for Animation setting
page.screenshot() Viewport or full scrollable page Pass animations: 'disabled' when you want effects stopped for capture.
locator.screenshot() A single matched element Set the option explicitly; locator screenshots allow animations by default.
expect(page).toHaveScreenshot() Visual assertions in Playwright Test Use the assertion options; it waits for two consecutive screenshots to match before comparing with the baseline.

toHaveScreenshot() is a Playwright Test assertion, not a general screenshot method available in every Playwright script. See the visual comparisons guide and PageAssertions API.

2. Capture a viewport or full page

The following is a complete Node.js example using Playwright’s library. Install the package and browser first, then save this as screenshot.js and run it with Node.js.

npm install playwright
npx playwright install chromium
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  try {
    await page.goto('https://example.com', { waitUntil: 'load' });
    await page.screenshot({
      path: 'page.png',
      animations: 'disabled',
      fullPage: true
    });
  } finally {
    await browser.close();
  }
})();

Remove fullPage: true to capture only the viewport. The animations option is independent of the capture scope. Full-page capture can cause the page to render additional content as the browser captures its scrollable area, so lazy-loaded content may need to be loaded deliberately before the screenshot.

3. Capture one element

Use a locator when the screenshot should contain a specific component rather than the whole page. Wait for it to be visible before capturing so a missing selector fails clearly instead of producing an unexpected result.

const card = page.locator('.product-card');
await card.waitFor({ state: 'visible' });
await card.screenshot({
  path: 'product-card.png',
  animations: 'disabled'
});

Locators are preferable to selecting an element once and retaining a potentially stale handle while the page changes. The official Locator API documents element screenshot options.

4. Use animation control in visual tests

For visual regression checks, use Playwright Test’s screenshot assertion. It waits for two consecutive screenshots to match before comparing the result against its stored baseline, which helps with transient rendering changes.

import { test, expect } from '@playwright/test';

test('product page visual baseline', async ({ page }) => {
  await page.goto('https://example.com/products/widget');
  await expect(page).toHaveScreenshot('product-page.png', {
    animations: 'disabled',
    fullPage: true
  });
});

Configure Playwright Test and install its browser in the project before running this test. The assertion is not interchangeable with page.screenshot(): one compares against a baseline, while the other simply writes an image file.

For dynamic regions that still change after animations are disabled, use a screenshot stylesheet where appropriate. Playwright’s visual comparison options support stylePath for applying styles during screenshot capture. A stylesheet can hide or neutralize volatile content, but it should preserve the layout and content that the test intends to verify. See Playwright’s visual comparisons guide.

5. Understand what “disabled” changes

  • CSS animations: stopped for the screenshot.
  • CSS transitions: finite transitions are fast-forwarded to completion. This can fire a transitionend event.
  • Web Animations: included in the animation handling.
  • Infinite animations: canceled to their initial state for capture, then played again after the screenshot.

Those behaviors are specific to animation effects. The option does not pause JavaScript timers, video playback, canvas drawing, network updates, clocks, randomized content, or other application state. If those affect the image, stabilize them separately—for example, configure deterministic test data, wait for the relevant content, or use a screenshot stylesheet for volatile regions.

6. Make captures repeatable

  1. Use the same browser engine and version as the baseline run.
  2. Keep viewport dimensions, device scale, locale, and relevant browser settings consistent.
  3. Wait for the page’s meaningful content and fonts to be ready before capture.
  4. Disable animations on the capture call.
  5. Stabilize any timers, data, video, canvas, or rotating content that remains dynamic.
  6. Use a screenshot stylesheet only for regions that should not affect the comparison.

Playwright notes that rendering can vary with host operating system, browser version, settings, hardware, power source, and headless mode. Animation control alone cannot make captures pixel-identical across different environments. For more, consult the visual comparisons documentation.

7. Troubleshooting

Symptom Likely cause Fix
The element screenshot still animates. The option was set on a page screenshot call, while the capture uses a locator. Pass animations: 'disabled' directly to locator.screenshot().
The result shows an unexpected final animation state. A finite animation was fast-forwarded to its completion state. Set the application into the intended test state before capture, or use a capture stylesheet to control the visual state.
A spinner or blinking cursor is still changing. It may be driven by a timer, video, canvas, or script rather than the animation types covered by this option. Pause or seed that source in the test, or hide the specific volatile element with a screenshot stylesheet.
The visual assertion fails across machines. Browser or host rendering differs from the baseline environment. Run the baseline and comparison in a consistent browser and host environment, and inspect whether the changed region is genuinely dynamic.
A full-page screenshot is missing lazy content. The page has not loaded or revealed content below the fold before capture. Scroll or otherwise trigger the page’s lazy-loading behavior, wait for content, then capture.
toHaveScreenshot is undefined or unavailable. The code is running outside Playwright Test or lacks its test assertion setup. Use page.screenshot() for a plain image, or run the assertion in a Playwright Test project.

8. Version, performance, reliability, and cost

Playwright release notes identify version 1.20 as adding the animations: 'disabled' screenshot option for page, locator, and element-handle methods; current API documentation continues to describe it. If maintaining an older project, check the installed version and upgrade if the option is unavailable. See the release notes.

Disabling animations is a screenshot-time control and does not require a separate capture service. Full-page images and visual assertions can take longer than a viewport image because they capture or compare more content. A visual assertion also waits for two matching consecutive captures. No benchmark is implied here; measure runtime on the pages and environments your project uses. For reliability, keep the browser environment and test data stable and make waits target meaningful page state rather than arbitrary delays.

9. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. For a straightforward URL capture, one GET request returns an image or PDF. See the ScreenshotNeo API documentation for parameters and 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,
)
r.raise_for_status()
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}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

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 step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify page verdict and billing status in headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. These are ScreenshotNeo service details; the animation behavior described earlier is specifically Playwright’s API behavior.

Sign up for 1,000 free screenshots a month, with no card required.

10. FAQ

Does disabling animations change the page permanently?

No. Infinite animations resume after the screenshot. Finite animations are fast-forwarded to completion as part of the capture behavior.

Can I use this option without Playwright Test?

Yes. Use it with page.screenshot() or locator.screenshot() from Playwright. Only toHaveScreenshot() requires the Playwright Test assertion environment.

Does this make screenshots identical on every machine?

No. Browser and host rendering can differ, and other dynamic page content may remain. Keep the environment consistent and stabilize remaining volatile content.