Listen for changes on a Puppeteer page with page.on('eventName', handler). Use page.once() for a one-time callback and page.off() with the same callback function to remove a listener. The examples below cover lifecycle events, URL changes, popups, page errors, and network requests—and explain how to avoid navigation races.
Register and remove a Page event listener
A Puppeteer Page is an EventEmitter. Register a persistent listener with page.on(eventName, handler); register one that runs only once with page.once(eventName, handler). To remove a persistent listener, pass the same function reference to page.off().
As an Amazon Associate I earn from qualifying purchases.
function logRequest(request) {
console.log('A request was made:', request.url());
}
page.on('request', logRequest);
// Later, when the listener is no longer needed:
page.off('request', logRequest);
// Run a callback only for the next load event:
page.once('load', () => console.log('Page loaded!'));
For a callback you may need to remove later, use a named function or save the function in a variable. An inline arrow function passed directly to page.on() is difficult to remove unless you kept a reference to it.
Recommended Free Tools
Choose an event for the change you need
| What you need to detect | Event or API | What the handler receives or inspects |
|---|---|---|
| The document reaches its load milestone | load |
Page lifecycle event |
| The document’s DOM is ready | domcontentloaded |
Page lifecycle event |
| A frame navigates, attaches, or detaches | framenavigated, frameattached, framedetached |
A Frame |
| The page opens a popup | popup |
The popup’s Page |
| Page JavaScript logs a message | console |
A ConsoleMessage |
| Page JavaScript throws an uncaught exception | pageerror |
Error data |
| Observe network activity | request, response, requestfinished, requestfailed |
An HTTPRequest or HTTPResponse |
framenavigated is useful for detecting URL changes, but it can report navigation in a frame rather than only in the main document. Inspect the supplied frame if you only care about the top-level page. Puppeteer dispatches frame lifecycle events on the parent page.
#1 Best Overall
Listen for lifecycle events and URL changes
load and domcontentloaded mark different document lifecycle milestones. To observe a frame URL change, listen for framenavigated and inspect the frame URL:
page.on('framenavigated', frame => {
console.log('Frame navigated:', frame.url());
});
page.once('domcontentloaded', () => {
console.log('The DOM content is ready');
});
The frame event may concern an iframe. If your logic is specifically about the main frame, compare the event’s frame with page.mainFrame() before acting.
Wait for an event without racing navigation
If a click or other action is expected to cause navigation, start waiting for the event and trigger the action together. Waiting only after the action can miss an event that has already fired.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
const [response] = await Promise.all([
page.waitForNavigation(),
page.click('a.next-page'),
]);
console.log('Navigation response:', response?.status());
Use the event that matches what the action is expected to do. A popup is not the same as navigation in the current page, and a single-page application may update content or history without producing a full document navigation.
Handle popups, console messages, and page errors
Capture a popup
The page’s popup event supplies the new tab or window as a Puppeteer Page. It is associated with the parent page’s browser context.
page.once('popup', async popup => {
await popup.waitForLoadState?.('load');
console.log('Popup URL:', popup.url());
});
await page.click('a[target="_blank"]');
Puppeteer wait APIs vary by version. If your installed version does not provide the method shown, use its documented page lifecycle wait method or inspect the popup after the event; check the API reference matching your installed release.
Rank #3
Inspect browser-side diagnostics
page.on('console', message => {
console.log('Page console:', message.type(), message.text());
});
page.on('pageerror', error => {
console.error('Uncaught page error:', error);
});
A console event is a Puppeteer ConsoleMessage, not the Node.js console itself. The pageerror event is for uncaught exceptions from page JavaScript; it is distinct from HTTP status codes and request failures.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Observe request and response stages
Puppeteer emits request and response events without request interception. A request event marks a request being issued, a response event indicates that a response arrived, and requestfinished means the response body has been downloaded and the request completed.
page.on('request', request => {
console.log('Request:', request.url());
});
page.on('response', response => {
console.log('Response:', response.url(), response.status());
});
page.on('requestfinished', request => {
console.log('Finished:', request.url());
});
page.on('requestfailed', request => {
console.log('Failed:', request.url(), request.failure()?.errorText);
});
An HTTP error status is still an HTTP response. A 404 or 503 request can receive a response and finish normally; it does not become requestfailed just because the status is unsuccessful. A failed network request instead emits requestfailed rather than requestfinished. Redirects finish one request and issue another request to the redirected URL. See Puppeteer’s network logging guide.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Use request interception only when you need control
Do not enable interception merely to observe traffic. Use page.setRequestInterception(true) when you need to alter, continue, answer, or abort requests. Once enabled, requests stall until resolved, unless completed using the browser cache.
await page.setRequestInterception(true);
page.on('request', request => {
if (request.isInterceptResolutionHandled()) return;
if (request.url().endsWith('.png')) {
request.abort();
} else {
request.continue();
}
});
When interception handlers include asynchronous work, another handler may resolve the request while the first is awaiting. Check isInterceptResolutionHandled() immediately before resolving it, and keep the check and resolution together synchronously. This prevents a second resolution attempt. The request interception guide explains the resolution behavior.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Understand lifecycle events versus navigation wait conditions
networkidle0 and networkidle2 are navigation wait conditions, not Page event names. They wait for the number of active network connections to remain under the relevant limit for at least 500 ms. They can be useful when a page needs time to settle, but pages with ongoing network activity may not reach that condition. Choose a wait strategy based on the page behavior you need to observe rather than treating network idle as a universal signal that all content is ready. See the lifecycle event reference.
Best Value
Common listener problems and fixes
- The listener does not run: Register it before the action that may trigger the event. For navigation waits, pair the wait with the triggering action using
Promise.all. page.off()does not remove it: Pass the original callback reference, not a new arrow function with identical code.- A 404 does not emit
requestfailed: That is expected; a 404 is an HTTP response. Inspectresponse.status()to detect HTTP errors. - A frame event fires unexpectedly:
framenavigatedcan refer to an iframe. Check whether the frame ispage.mainFrame()when only the top-level URL matters. - An intercepted request errors or stalls: Make sure every intercepted request is continued, responded to, or aborted, and check that another handler has not already resolved it.
networkidle0is rejected as an event name: Use it as a navigation lifecycle wait condition, not withpage.on().
Check event availability in your Puppeteer version
The official Page API reference surfaced for Puppeteer 25.12.0 and identifies Page as an EventEmitter. The PageEvent enum reference is under the next documentation, so confirm event names and payloads against the documentation for the version installed in your project before relying on an event in production.
Or skip the browser setup
If your goal is a screenshot rather than browser-side event handling, ScreenshotNeo can return an image or PDF with one GET request. Its screenshot 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, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. ScreenshotNeo also offers an MCP server with screenshot, page-info, and PDF tools for AI agents. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.
Example using cURL (replace the URL with the page to capture):
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Sign up for 1,000 free screenshots a month with no card.
Frequently Asked Questions
Does page.on('load') wait for navigation?
No. It registers a listener for the event; use a navigation wait API when your code must await navigation.
Is networkidle0 a Page event?
No. It is a lifecycle wait condition based on active network connections.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




