Recommended Free Tools
Call await response.buffer() on a Puppeteer HTTPResponse. It resolves to a Node.js Buffer containing the response body; write that buffer separately if you need a file.
Get a response and read its body
For a navigation response, capture the value returned by page.goto(), then await its body:
As an Amazon Associate I earn from qualifying purchases.
const response = await page.goto('https://example.com');
if (!response) {
throw new Error('Navigation did not return an HTTP response');
}
const body = await response.buffer();
console.log(`Received ${body.length} bytes`);
HTTPResponse.buffer() returns a Promise<Buffer>, so the asynchronous call must be awaited before the buffer is used. See the Puppeteer buffer() reference. A response obtained from a request or response event can be handled the same way once you have the relevant HTTPResponse.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Write the buffer to a file
buffer() retrieves bytes into memory; it does not save them to disk. Use Node.js filesystem APIs for persistence. This complete example saves the navigation response body:
#1 Best Overall
const fs = require('node:fs/promises');
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
const response = await page.goto('https://example.com');
if (!response) {
throw new Error('Navigation did not return an HTTP response');
}
const body = await response.buffer();
await fs.writeFile('response-body.bin', body);
console.log(`Saved ${body.length} bytes to response-body.bin`);
} finally {
await browser.close();
}
})().catch(error => {
console.error(error);
process.exitCode = 1;
});
Choose an extension that reflects what the endpoint actually returns. The buffer may contain HTML, an image, JSON, or another body format; the filename extension does not convert it.
Check status separately from reading the body
Getting a body buffer does not establish that the HTTP request succeeded. If your application treats non-success responses as errors, inspect the response status or ok() before saving or processing its body:
Rank #2
const response = await page.goto('https://example.com');
if (!response) throw new Error('No HTTP response');
if (!response.ok()) {
throw new Error(`HTTP ${response.status()} for ${response.url()}`);
}
const body = await response.buffer();
The HTTPResponse class reference also documents headers(), request(), and url(). Choose the checks your application needs; body retrieval and success/failure decisions are separate.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteChoose the right body representation
| Method | Result | Use it when |
|---|---|---|
buffer() |
Promise<Buffer> |
You need a Node.js buffer for binary handling or filesystem writes. |
content() |
Promise<Uint8Array> |
A typed array is suitable for the code consuming the body. |
text() |
A decoded string | You want UTF-8 text; Puppeteer documents that it throws if the content is not UTF-8. |
json() |
A parsed JavaScript value | You want JSON data; it throws if the body cannot be parsed with JSON.parse. |
These methods and their documented behaviors are listed in the Puppeteer HTTPResponse reference. For a binary body, use buffer() rather than decoding it as text.
Account for browser handling of response bytes
Puppeteer warns that the browser may re-encode a response body based on HTTP headers or other heuristics. Therefore, the returned buffer should not be treated as a guarantee of untouched, byte-for-byte wire data. If preserving a particular wire representation is essential, verify that Puppeteer’s browser-provided body is appropriate for that requirement. The caveat is documented on the buffer() method page.
Troubleshoot common problems
responseis null: Check that the operation returned an HTTP response before callingbuffer(). Navigation can fail without yielding one; handle that case rather than dereferencing null.- The result is a Promise, not immediately usable bytes: Use
await response.buffer()inside an async function, or attach promise handling before accessing the result. - The file was not created:
buffer()only obtains data in memory. Call a filesystem write operation such asfs.writeFile(path, body)and ensure the process can write to that path. - The saved body looks unexpected: Check
response.status(),response.url(), andresponse.headers()to confirm which response you received and its metadata. A redirect or an error response may not contain the content you expected. - Bytes differ from an expected wire capture: Browser handling can re-encode the body; Puppeteer does not promise this method returns untouched wire bytes. Validate suitability for the required representation.
Version note
Puppeteer’s official method reference identifies version 25.10.0, while its HTTPResponse class reference identifies version 25.12.0. Since API documentation can vary by release, check the references for the Puppeteer version installed in your project when exact version-specific behavior matters.
Rank #4
Or skip the browser setup
If your goal is a website screenshot rather than retrieving an arbitrary HTTP response body, ScreenshotNeo provides a screenshot API. One GET request can return an image or PDF:
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 options and response handling. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. ScreenshotNeo also has an MCP server with tools for AI agents, and the free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo free to try 1,000 screenshots a month with no card.
Quick Recap
Best Value
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.




