How to Handle Screenshot API Timeouts on Slow Websites
Diagnose which capture stage is timing out, choose the right readiness condition, and set a bounded timeout for slow websites.
A screenshot API timeout means the capture request exceeded a time limit before it could return an image. First identify whether navigation, page readiness, or the overall request is taking too long. Then choose the least expensive readiness condition that includes the content you need, and set a finite timeout within that provider’s documented limits. There is no universal timeout value: APIs use different units, defaults, limits, and parameter names.
A navigation timeout and a delay after navigation solve different problems. A timeout caps how long the browser waits for navigation or rendering; a post-load delay deliberately waits after a readiness condition has already been met. Increasing a timeout will not fix an unavailable page, access restriction, or a dependency that never settles.
1. Identify which part of the capture is timing out
Before changing settings, record the exact endpoint and parameters, response status or error, elapsed time, and whether failure occurs before or after navigation. These are useful troubleshooting details; providers do not all return the same diagnostic fields.
- Request stage: The request may be delayed by your own network, an overloaded client, or the provider’s queue. Check the provider’s response and job documentation.
- Navigation stage: The browser may not reach the configured navigation event before its timeout.
- Readiness stage: Navigation may finish, but a selector, network-idle condition, or other wait may never complete.
- Post-load delay: An explicit delay adds time after the readiness condition. It cannot make a stalled navigation complete.
- Rendering or response stage: The page may be ready while screenshot generation or transfer takes additional time. Check whether the provider’s timeout covers navigation alone or the whole request.
Compare timeout settings only after checking what they bound. A 30-second navigation limit and a 30-second whole-request limit do not describe the same wait.
2. Choose a readiness condition that matches the content
The right condition is the earliest signal at which the content you need is actually present. Waiting for more than that can add latency and expose the capture to unrelated requests.
| Condition | Use when | Trade-off |
|---|---|---|
domcontentloaded |
The parsed document and initial markup are enough. | May be too early for images, client-rendered data, or late UI. |
load |
The page’s load event is a meaningful signal for the content. | Can wait on resources that are not needed in the screenshot. |
networkidle / networkidle0 / networkidle2 |
A dynamic page needs time for background data and network activity to settle. | Can take longer or fail to settle on pages with polling, analytics, or persistent requests. |
| Specific selector | A known element indicates that the required content has appeared. | Fails if the selector is wrong, absent, or never inserted. |
For JavaScript-heavy pages and single-page applications, Cloudflare documents network-idle waits and selector waits. Its documentation notes that waiting for a specific element can be faster than waiting for all network activity to stop. ScreenshotAPI.net likewise documents domcontentloaded as a speed-oriented choice and networkidle for dynamic applications. These are provider-specific options; check the API you use.
3. Set a finite timeout within the provider’s limit
Check the current API reference for the parameter name, units, default, maximum, and what work the timeout covers. For example, Cloudflare Browser Run documents gotoOptions.timeout in milliseconds, with a maximum of 60,000 ms, and supports load, domcontentloaded, networkidle0, and networkidle2 as waitUntil values. ScreenshotAPI.net documents a default of 100,000 ms for its own timeout parameter. Those settings are not interchangeable and are not universal recommendations.
Use this sequence:
- Start with the default or a conservative finite value allowed by the API.
- Set the readiness condition to the earliest reliable signal for your required content.
- Measure elapsed time and inspect the returned error for representative slow pages.
- Raise the limit only when evidence shows the page needs more time and the provider permits it.
- Keep a caller-side deadline too, so your application does not wait indefinitely if the service stalls.
For an unspecified API, do not assume that increasing a number will help. Verify its timeout semantics, maximum, and error behavior in its own documentation.
4. Provider-specific examples
These examples illustrate the settings documented by the named providers. Replace credentials and target URL with your own values, and confirm current parameter syntax in the provider’s reference before deploying.
Cloudflare Browser Run: bounded navigation and readiness
Cloudflare’s screenshot reference accepts navigation settings under gotoOptions. The example uses domcontentloaded for a page where initial document structure is sufficient, and sets a finite 30-second timeout below the documented 60-second maximum. Adapt the body and authentication to the endpoint and account setup in Cloudflare’s documentation.
curl -X POST \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/browser-rendering/screenshot" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"url": "https://example.com",
"gotoOptions": {
"waitUntil": "domcontentloaded",
"timeout": 30000
}
}' \
--output screenshot.png
Use the API’s documented request shape for your account and screenshot options. If the screenshot needs a particular dynamic element, use the documented selector-wait option instead of assuming that network idle is always necessary. The 30-second value here is an example configuration, not a general recommendation.
ScreenshotAPI.net: select readiness and review its timeout setting
ScreenshotAPI.net documents a timeout parameter with a 100,000 ms default and separate wait behavior. The exact request URL and authentication depend on your account and current API reference; apply its documented parameter names rather than copying another provider’s syntax.
# Request structure only: use the endpoint and authentication from the provider docs.
curl -G "YOUR_SCREENSHOTAPI_NET_ENDPOINT" \
--data-urlencode "url=https://example.com" \
--data-urlencode "waitUntil=domcontentloaded" \
--data-urlencode "timeout=100000" \
-o screenshot.png
Choose networkidle instead when settling network activity is a useful proxy for the required content. The listed default belongs to ScreenshotAPI.net; check its documentation for accepted range, units, and current parameter syntax.
5. Troubleshoot a screenshot API timeout
| Symptom | Likely cause | What to do |
|---|---|---|
| Timeout happens at the same configured interval | The navigation or request limit is being reached. | Confirm units and scope, then use an earlier readiness condition or raise the limit only within the provider’s documented maximum. |
networkidle never finishes |
Polling, analytics, streaming, or another persistent request keeps activity alive. | Wait for a specific content selector if supported, or use an earlier condition and a short post-load delay only when justified. |
| Selector wait times out | The selector is incorrect, the element is conditional, or the page never renders it. | Inspect the target page and selector; confirm the element exists for the same locale, account state, and viewport. |
| Screenshot is returned but content is missing | The selected readiness event occurs before client-side content appears. | Wait for a content-specific selector or an appropriate later event. Verify that the selector marks the actual content, not merely a shell. |
| Raising the timeout changes nothing | The target may be unavailable, blocked by access controls, or stuck on a slow dependency. | Open the target independently, check access requirements and provider error details, and consult its retry documentation. |
| Request exceeds the documented maximum | The provider enforces a service-specific cap. | Stay within the documented limit and reduce unnecessary waiting; do not assume the API will honor a larger value. |
| Client reports timeout, but provider may still be working | The client deadline may be shorter than the provider’s processing time. | Check whether the provider supports asynchronous jobs or request-status lookup, and follow its documented semantics before retrying. |
Do not apply a universal retry schedule. A retry may repeat a slow or blocked request, and the reviewed provider documentation does not establish a shared retry policy. Follow the chosen API’s guidance and retry only errors it identifies as retryable.
6. Performance, reliability, and cost
- Performance: Use the earliest readiness signal that reliably includes the required content. Broad network-idle waits can make captures slower when irrelevant requests remain active.
- Reliability: A selector tied to the content you need can be more meaningful than general network quiet, but only if that selector is stable and present on every expected page state.
- Timeouts: A finite cap protects application workers and user-facing requests from waiting without a ceiling. Keep provider limits and your own caller deadline aligned.
- Cost: Billing rules vary by API. Check whether timed-out, failed, cached, or queued requests count as usage; the cited timeout documentation does not establish a common billing rule.
- Operations: Log provider, endpoint, readiness condition, configured limit, elapsed time, and outcome. This helps distinguish a consistently slow target from a bad selector or an API-side issue.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. Its capture flow accepts cookie and consent banners 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 the page verdict and billing status in headers. An MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs.
Use the same one-call request from cURL, Python, or Node.js below. See the ScreenshotNeo API documentation for parameters, timeout behavior, and response details.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
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)
Node.js
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, popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, and failed loads are never billed; the MCP server lets AI agents take screenshots; and 1,000 screenshots per month are free with no card, with paid plans starting at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.
8. Frequently asked questions
Should I always wait until the page is fully loaded?
No. “Fully loaded” may include resources unrelated to the screenshot. Select the earliest condition that reliably includes the content you need.
Does a post-load delay fix a navigation timeout?
No. A delay starts after its readiness condition is met. It cannot resolve a navigation that never reaches that condition.
How much should I increase a screenshot API timeout?
There is no universal value. Check the API’s units, scope, default, and maximum, then adjust based on measured target behavior within its documented limit.
When should I use a selector instead of network idle?
Use a selector when a specific element reliably indicates that the content is ready. Use network idle only when network settling is a useful signal for that page.
Will retrying a timeout make the screenshot succeed?
Not necessarily. A retry cannot fix a blocked target, missing selector, or persistent slow dependency. Check provider error and retry guidance first.


