Skip to main content
AI agents are now live in Website Scanner! Enter your URL and fix website issues 3x faster with AI. Explore now!
No Result Found
Get your setup working faster. Join our Discord for optimisation tips from elite testers. Join our DiscordJoin our Discord

Percy readiness gate for page load

Prevent snapshots from capturing loading spinners, skeleton screens, or missing images by configuring Percy to wait for your page to finish loading.

Percy captures your page’s DOM at a specific point in time and compares the rendered snapshot with the baseline. Pages often load content in stages. APIs return data, images and web fonts download, and JavaScript updates the layout after the page first appears. If the capture happens before this finishes, the snapshot contains incomplete content, and you see visual diffs that don’t result from your code changes.

Use this guidance if your Percy builds show any of the following:

  • Loading spinners, skeleton screens, or placeholder content in snapshots.
  • Missing images or text rendered in a fallback font.
  • Partially rendered charts, tables, or other dynamic content.
  • Different diffs across builds, even when the page hasn’t changed.
  • A recommendation on the Percy build page to adjust readiness settings.

To prevent these issues, Percy provides a feature called the readiness gate. The readiness gate makes Percy wait until your page stops changing before it captures a snapshot.

The readiness gate requires Percy CLI v1.32.5 or later. We recommend that you use the latest version.

How the readiness gate works

Before each snapshot, Percy waits for the following conditions:

  • The page layout stops changing.
  • Network activity goes quiet.
  • Web fonts and visible images finish loading.
  • Page scripts go idle.

By default, Percy waits up to 10 seconds. If the page isn’t ready by then, Percy captures it as is and the build continues. To change this limit, choose a different preset or set timeout-ms.

Some Percy SDKs run the readiness gate by default. Others, and the percy snapshot command, run it only after you configure it. To make sure the readiness gate runs, add a readiness block to your .percy.yml file.

Configure the readiness gate

You configure the readiness gate in the readiness block of your .percy.yml file. Settings in this file apply to every snapshot. To use different settings for specific snapshots, see Override settings for a single snapshot.

Start by choosing a preset. If snapshots still capture incomplete content, tell Percy which elements to wait for. Customize a preset only when none of them fits your page.

Choose a preset

A preset is a ready-made combination of readiness settings. It controls how long the page must stay unchanged and how long Percy waits in total.

The following table describes each preset:

Preset Page must stay unchanged for Maximum wait Use when
balanced 300 ms 10 seconds Most pages. This is the default preset.
strict 1000 ms 30 seconds Pages with long animations, charts, or content that loads in several stages.
fast 100 ms 5 seconds Static or lightweight pages where build speed matters more than waiting. This preset doesn’t wait for images.
disabled N/A N/A Pages where your test code already waits for loading to finish.

Percy uses the balanced preset by default. To choose a different preset, set preset in your .percy.yml file:

Yaml
Copy icon Copy

To turn off the readiness gate, set preset to disabled. Use this when your test code already waits for the page to load.

Wait for specific elements

A preset waits for the page as a whole to settle. Some pages look settled while they still show a loading state, such as a spinner that stays on screen while data loads. For these pages, tell Percy which elements show that loading has finished:

  • ready-selectors: Percy waits until every listed element appears on the page and is visible. Use it for an element that appears only after loading finishes. An element hidden with display: none, or inside a hidden parent, doesn’t count as visible.
  • not-present-selectors: Percy waits until none of the listed elements exist on the page. Use it for spinners, skeleton screens, and loading overlays. Percy checks whether the element exists, not whether it’s visible. If your app hides a spinner with display: none but leaves it on the page, Percy waits for the full timeout on every snapshot. Use a selector that matches only the visible state, such as .spinner.is-active.

Both options accept CSS selectors and XPath expressions, and you can mix both in one list. Percy treats a selector as XPath only when it starts with /, //, ./, (/, or (./. Percy treats any other selector as CSS. For example, id('root') runs as CSS and never matches. To set the type explicitly, use an object such as css: "#header" or xpath: "//main" as the list item.

Yaml
Copy icon Copy

Customize a preset

If no preset fits your page, change the individual values that a preset sets, such as the maximum wait time. Any value you set replaces the matching value from your preset, and the preset supplies the rest. To skip one condition, set it to false. For example, set dom-stability: false for pages with live data or continuous animations, where the layout never stops changing.

