How to reload a page in Puppeteer and wait for it to load
Use page.reload() with the right wait condition, then wait for a specific element when your app needs more than a browser lifecycle event.
To reload the current page and wait for its normal load event, use await page.reload(). Puppeteer waits for the load lifecycle event by default and returns the main resource’s HTTPResponse, or null when there is no main-resource response. Choose another lifecycle condition with waitUntil, and add a selector or predicate wait if you need to know that application content is ready.
Set up Puppeteer
These examples use JavaScript modules and a recent Puppeteer installation. Install it in a Node.js project:
npm install puppeteer
Save the following as reload.mjs. It opens a page, reloads it, and prints the status from the reload response when one is available:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
const response = await page.reload();
console.log(response ? `Reload status: ${response.status()}` : 'Reload had no main-resource response');
} finally {
await browser.close();
}
Run it with node reload.mjs. The reload promise itself waits for the selected lifecycle event, so a separate waitForNavigation() is not needed when your code directly calls page.reload().
Choose when the reload is considered complete
Pass a waitUntil option to select a browser lifecycle milestone:
await page.reload({ waitUntil: 'load' });
await page.reload({ waitUntil: 'domcontentloaded' });
await page.reload({ waitUntil: 'networkidle0' });
await page.reload({ waitUntil: 'networkidle2' });
| Condition | What it signals | Use it when |
|---|---|---|
load |
The document and its load-dependent resources have reached the browser’s load event. | The page’s normal load event is the required threshold. This is the default. |
domcontentloaded |
The initial HTML has been parsed and the DOMContentLoaded event has fired. | You need the parsed document and do not need to wait for later resources. |
networkidle0 |
No more than zero network connections for at least 500 ms. | Network quiet is a useful signal for this page and its requests eventually settle. |
networkidle2 |
No more than two network connections for at least 500 ms. | A page has some continuing network activity but a looser quiet threshold suits the task. |
These conditions describe browser lifecycle or network activity; they do not prove that the application displayed the correct data. Pages with polling, streaming connections, analytics, or other background requests may not reach a network-idle condition promptly. The exact lifecycle option definitions are in the Puppeteer lifecycle event documentation, and reload options are described in the wait options reference.
Wait for application content after reload
If the goal is to confirm a result panel, status, or other rendered content, wait for that specific signal after the reload:
await page.reload({ waitUntil: 'domcontentloaded' });
await page.locator('[data-testid="results"]').wait();
Use a selector that represents the outcome your script needs. For a particular value or state, use a condition that checks it rather than treating the element’s mere existence as proof that its contents are correct. Puppeteer’s page interaction guide documents locator and function-based waits.
Wait when a click or other action causes the reload
When an interaction triggers a navigation or reload, start waiting for navigation at the same time as the action. This avoids a race where the page starts navigating before the wait is registered:
const [response] = await Promise.all([
page.waitForNavigation({ waitUntil: 'load' }),
page.click('button.reload'),
]);
console.log(response ? `Navigation status: ${response.status()}` : 'Navigation had no main-resource response');
waitForNavigation() can resolve to null for navigation types that have no main-resource response, including History API URL changes. A null result alone does not establish that the action failed. The waitForNavigation reference documents this pattern and return behavior.
If the click updates the page without a document navigation, wait for the resulting element or state instead of waiting for navigation. For a reload initiated directly by your code, use page.reload() and its options.
Configure timeouts
Navigation waits use a 30,000 ms default timeout. Set a timeout for one reload when a particular page needs longer:
await page.reload({ waitUntil: 'load', timeout: 60_000 });
Or change the default navigation timeout for the page. It applies to reloads, navigations, and related navigation waits:
page.setDefaultNavigationTimeout(60_000);
await page.reload({ waitUntil: 'load' });
Use timeout: 0 to disable a wait’s timeout, but a bounded timeout is generally easier to diagnose and recover from. See Puppeteer’s wait options and default navigation timeout reference.
Run a reload from the command line or other languages
Puppeteer is a Node.js browser automation library, so its reload API is JavaScript. cURL and Python do not call page.reload(); they can request a URL directly, but that does not reproduce a browser reload or provide Puppeteer lifecycle waits. If you need browser rendering and a screenshot, use Puppeteer’s Node.js API or a screenshot service.
For example, a direct HTTP request with cURL fetches a resource response, not a rendered browser page:
curl -L --fail --output page.html https://example.com
Likewise in Python, requests fetches the HTTP response body without running page JavaScript:
import requests
response = requests.get('https://example.com', timeout=30)
response.raise_for_status()
print(response.status_code)
print(response.text[:500])
Use those approaches only when the raw HTTP response is sufficient. They cannot wait for a browser’s load event or an app-rendered selector.
Or skip the browser setup
If your goal is a rendered page screenshot rather than browser automation, ScreenshotNeo returns an image or PDF with one GET request. See the ScreenshotNeo API documentation for its 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 removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers say which page verdict applied and whether the request was billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, with no card required.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
page.reload() times out |
The selected lifecycle event did not occur before the timeout, or the page remains active with background requests. | Choose the milestone the task actually needs, such as domcontentloaded, increase the timeout if the page legitimately needs longer, or wait for an application selector instead of network idle. |
networkidle0 never completes |
The page keeps connections open or continues making requests. | Use load or domcontentloaded if that is enough, or wait for the specific UI state you need. |
| The script continues before the expected content appears | The lifecycle event completed, but the application renders or fetches data afterward. | After reloading, wait for a locator or condition tied to the expected content. |
| A click-triggered navigation is missed | The navigation wait was registered after the click began. | Register the wait and click together with Promise.all. |
The navigation response is null |
The navigation may not have a main-resource response, as with a History API URL change. | Check the resulting URL or application state; do not treat null by itself as failure. |
| The observed response status is an error | The browser received an HTTP error response for the main resource. | Inspect the response status and page state. A completed navigation wait means the lifecycle condition was reached; it does not mean the server returned a successful status. |
Performance, reliability, and cost
- Wait only as long as the task requires.
domcontentloadedcan avoid waiting for later resources when the parsed DOM is enough. Do not use network idle as a generic synonym for “ready.” - Prefer explicit application readiness. A selector or predicate makes the script’s success condition clearer than an arbitrary delay and more relevant than network quiet when the app loads data asynchronously.
- Keep a timeout and handle failures. A timeout makes stalled pages observable; callers can log the URL and selected condition, then retry selectively according to their own task’s retry policy.
- Check the response when HTTP success matters. The lifecycle wait concerns browser progress. Inspect the returned response and status separately if a successful HTTP result is required.
- Account for browser execution costs. Puppeteer runs a browser process and waits on the page’s resources. The required runtime depends on the page and environment; this guide makes no benchmark claim. A screenshot API can avoid managing browser setup when the deliverable is only a screenshot.
FAQ
Does page.reload() return the page?
No. It resolves to the main resource’s HTTPResponse or null, not a Page object.
Should I call waitForNavigation() after page.reload()?
Usually no. The reload call already waits according to its waitUntil option. Pair waitForNavigation() with an action when that action causes the navigation.
Is networkidle0 always more reliable than load?
No. It waits for a network-activity threshold, which may be unsuitable for pages with persistent or recurring requests. Choose the signal that matches the page and task.
Can I reload only part of a page?
page.reload() reloads the page. To update a component without a document reload, use the application’s own interaction or request flow and wait for its resulting state.


