How to Fix Percy Timeout Errors on Slow-Loading Pages
Diagnose Percy page-load, network-idle, and readiness failures on slow pages, then apply the fix that matches the evidence.
Percy timeout errors have different causes, so start with the exact failure label. A page-load timeout means Percy could not finish loading the page; a network-idle timeout means requests did not become quiet within the discovery window; and a readiness problem means the page may load but the snapshot is taken before the relevant UI appears. Match the fix to the failing stage instead of increasing every timeout.
Percy documents a page remaining in the loading state for more than 30 seconds during asset discovery as a page timeout. Its troubleshooting guidance suggests checking network logs, considering a larger PERCY_PAGE_LOAD_TIMEOUT (with 60000 milliseconds as an example), and evaluating the resources available to the Percy CLI. That example is not a guarantee or the right value for every project or SDK version. Percy page-timeout guidance.
1. Identify which timeout you have
| What you see | What it points to | First check |
|---|---|---|
| Page timeout, page loading failed, or page remains loading | Navigation or asset discovery did not complete | Can the Percy environment reach the URL? Which requests are slow or failing? |
| Network-idle timeout | Requests did not reach the expected quiet period | Are analytics, polling, streaming, or other requests still pending? |
| Snapshot succeeds but a late element is missing | Capture started before the UI was ready | Wait for a stable selector or, if necessary, a known delay. |
| Blank or stuck-loading capture | Possibly page JavaScript or application readiness behavior | Check the SDK’s JavaScript setting and the app’s own ready state. |
Percy treats page-load failures and network-idle failures as distinct failure types. A readiness wait can help with a late-rendered element, but it cannot make an unreachable URL load or settle a request that never finishes. See Percy troubleshooting and the CLI configuration reference.
2. Check reachability and authentication
- Open the exact URL from the environment where the Percy CLI runs, including the same hostname, path, and query parameters.
- Check whether the page requires a session cookie, basic authorization, or another access mechanism. Configure it for the capture environment; a URL that works in your local logged-in browser may still be inaccessible to Percy.
- Confirm the route does not redirect to a login page, access-denied screen, or a different host that the capture environment cannot reach.
- Look at the Percy failure label and network evidence before changing timing settings. A failed page load calls for reachability or authentication work, not a longer wait for a selector.
3. Inspect slow and pending requests
Use Percy network logs to find slow or failed assets. Percy specifically calls out SVG and video content as asset types that can take longer to resolve. Also inspect third-party trackers, analytics, polling, and other requests that may keep the page active. The page-timeout guide and network-idle troubleshooting describe these separate paths.
- If one large asset is slowing discovery, optimize or defer it where practical.
- If a particular asset is not needed in the visual snapshot and can safely be omitted, consider a DOM transformation to remove it from the rendered DOM.
- If the issue is a request that never settles, determine whether it is essential to the screenshot. Address the request behavior or tune the network-idle setting for that specific condition.
Do not remove assets indiscriminately: the page may render differently from what users see, or a required visual element may disappear.
4. Wait for the page state the snapshot needs
When navigation finishes but an application renders content asynchronously, wait for a stable completion element. Prefer a semantic selector that means the page is ready over a fixed sleep. Percy documents waitForSelector and waitForTimeout as readiness controls; their exact syntax depends on the SDK or CLI integration in use. Consult the CLI snapshot documentation and Percy core package documentation for the installed version.
// Illustrative readiness pattern; adapt to the Percy SDK/API in your project.
await page.waitForSelector('[data-testid="results-ready"]');
await percySnapshot(page, 'Search results');
If there is no reliable selector and the render delay is understood, a fixed delay can be used as a fallback:
// Illustrative fixed-delay pattern; confirm the supported option in your SDK.
await page.waitForTimeout(2000);
await percySnapshot(page, 'Search results');
These snippets express the browser automation pattern; they are not a drop-in Percy API contract for every integration. Verify the argument shape and supported methods for your Percy package version. A delay that is too short remains flaky; one that is too long wastes CI time.
5. Handle lazy-loaded content
If content appears only after scrolling, bring it into view or load it before taking the snapshot. Percy troubleshooting guidance suggests scrolling to the bottom for pages that use lazy loading. A practical sequence is:
- Navigate to the target page.
- Scroll through the page far enough to trigger the lazy content the snapshot should include.
- Wait for the expected content using a stable selector.
- Capture only after the content is present.
Scrolling can also trigger more network requests, so re-check the network evidence if doing so introduces or exposes a network-idle timeout.
6. Tune only the diagnosed timeout
For a page-load timeout
Percy’s guide suggests increasing PERCY_PAGE_LOAD_TIMEOUT; its example uses 60000 milliseconds. Set it in the environment that launches Percy, then rerun the affected case. Also check whether the CI worker has enough CPU and memory and whether reducing capture concurrency or increasing CI resources changes the failure. Apply a larger value deliberately: a higher limit can make a genuinely stuck page take longer to fail.
# Example for a shell-based CI step; confirm support in your installed Percy version.
PERCY_PAGE_LOAD_TIMEOUT=60000 npx percy exec -- npm test
For a network-idle timeout
Inspect the requests that prevent the page from becoming quiet, then adjust the relevant network-idle setting if the page’s normal behavior requires it. Percy configuration documents network-idle-timeout in relation to the duration with zero network requests. Do not change page-load timeout when the evidence points to pending requests, and do not treat a longer network-idle period as a fix for a page Percy cannot reach.
For a readiness issue
Wait for the page-specific selector or use a measured delay only when no stable readiness signal exists. Do not increase global navigation timeouts to compensate for capturing the UI too early.
7. Investigate blank or loading captures
When a page is blank or stuck loading and enable-javascript: true is configured, Percy troubleshooting suggests trying enable-javascript: false. Check the syntax for your SDK or configuration format, because option names and support can differ. Also verify that the application has reached its ready state before the snapshot call. Use this change only as a diagnostic or a suitable configuration for the page; disabling JavaScript can change the rendered result.
8. Use debug output and compare the result
- Enable Percy CLI debug output for asset discovery using the flag or configuration supported by your installed version.
- Reproduce the failing URL and inspect the failure label and network evidence.
- Change one relevant factor: reachability, a slow asset, readiness, page-load timeout, network-idle timeout, or CI capacity.
- Rerun the same case and compare its failure stage and logs. If the label changes, diagnose the new stage rather than repeating the old fix.
CLI options can change by release. Check the Percy CLI documentation and your installed package’s help output rather than copying a flag from a different version.
9. Common fixes at a glance
| Symptom | Likely cause | Action |
|---|---|---|
| Page timeout around asset discovery | Slow asset, inaccessible page, or constrained CI worker | Verify access, inspect network logs, consider the documented page-load timeout setting, and review CI resources. |
| Network idle never occurs | Persistent, pending, or repeatedly initiated requests | Identify the requests and adjust the network-idle behavior only if justified. |
| Late content absent from snapshot | Snapshot taken before asynchronous UI completion | Wait for a stable selector; use a fixed delay only when needed. |
| Lazy content missing | Content was never brought into view or loaded | Scroll to trigger loading, then wait for the content. |
| Protected page fails in capture | Missing authentication or session state | Make the URL reachable and supply required credentials or cookies. |
| Blank or stuck page | JavaScript/configuration behavior or app not ready | Check readiness and test the documented JavaScript setting with the correct SDK syntax. |
| Intermittent failures under CI load | Resource pressure or too much concurrent work | Inspect CI capacity and compare with lower concurrency or more resources. |
10. Or skip the browser setup
If you need a clean screenshot without maintaining a browser capture flow, ScreenshotNeo accepts one GET request for a URL and returns an image or PDF. The ScreenshotNeo API documentation covers its request 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 are accepted before capture, and 60+ known consent platforms, newsletter popups, and chat widgets are removed; each step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers identify the page verdict and billing status.
- An MCP server lets AI agents, including Claude, Cursor, and other MCP clients, take screenshots.
- The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Every feature is on every plan.
See ScreenshotNeo and the API docs. Create a free account for 1,000 screenshots a month, with no card required.
Performance, reliability, and cost considerations
- Performance: A selector wait usually spends time only until the required UI exists; a fixed delay always spends its full duration. Longer page-load or network-idle limits can extend CI jobs, especially when failures are real hangs.
- Reliability: Diagnose using the same URL and environment as the failing run. A selector tied to a stable page state is usually a better readiness signal than a guessed sleep. Re-check logs after each change because a fix can reveal a different failing stage.
- CI cost: More worker resources or lower concurrency may help when the capture environment is constrained, but may increase CI resource use or wall-clock time. A timeout increase alone does not make a slow asset faster.
- Version compatibility: Percy CLI and package flags can vary. Confirm environment variables, debug options, and wait APIs against the version actually installed.
FAQ
Is every Percy timeout a page-load problem?
No. Page-load, network-idle, and capture-readiness failures indicate different stages. Use the reported label and logs to choose the remedy.
Should I always set the timeout to 60 seconds?
No. Percy documents 60,000 milliseconds as an example for page-load timeout troubleshooting. Choose a value based on the failing page and the installed version.
Will waiting for a selector fix a network-idle timeout?
Not by itself. It can control when capture begins, while network idle concerns whether requests have become quiet.
Can I remove a slow asset?
Consider a DOM transformation only when the asset is unnecessary for the snapshot and removing it will not misrepresent the page.