Use kebab-case keys, such as timeout-ms, in .percy.yml. Use camelCase keys, such as timeoutMs, in your test code in every language, including Python, Ruby, and .NET. In Selenium SDKs, use timeoutMs so that the SDK raises the driver’s script timeout to match. The following table lists all settings:

.percy.yml key Test code option Description
preset preset The preset to start from: balanced, strict, fast, or disabled. Default: balanced.
timeout-ms timeoutMs The maximum time, in milliseconds, that Percy waits before it captures the snapshot anyway. Range: 1000 to 60000.
max-timeout-ms maxTimeoutMs An upper limit on timeout-ms. Set it to keep the wait under your test driver’s script timeout. Range: 1000 to 60000.
stability-window-ms stabilityWindowMs How long, in milliseconds, the page layout must stay unchanged. Range: 50 to 30000.
network-idle-window-ms networkIdleWindowMs How long, in milliseconds, the page must go without a new network request. Range: 50 to 10000.
js-idle-window-ms jsIdleWindowMs How long, in milliseconds, page scripts must stay idle. Range: 50 to 30000.
dom-stability domStability Set to false to stop waiting for the layout to stop changing.
image-ready imageReady Set to false to stop waiting for visible images.
font-ready fontReady Set to false to stop waiting for web fonts.
js-idle jsIdle Set to false to stop waiting for page scripts to go idle.
ready-selectors readySelectors A list of CSS or XPath selectors. Percy waits until every matching element appears and is visible.
not-present-selectors notPresentSelectors A list of CSS or XPath selectors. Percy waits until no matching element exists.

Override settings for a single snapshot

Settings in .percy.yml apply to every snapshot in your build. Some pages need different settings, such as a dashboard that loads more slowly than the rest of your app.

For these pages, pass a readiness object in the snapshot options in your test code. You can use any setting from the previous sections. These settings apply to that snapshot only:

// Playwright
await percySnapshot(page, 'Dashboard', {
  readiness: {
    preset: 'strict',
    readySelectors: ['#chart[data-rendered="true"]'],
    notPresentSelectors: ['.loading-overlay']
  }
});

Percy combines the two configurations one setting at a time. Each setting you pass for a snapshot replaces the same setting from .percy.yml, and all other settings come from .percy.yml. This has the following effects:

  • A selector list you pass for a snapshot replaces the list in .percy.yml. It doesn’t add to it. To keep the selectors from .percy.yml, include them in the snapshot’s list too.
  • If .percy.yml sets preset to disabled, the readiness gate stays off for every snapshot, even one where you change other settings. To turn the gate on for one snapshot, set preset in that snapshot’s options.

Troubleshoot readiness issues

To see readiness logs, including which conditions timed out, run Percy with the --verbose flag. The following table lists common issues and fixes:

Issue Fix
Snapshots still show a loading state Add the loading element, such as .skeleton or .spinner, to not-present-selectors. Or add an element that appears only after loading to ready-selectors.
Snapshots take too long Switch to the fast preset, or lower timeout-ms. If a page never settles, Percy waits for the full timeout on every snapshot.
Readiness times out on pages that update constantly Set dom-stability: false for pages with live data, tickers, or continuous animations. The other conditions still apply.
Every snapshot waits for the full timeout when you use not-present-selectors Your app hides the loading element but leaves it on the page. Percy checks whether the element exists, not whether it’s visible. Use a selector that matches only the visible state, such as .spinner.is-active.
A selector never matches Check that XPath selectors start with /, //, ./, (/, or (./. Percy runs any other selector as CSS.
A selector in ready-selectors never passes Check that the element is visible. Elements hidden with display: none or inside a hidden parent don’t pass.
Tests hang when the page uses fake timers Set preset to disabled for tests that pause or fake timers, such as Playwright page.clock or Jest and Sinon fake timers.
Selenium script timeout errors Set timeoutMs in your snapshot options, not timeout_ms. With timeoutMs, the SDK raises the driver’s script timeout to match. Or set max-timeout-ms below your driver’s script timeout.

For other snapshot issues, see Troubleshoot common issues.

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback

Is this page helping you?

Yes
No

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback!

Talk to an Expert
Download Copy Check Circle