Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Puppeteer’s page.on('response') event to observe responses as they arrive, or page.waitForResponse() to wait for a response that matches a particular URL or request. Read status and headers directly from the response; use text(), json(), buffer(), or content() when you need its body. For a response caused by a click or other action, start waiting before you trigger that action so the response cannot arrive first.

Choose the capture method that fits the job

Puppeteer exposes response information through its page response event and response-waiting API. These are observation tools: they let your script inspect traffic the page makes without changing how requests are sent.

Need Use What to watch for
Observe multiple responses during navigation or page activity page.on('response', handler) Filter the traffic so you do not try to read every asset body.
Get the response associated with a particular action page.waitForResponse(predicate) Set up the wait before clicking, submitting, or otherwise triggering the request.
Change, fulfill, or abort outgoing requests Request interception Interception is not needed just to read responses. Every intercepted request must be resolved.

The examples below use Puppeteer’s documented response and body APIs. The API references returned for this topic are versioned 25.10.0 for body methods and 25.12.0 for request and interception APIs; check the documentation for the version installed in your project if behavior or types differ.

Capture responses with an event listener

Attach the listener before navigating if you need responses produced during page load. The handler can inspect status, URL, and related request metadata. This example records basic information without reading bodies:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const responses = [];

page.on('response', response => {
  const request = response.request();
  responses.push({
    url: response.url(),
    status: response.status(),
    method: request.method()
  });
});

await page.goto('https://example.com');
console.log(responses);

A response event is useful when you do not know in advance which response will matter, or when you want to inspect several responses after navigation. It can fire for documents, scripts, stylesheets, images, and API calls. Narrow the handler with URL, method, resource type, or status checks to avoid collecting unrelated traffic.

When you need a response body, the event callback can be asynchronous, but the event emitter does not make the page wait for your callback to finish. If you need all body reads to complete before continuing, explicitly keep the resulting promises and await them after the action or navigation:

const bodyReads = [];

page.on('response', response => {
  if (!response.url().includes('/api/')) return;

  bodyReads.push((async () => ({
    url: response.url(),
    status: response.status(),
    body: await response.text()
  }))());
});

await page.goto('https://example.com');
const apiResponses = await Promise.all(bodyReads);
console.log(apiResponses);

This pattern can consume memory if the page makes many matching requests or returns large bodies. Apply a precise filter and capture only the fields your task needs.

Wait for the response caused by an action

When a click or form submission triggers a request, create the response wait first, then perform the action. Match the response tightly enough to distinguish it from unrelated traffic:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const responsePromise = page.waitForResponse(response =>
  response.url().includes('/api/items') &&
  response.request().method() === 'GET'
);

await page.click('button.load-items');
const response = await responsePromise;

console.log(response.status(), response.url());
const items = await response.json();
console.log(items);

If you click first and only then call waitForResponse(), a fast response may already have arrived, leaving the wait to time out. Use the same ordering for other actions that can initiate a request. If an action can cause more than one matching request, make the predicate more specific—for example, include a distinctive path or query value when the application provides one.

waitForResponse() waits for the response object. It does not make an HTTP error status into a successful application result. Check response.status() and handle the body according to your task.

Inspect status, headers, request details, and body

An HTTPResponse gives you metadata and body-reading methods. Use the smallest amount of data needed for the task.

Status and response headers

Use status() for the numeric HTTP status and headers() for response headers. Pair these with url() and the associated request’s method when deciding whether a response is relevant:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const response = await page.waitForResponse(r =>
  r.url().includes('/api/items')
);

const request = response.request();
console.log({
  status: response.status(),
  url: response.url(),
  method: request.method(),
  headers: response.headers()
});

Do not treat a 404 or 503 as proof that the request failed at the network level. Puppeteer documents that HTTP error responses are still completed HTTP responses; the request can finish normally even when the status indicates an application- or server-side error.

Text and JSON

Use text() when you want a text representation or json() when the response body is JSON. JSON parsing can fail if the body is empty, malformed, or not JSON, so catch errors and preserve the status and URL for diagnosis:

try {
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error('Could not parse response as JSON', {
    url: response.url(),
    status: response.status(),
    error
  });
}

