Browserless Screenshot Times Out on Slow Websites: How to Fix It
Diagnose which Browserless timeout is expiring, choose a page readiness condition, and fix slow captures without waiting blindly.
A Browserless screenshot timeout can expire while the REST request is running, while the page is navigating, while a selector or function is being awaited, or during the screenshot operation. First identify which stage failed. Then adjust that stage’s timeout and wait for the condition your capture actually needs. Increasing every timeout indiscriminately can make failures slower to detect without fixing a CAPTCHA, access-denied response, blank page, or expensive full-page capture.
Browserless documents the query parameter timeout as the budget for the entire REST operation, including waits. Navigation has its own gotoOptions.timeout; selector, function, and event waits have their own timing; BQL screenshot options have a screenshot timeout. The whole-request budget must leave room for navigation, readiness waits, and capture. Browserless does not establish one maximum that applies to all routes, deployments, and accounts, so check the live documentation for your endpoint and account.
1. Identify which timeout expired
| Layer | What it limits | What to inspect |
|---|---|---|
REST request timeout |
The complete operation, including waits | Query parameter and total elapsed request time |
Navigation gotoOptions.timeout |
Page navigation | Navigation settings and the selected waitUntil event |
| Readiness wait | A selector, function, or event condition | The awaited selector or condition; confirm it exists on the target page |
| Screenshot operation | The capture itself | Screenshot options, full-page mode, image waiting, and screenshot timeout |
Use the error context and request configuration to locate the expiring stage. A whole-request timeout can mask which inner operation was slow because it includes all of them. Browserless also notes that an HTTP 200 from its API does not necessarily mean the target website returned a successful status.
2. Choose a navigation condition that fits the page
The navigation completion event determines what Browserless waits for before moving on. Choose based on the content the screenshot needs:
waitUntil |
Waits for | Useful when | Watch out for |
|---|---|---|---|
domcontentloaded |
Initial HTML parsing to finish | The needed content appears early and remaining resources are not important | Images, styles, or client-side content may still be loading |
load |
The load event after dependent resources finish loading | The capture needs the page’s usual loaded resources | Slow resources can delay the event |
networkidle0 |
No network connections for at least 500 ms | The page becomes quiet and that is a useful readiness signal | Long polling or persistent background requests can prevent idleness |
networkidle2 |
No more than two network connections for at least 500 ms | Some background connections remain open | It still may not signal that the specific content you need is ready |
If a site keeps connections open, an idle condition can time out even though the desired content is already visible. In that case, use a specific selector or application condition. Prefer the narrowest condition that reliably represents the content in your screenshot.
3. Wait for the content you need
A condition-based wait usually gives a more reliable capture than guessing a fixed delay. Browserless supports waiting for a selector, optionally requiring visibility, or waiting for a page function to become true. A fixed delay is available when time itself matters, such as allowing an animation to finish; it always consumes that delay even if the page becomes ready sooner.
Example Browserless REST configuration (JavaScript object illustrating the documented options; use it in the request body format required by your Browserless screenshot route):
const options = {
gotoOptions: {
timeout: 45000,
waitUntil: "domcontentloaded"
},
waitForSelector: {
selector: "main article",
options: {
visible: true,
timeout: 20000
}
},
screenshot: {
fullPage: false,
waitForImages: false
}
};
These values are an example budget, not a Browserless recommendation or a guarantee that a particular target will finish in that time. Keep the total request timeout higher than the time you allocate to navigation plus readiness and capture. Check the current endpoint documentation for the exact request schema: Browserless offers different routes and request forms.
4. Set a deliberate total time budget
Browserless’s timeout guide advises using realistic timeout values: a low budget may fail on slow content, while an unnecessarily high budget delays error detection. Budget for each stage and leave enough overall time for all of them. For example, if navigation may take 45 seconds and the selector may take another 20 seconds, the request-level budget must exceed their combined time plus capture and overhead.
Browserless states that “The query parameter timeout applies to the entire request, including all wait operations.” Treat the query parameter as the outer deadline, not a replacement for navigation or wait configuration. Monitor total request time in your own workflow and handle timeout errors explicitly.
5. Use bestAttempt only for acceptable partial captures
Browserless documents bestAttempt: true as a way to proceed after some awaited events time out, returning the page state available at that point. This can be useful when a partial result has value. It does not mean that the required content loaded: inspect the screenshot or validate the expected content before using the result.
6. Check for blocking and expensive capture work
A longer timeout will not necessarily fix a CAPTCHA, blank or white page, access-denied or 403 response, or a missing element. Browserless documents these as signs that automation may be blocked or the target response may not be what the workflow expects. Check the page result and target response before changing timeout values again.
Capture options can also add work:
fullPagecaptures beyond the initial viewport and can require more rendering and image work. Turn it off if the desired output is only the visible viewport.waitForImageswaits for images to load. Enable it only when all images are required; otherwise it can hold up a capture on slow or broken image resources.- Browserless shared configuration supports rejecting resources or request patterns. Block only resources confirmed to be unnecessary for the visual result. Blocking stylesheets, fonts, or scripts the page needs can make the screenshot inaccurate.
For BQL, Browserless documents a default screenshot.timeout of 30 seconds (30,000 ms). This is the documented default for that screenshot operation, not a universal maximum for the full REST request or every deployment. Check the current BQL and route documentation before relying on a setting or ceiling.
7. Troubleshooting checklist
| Symptom | Likely cause | Next step |
|---|---|---|
| The whole API request times out | The outer timeout budget is shorter than navigation, waits, and capture combined |
Measure the stages, then set a realistic request budget with room for each stage |
| Navigation times out but the request budget remains | The navigation event takes too long, or the chosen event never occurs | Adjust gotoOptions.timeout; choose a more appropriate waitUntil condition |
| Selector wait times out | The selector is wrong, absent, hidden, or never rendered | Confirm the selector on the target page; use visibility only when visible content is required |
networkidle0 never completes |
Persistent requests or long polling keep the network active | Use a meaningful selector or function condition, or consider networkidle2 if it fits the page |
| Screenshot operation times out | Capture work is too large or the screenshot-specific budget is too low | Check screenshot timeout settings; disable unneeded full-page or image waiting options |
| Screenshot is blank or white | The site may be blocked, failed to render, or returned a page without the expected content | Inspect the target result and browser output; diagnose blocking rather than only extending the timeout |
| CAPTCHA, 403, or access denied | The target may be blocking automation or rejecting the request | Confirm the target response and whether access is permitted; more waiting does not resolve an access restriction |
| API reports success but screenshot content is wrong | API HTTP status does not establish that the target returned a successful page | Validate the captured page or expected content independently |
| Capture is slow after the page appears ready | Full-page rendering, image waits, or unnecessary resources add work | Capture only the required area and wait only for resources needed in the output |
8. Reliable production handling
- Log the endpoint, target URL, timeout settings, selected navigation condition, and which readiness wait was used.
- Separate navigation failures from selector/function wait failures and screenshot failures in error handling; changing the correct layer is easier when the stage is visible.
- Validate the result for expected content. A returned image or successful API status alone does not prove the target page loaded correctly.
- Use
bestAttemptonly when a partial page is acceptable and downstream checks can reject incomplete captures. - Set an overall deadline appropriate to your application. Very high timeouts tie up workers and delay failure reporting; overly low values reject legitimate slow pages.
- Use resource rejection conservatively and verify that removed resources do not alter layout or hide the content you need.
Or skip the browser setup
If you need screenshots without configuring browser waits and capture plumbing, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for parameters.
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 like a visitor and removed before the shot, along with 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status.
- An MCP server lets AI agents use
take_screenshot,get_page_info, andcapture_pdf. - The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan.
Sign up free for 1,000 screenshots a month, with no card required.
Frequently asked questions
Is Browserless’s 30-second screenshot timeout the limit for every request?
No. The documented 30-second default applies to the BQL screenshot operation. It does not establish a universal limit for the full REST request, every route, or every deployment.
Should I always use network idle for screenshots?
No. Network-idle conditions can be unsuitable for pages with persistent background requests. Use an application-specific condition when it better signals that the needed content is ready.
Does bestAttempt guarantee a complete screenshot?
No. It allows continuation after some awaited events time out. Check whether the returned page state contains the content your workflow requires.


