Inside a Puppeteer page request handler, call request.frame(). It returns the frame that initiated the request, or null in the documented case of navigation to an error page. Check for null before using frame methods. To test whether the request drives a navigation, check request.isNavigationRequest() separately.
Get the initiating frame from a request
Puppeteer’s page-level request, requestfinished, and requestfailed events provide an HTTPRequest. In a request handler, use its frame() method:
As an Amazon Associate I earn from qualifying purchases.
page.on('request', request => {
const frame = request.frame();
if (frame === null) {
// Puppeteer documents null when navigating to an error page.
return;
}
console.log('frame URL:', frame.url());
console.log('drives navigation:', request.isNavigationRequest());
});
The null check matters: do not assume every request has a usable frame. Also, do not substitute page.mainFrame() when request.frame() is null. The request accessor is specifically about the frame that initiated that request; the main frame is a different lookup.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Frame association is not the same as navigation
request.frame() answers which frame initiated the request. It does not say whether the request itself is navigating that frame. Use request.isNavigationRequest() when you need to filter for requests that drive navigation.
#1 Best Overall
page.on('request', request => {
if (!request.isNavigationRequest()) return;
const frame = request.frame();
if (frame === null) {
console.log('Navigation request has no frame (error-page navigation).');
return;
}
console.log('Navigation for frame:', frame.url());
});
Use the right API for the object you have
| What you have or need | Use | What it tells you |
|---|---|---|
An HTTPRequest in a request event |
request.frame() |
The frame that initiated the request; it can be null for navigation to an error page. |
| A request’s navigation status | request.isNavigationRequest() |
Whether the request drives the current frame’s navigation. |
An HTTPResponse in a response handler |
response.frame() |
The frame associated with the response; it has the same documented null case for error-page navigation. |
The request associated with an HTTPResponse |
response.request() |
The HTTPRequest associated with that response, including its request metadata. |
| The page’s main frame | page.mainFrame() |
The page’s main frame, not necessarily the frame associated with a particular request. |
| All frames attached to a page | page.frames() |
The page’s frame list. |
| Direct child frames of a frame | frame.childFrames() |
That frame’s child frames. |
Handle request outcomes accurately
An HTTP error status such as 404 or 503 is still a completed HTTP request: Puppeteer’s request lifecycle emits requestfinished for it. A request that fails at the loading level emits requestfailed. Treating those as equivalent can misclassify page behavior.
Redirects also have a lifecycle detail worth accounting for: the original request completes, and Puppeteer issues a new request to the redirected URL. If you inspect requests, do not assume a redirect remains a single request object.
Rank #2
Account for frame lifecycle and navigation timing
Frames can attach, navigate, and detach while a page is running. Puppeteer exposes the frameattached, framenavigated, and framedetached lifecycle events. If you retain a Frame for later work, consider that it may no longer be attached by the time you use it.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsWhen an action is expected to navigate a particular frame, start waiting for navigation and trigger the action together so the navigation is not missed:
await Promise.all([
frame.waitForNavigation(),
frame.click('a.navigate')
]);
Use the selector appropriate to your page. This pattern coordinates the wait with the action rather than waiting only after the click.
Troubleshooting
request.frame()returnsnull: Puppeteer documents this for navigation to an error page. Preserve the null result and skip frame-specific calls; do not silently replace it with the main frame.- You are seeing subresource requests as well as document navigation: Check
request.isNavigationRequest(); frame association alone is not a navigation filter. - A 404 or 503 appears as a finished request: This is expected for an HTTP error response. Distinguish the response status from a loading failure that emits
requestfailed. - A redirect appears as more than one request: Puppeteer completes one request and creates another for the redirected URL. Inspect the redirected request separately.
- A saved frame is no longer usable later: Frame attachment changes over time. Track frame lifecycle if delayed work depends on a frame remaining attached.
- A navigation wait misses the navigation: Start
frame.waitForNavigation()concurrently with the action usingPromise.all.
Or skip the browser setup
If your goal is a screenshot rather than frame-level browser automation, ScreenshotNeo provides a website screenshot API and MCP server. Its one-call cURL example is:
Quick Recap
Best Value
- Used Book in Good Condition
Rank #4
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. Cookie banners, popups, and chat widgets are removed before capture; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →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.