Binary body data

buffer() resolves to a Node.js Buffer; content() resolves to a Uint8Array. These methods are useful when the body is not text or JSON. However, Puppeteer’s documentation warns that the browser may re-encode a body based on HTTP headers or other heuristics. Do not assume the bytes returned by these methods are always an exact copy of the bytes transmitted over the network.

const bytes = await response.buffer();
console.log(`Received ${bytes.length} bytes from ${response.url()}`);

Understand request and response lifecycle events

Puppeteer distinguishes requests that complete from requests that fail at the network or request level. The events help explain what happened when a response is absent or a page behaves unexpectedly.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • request indicates that a request was issued.
  • requestfinished indicates that the response body has been downloaded and the request is complete.
  • requestfailed indicates a request-level failure, such as an inability to complete the request.

An HTTP status such as 404 or 503 is still a response; it does not by itself mean the request emitted requestfailed. A redirect finishes the original request and results in a new request to the redirected URL. When investigating redirects or failures, follow the individual request and response events rather than assuming one URL corresponds to one uninterrupted request.

Each response can be connected to its request with response.request(). That is the practical way to filter by both response details and request attributes such as method.

Why passive observation is not interception

For logging, checking status codes, or reading bodies, prefer response events or waitForResponse(). Request interception serves a different purpose: it lets code abort, continue, or fulfill requests with abort(), continue(), or respond().

Once page.setRequestInterception(true) is enabled, each request stalls unless it is resolved, or completed from browser cache. A handler that forgets to resolve even one request can prevent page activity or navigation from completing. Avoid enabling interception just to observe traffic; it adds work and creates a failure mode that passive listeners do not.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition

If interception is genuinely required

Multiple handlers may be registered. Before resolving a request, check whether it has already been handled. If your handler awaits asynchronous work, check again immediately afterward and before calling abort(), continue(), or respond(), because another handler may have resolved it while your code was waiting. Puppeteer also documents cooperative priorities, but handlers should not be assumed to coordinate automatically unless they consistently use the documented cooperative mode.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot missing responses and body errors

  • The response wait times out. The action may not have triggered the request, the predicate may not match its URL or method, or the request may have failed before producing a response. Attach request and failure listeners temporarily, verify the action and predicate, and create the wait before triggering the action.
  • You captured the wrong response. Broad predicates can match multiple resources or API calls. Include the relevant path and request method, and use other request metadata when available to make the match distinct.
  • The status is 404 or 503, but no request failure occurred. This is an HTTP response with an error status, not necessarily a network-level failure. Inspect the status and response body as an application/server error.
  • json() throws. The body may not be valid JSON, may be empty, or may be an error page. Log status and URL, then inspect with text() if appropriate.
  • Body bytes differ from an expected file or wire capture. Puppeteer warns that browser decoding and re-encoding may affect the body. Treat its body methods as the data exposed by the browser, not as a wire-fidelity guarantee.
  • Navigation hangs after enabling interception. Ensure every intercepted request is resolved. Review all handlers, including early returns and exception paths, and check whether another handler has already acted before resolving.

Or skip the browser setup

Puppeteer is the right choice when your task is to inspect browser responses, including API response bodies and request metadata. ScreenshotNeo is a different tool: it captures a rendered webpage as an image or PDF, not HTTP response bodies. If your actual goal is a clean page screenshot rather than network inspection, its API takes a URL in one GET request. See the ScreenshotNeo site and API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Cookie banners and consent prompts, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use screenshot tools, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000. Sign up for the free plan.

Frequently Asked Questions

Can Puppeteer capture every response made by a page?

A page response listener can observe responses emitted while it is attached, including responses during navigation if you register it first. It cannot recover responses that arrived before the listener was attached.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does `requestfailed` mean the server returned an HTTP error?

No. An HTTP error status such as 404 or 503 is still a response; `requestfailed` is for a request-level failure.

Does Puppeteer provide a guaranteed wire-exact response body?

No such guarantee is established by the documented body methods. Puppeteer warns that browser re-encoding can affect the bytes they expose.

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.