How to Set a Delay before Taking a Website Screenshot with Puppeteer
Add an awaited JavaScript timer before Puppeteer’s screenshot call, or wait for a page condition when you need a more reliable signal that content is ready.
To delay a Puppeteer screenshot, await a JavaScript timer immediately before calling page.screenshot():
await new Promise(resolve => setTimeout(resolve, 2_000));
await page.screenshot({ path: 'screenshot.png' });
The duration is in milliseconds, so 2_000 means two seconds. The timer belongs in your Node.js script; Puppeteer’s documented screenshot options do not include a delay setting. A fixed delay is useful when you know a visual change needs extra time. If you can identify the page state you need, waiting for that condition is usually more dependable.
1. Add a fixed delay before capture
Here is a complete runnable example using Puppeteer. It opens a page, waits two seconds, and writes a screenshot to the current directory:
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
// Wait 2,000 milliseconds (2 seconds) before capturing.
await new Promise(resolve => setTimeout(resolve, 2_000));
await page.screenshot({ path: 'screenshot.png' });
} finally {
await browser.close();
}
}
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
Save it as screenshot.js and run it in a Node.js project with Puppeteer installed. The timer must be awaited: without await, execution can reach the screenshot call before the delay finishes. Puppeteer’s screenshot guide and Page.screenshot() API document capturing the page.
Choose a sensible duration
Use the shortest duration that covers the known delay you need to accommodate. A longer sleep always adds that full time, even when the page is ready earlier. A timer also does not guarantee that an image, client-rendered widget, or animation has reached the exact state you want.
2. Choose the right wait for the page state
Navigation completion, network quiet, a particular element appearing, and an animation finishing are different readiness conditions. Match the wait to what should be visible in the screenshot.
| Wait strategy | Use it when | Trade-off |
|---|---|---|
| Fixed timer | You know a timed visual change needs a little more time. | Always waits the full duration, even if the page is ready sooner; does not prove readiness. |
| Network idle | You want navigation to wait for a period of network quiet. | Network quiet does not prove a particular widget or animation is finished. |
| Selector or page condition | A specific element or observable state means the content is ready. | The condition must accurately represent the state you need. |
Puppeteer’s Page API documents waitForFunction() and waitForNetworkIdle(). Its page interactions guide covers locator-based waits and waitForSelector.
Wait for a selector
If the page displays a report-ready marker when its content is available, wait for it directly:
await page.goto('https://example.com/report');
await page.waitForSelector('.report-ready', { visible: true });
await page.screenshot({ path: 'report.png' });
Replace .report-ready with a selector that is specific to the page and signals the content you want. If the element exists before its contents finish updating, wait for a more meaningful condition instead.
Wait for a page condition
For state that can be expressed in the page, use waitForFunction(). This example waits until a page-owned readiness flag becomes true:
await page.goto('https://example.com/report');
await page.waitForFunction(() => window.reportReady === true);
await page.screenshot({ path: 'report.png' });
The predicate must be meaningful for the site you are capturing. For example, if you control the page, expose a flag only after the data and layout needed for the screenshot are ready.
Wait for network idle during navigation
You can ask navigation to wait for network activity to quiet down:
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'screenshot.png' });
Puppeteer’s screenshot guide demonstrates networkidle2 for navigation. It can help with initial loading, but it does not guarantee every client-rendered widget, delayed update, or animation has finished. Add a condition or a deliberate timer when your target state needs one.
3. Capture a full-page screenshot after waiting
Wait first, then set fullPage: true on the screenshot call to capture the full page:
await page.goto('https://example.com');
await new Promise(resolve => setTimeout(resolve, 2_000));
await page.screenshot({ path: 'full-page.png', fullPage: true });
The wait sequence is the same as for a viewport screenshot. fullPage is a screenshot option; the delay remains a separate step in your script. See Puppeteer’s ScreenshotOptions reference for documented screenshot settings.
4. Configure waits and screenshot options
Keep timing and capture configuration separate so it is clear what controls page readiness and what controls the output.
- Timer duration: The value passed to
setTimeoutis milliseconds. Await its promise before capture. - Wait timeout: Applicable Puppeteer wait operations support timeout configuration. The documented default is 30,000 milliseconds; check WaitTimeoutOptions and the installed Puppeteer version for the operation you use.
- Navigation condition:
page.goto()accepts awaitUntilcondition, such as the documentednetworkidle2example. This controls navigation waiting, not whether a specific visual state is correct. - Screenshot options: Set options such as output path or
fullPageinpage.screenshot(). The screenshot options reference does not document adelayfield.
Official API pages in the research were labeled Puppeteer version 25.12.0 when researched on 2026-10-03. APIs can vary by installed version, so check your package version and its matching documentation when adapting examples.
5. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The screenshot happens immediately. | The timer promise is not awaited, or the timer is placed after the screenshot. | Put await new Promise(resolve => setTimeout(resolve, milliseconds)) immediately before the capture. |
Puppeteer rejects a delay screenshot option. |
delay is not a documented page.screenshot() option. |
Use a separate awaited timer, or wait for a page condition before calling the screenshot method. |
| The screenshot is still missing content after the sleep. | The chosen duration elapsed, but the target content was not ready; load time and rendering can vary. | Wait for a selector or page condition that represents readiness. Consider network idle for initial loading, then add the visual condition the page requires. |
| Network idle occurs while an animation or widget is unfinished. | Network quiet and visual completion are separate conditions. | Wait for a selector, state, or deliberate duration tied to that visual change. |
| A selector wait times out. | The selector may be wrong, absent on this route, or never visible in the current page state. | Confirm the selector and route, and ensure the condition reflects content that actually appears. Adjust the wait timeout only when a longer wait is justified. |
| The script exits before a file is written or reports an error. | An earlier navigation, wait, launch, or screenshot operation rejected. | Keep the operations awaited, log the error, and use try/finally to close the browser. Diagnose the failing operation rather than increasing the delay blindly. |
6. Performance and reliability
- Latency: A fixed delay adds its full duration to every capture. In a batch, even a modest sleep accumulates across pages. Prefer a condition that becomes true as soon as the needed content is ready.
- Reliability: A fixed sleep is predictable in duration, but not proof of readiness. A selector or page-state predicate is more closely tied to the visual result. Network idle is useful for network activity, not a universal signal for finished rendering.
- Timeouts: Distinguish the timer duration from Puppeteer wait timeouts. A JavaScript sleep does not inherit the timeout settings of Puppeteer wait methods.
- Cost: A local Puppeteer capture has no ScreenshotNeo per-shot charge, but it uses your machine or server resources and requires browser setup and maintenance. A hosted API trades that setup for service pricing; compare the expected volume and required capture behavior.
7. Or skip the browser setup
If you do not want to launch and manage a browser for each capture, ScreenshotNeo provides a website screenshot API and MCP server. Its API returns a PNG, JPEG, WebP, or PDF from one GET request. See the ScreenshotNeo API documentation for request parameters and response details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo and get 1,000 free screenshots a month with no card.
8. FAQ
Is the delay value in seconds?
No. JavaScript’s setTimeout duration is in milliseconds: use 1_000 for one second.
Can I wait after navigation and before every screenshot?
Yes. Put the awaited timer or condition-based wait directly before each screenshot whose target state needs it.
Does networkidle2 mean every image and animation is ready?
No. It addresses network activity during navigation. Use a page condition for the specific content or visual state that matters.
Can Puppeteer delay only the screenshot method?
The documented screenshot options do not provide a delay setting. Add the wait in your script before calling page.screenshot().


