How to Add a Delay Before Browserless Captures a Screenshot
Add a fixed delay with Browserless’s `waitForTimeout` option, or wait for a selector or page condition when readiness matters more than elapsed time.
For Browserless’s current REST Screenshot API, add waitForTimeout to the top level of the JSON request and set it to the number of milliseconds to wait. For example, "waitForTimeout": 3000 pauses for three seconds before Browserless proceeds. Keep screenshot settings such as fullPage and type inside options; the delay is alongside url.
{
"url": "https://example.com/",
"waitForTimeout": 3000,
"options": {
"fullPage": true,
"type": "png"
}
}
This guide uses Browserless’s current REST Screenshot API. Its older BaaS v1 API uses a different waitFor option, and BrowserQL has its own mutation syntax, so check the endpoint and API generation before adapting examples.
1. Send a fixed delay in a REST screenshot request
Browserless accepts a POST request to /screenshot. Replace YOUR_API_TOKEN_HERE with your account token, and save the response to a file matching the requested image type.
curl -X POST \
"https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/",
"waitForTimeout": 3000,
"options": { "fullPage": true, "type": "png" }
}' \
--output screenshot.png
The timeout value is in milliseconds: 1,000 is one second, 3,000 is three seconds. Keep the token out of public source code and logs. Browserless documents the endpoint and request shape in its Screenshot API reference.
Python
This example uses the requests package. Install it with python -m pip install requests, then run the script:
import requests
endpoint = "https://production-sfo.browserless.io/screenshot"
params = {"token": "YOUR_API_TOKEN_HERE"}
payload = {
"url": "https://example.com/",
"waitForTimeout": 3000,
"options": {"fullPage": True, "type": "png"},
}
response = requests.post(endpoint, params=params, json=payload, timeout=90)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
Node.js
This uses the built-in fetch available in modern Node.js releases:
const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", "YOUR_API_TOKEN_HERE");
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://example.com/",
waitForTimeout: 3000,
options: { fullPage: true, type: "png" },
}),
signal: AbortSignal.timeout(90000),
});
if (!response.ok) {
throw new Error(`Browserless returned ${response.status}: ${await response.text()}`);
}
const image = Buffer.from(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) => writeFile("screenshot.png", image));
2. Choose a wait that matches the page
A fixed delay is useful when a known animation, transition, or time-based operation needs a short pause. It always consumes the full configured duration and does not prove that the page is ready. Browserless also documents readiness-based options in its request configuration.
| Need | Use | Behavior |
|---|---|---|
| Wait a known amount of time | waitForTimeout |
Pauses for the configured milliseconds. |
| Wait for a page element | waitForSelector |
Continues when the selector is present or visible as configured; it can fail if the selector does not become ready before its timeout. |
| Wait for a page-specific condition | waitForFunction |
Continues when the supplied browser-side condition becomes true. |
| Wait for a custom page event | waitForEvent |
Waits for a custom event emitted by the page; Browserless says this is not for lifecycle events such as load or DOMContentLoaded. |
Use a condition when the page exposes a reliable readiness signal. For example, a product page might render a price element only after its data arrives. A fixed pause can be too short on a slow run and waste time on a fast one; that follows from the difference between elapsed-time and condition-based waits.
3. Budget the overall timeout
The overall REST request timeout is set with the timeout query parameter, also in milliseconds. It must leave enough time for navigation, the intentional delay or readiness wait, and screenshot generation. If the total request reaches its ceiling first, the screenshot will not complete. See Browserless’s timeout configuration for the available timeout controls and error handling guidance.
When choosing values, account for:
- How long the page may take to navigate and load.
- The maximum fixed delay or selector/function wait you expect.
- The time required to generate the requested screenshot, especially for a full-page capture.
- Client-side limits in your HTTP library or job runner, which should not expire before the Browserless request can finish.
There is no universal safe timeout: use the narrowest wait that reflects the page’s actual readiness and leave a reasonable overall request budget for slower responses.
4. Check the API generation before copying a wait option
The current REST Screenshot API uses the shared request configuration field waitForTimeout. The legacy /screenshot BaaS v1 page documents waitFor, which can accept a numeric delay, a CSS selector, or a function. BrowserQL is a separate API: its waitForTimeout mutation takes a time argument in milliseconds in the query sequence. These request shapes are not interchangeable.
5. Troubleshoot common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| The screenshot starts without the intended pause | The delay is nested under options, misspelled, or sent to a different API generation. |
For current REST requests, put numeric waitForTimeout beside url. Confirm the endpoint and schema. |
| The delay is far longer or shorter than expected | The value was treated as seconds rather than milliseconds. | Convert seconds to milliseconds: multiply by 1,000. Three seconds is 3000. |
| The request times out during the wait | The overall request timeout does not cover navigation, waiting, and capture. | Raise the overall timeout query parameter and client timeout as appropriate, or use a shorter/readiness-based wait. |
| A selector wait fails even though the page eventually shows the element | The selector readiness deadline is too short, the selector does not match the rendered DOM, or the target is inside a frame/shadow tree the selector does not reach. | Check the actual selector and page structure, then adjust the selector timeout or use a page-specific condition that matches the target’s rendering behavior. |
| The page is still incomplete after the fixed delay | Elapsed time did not correspond to application readiness, perhaps because data or images load variably. | Wait for a meaningful selector or function condition rather than guessing a longer constant delay. |
| The response is not a PNG image | The requested type and output filename do not match, or the API returned an error response. | Check HTTP status and response body before writing it; make options.type and the output extension agree. |
6. Performance, reliability, and cost considerations
A fixed delay adds its full duration to each capture even when a page is ready sooner. Under concurrent or bulk capture, this can keep browser sessions occupied longer. Readiness conditions can avoid needless waiting, while still needing sensible timeouts for pages that never become ready. The dossier provides no benchmark or pricing data for Browserless, so compare its current plan and usage terms directly before estimating cost.
For reliability, handle non-success HTTP responses, set an overall timeout, keep credentials private, and record which wait condition was used when diagnosing incomplete captures. Avoid an unbounded wait: a missing selector or page event can otherwise hold the request until the overall ceiling.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its one-call API captures a URL as PNG, JPEG, WebP, or PDF, and the API documentation describes 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}`);
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, blank pages, failed loads, timeouts, and cache hits are never billed, and response headers report the page verdict and billing status. Its MCP server gives Claude, Cursor, and other MCP clients screenshot, page-info, and PDF tools. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
FAQ
Does waitForTimeout guarantee that a page has finished loading?
No. It waits for elapsed time. Use a selector, function, or custom event when the page provides a dependable readiness signal.
Can the delay be a decimal?
The documentation describes the value in milliseconds. Use a numeric millisecond value; for clarity, express fractional seconds as the corresponding millisecond count.
Should I always add a delay?
No. Add one only when the page needs additional time after navigation or when its behavior requires it. A readiness condition is usually more precise when one is available.
Where can I verify the exact request schema?
Use the Browserless documentation for the specific API generation and endpoint you call; REST, legacy BaaS v1, and BrowserQL use distinct request shapes.


