Call response.headers() on the HTTPResponse returned by Puppeteer. The result is an object with lowercase header-name keys, so use headers['content-type'], not headers['Content-Type']. Check that a response exists before reading it: some navigations return null.
Read headers from a page navigation
page.goto() returns the response for the main navigation when one is available. Call its headers() method to inspect the response headers:
As an Amazon Associate I earn from qualifying purchases.
const response = await page.goto('https://example.com');
if (response) {
const headers = response.headers();
console.log(headers['content-type']);
console.log(headers);
}
headers() returns a Record<string, string>-style object. Header names are lowercase, regardless of how they may have appeared on the wire. The Puppeteer method reference labeled 25.9.0 also says duplicate header values are combined into comma-separated values, except Set-Cookie, which is separated by newline characters. Do not assume repeated headers remain separately addressable or that the returned object preserves original header casing.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsWhy the response check matters
Puppeteer documents page.goto() returning null for cases including navigation to about:blank and changing only the hash on the same URL. Without the check, calling headers() on a null value will fail.
#1 Best Overall
Read headers after a click-triggered navigation
When clicking an element causes navigation, start waiting for that navigation at the same time as the click. This avoids a timing race in which the navigation happens before the wait is registered:
const [response] = await Promise.all([
page.waitForNavigation(),
page.click('a.next'),
]);
const headers = response?.headers();
console.log(headers?.['content-type']);
The optional chaining handles the possibility that the navigation wait resolves without a response. If you need to inspect all headers, check headers before logging or using it.
Rank #2
Inspect responses beyond the main page
Use the page’s response event to inspect responses for requests such as scripts, images, stylesheets, and API calls—not just the main document navigation:
Recommended Free Tools
page.on('response', response => {
console.log(response.url(), response.status(), response.headers());
});
Each event supplies an HTTPResponse, which exposes url(), status(), and headers(). A page may emit many responses, so filter by URL or another condition if you only want a particular resource:
page.on('response', response => {
if (response.url().includes('/api/')) {
const headers = response.headers();
console.log(response.status(), headers['content-type']);
}
});
Response headers are not request headers
Puppeteer has separate APIs for reading headers received from a server and setting or inspecting headers sent by the browser. Choose the API according to the direction you care about:
| Need | API | What it does |
|---|---|---|
| Read headers returned by a server | HTTPResponse.headers() |
Returns headers associated with an HTTP response. |
| Read headers associated with an outgoing request | HTTPRequest.headers() |
Returns headers for the request, not the response. |
| Add headers to requests initiated by a page | page.setExtraHTTPHeaders({...}) |
Configures extra headers to send with page requests; it does not read response headers. |
setExtraHTTPHeaders() lowercases header names, and Puppeteer does not guarantee the order in which those headers are sent. Use it before the relevant page requests if you need to configure outgoing headers.
Rank #4
Inspect status and other response details
For nearby response information, the HTTPResponse API also provides status() for the status code and ok() for whether the response was successful (2xx). It also exposes url(), request(), and body-access methods. These are separate from headers(); use the method that matches the value you need.
Version note
The Puppeteer API reference for HTTPResponse.headers() inspected here is labeled 25.9.0, while the related HTTPResponse class reference is labeled 25.12.0. Those are labels on separate documentation pages, not confirmation of one package release. Check the documentation for the Puppeteer version installed in your project when exact behavior matters. The Next documentation describes asFetchResponse(), including parsing multiline Set-Cookie values into separate entries; do not assume that method is available in a stable release without checking your installed version.
Best Value
Troubleshooting
responseis null: Guard before callingheaders(). Puppeteer documents null responses for cases such asabout:blankand same-URL hash changes.- A header lookup returns
undefined: Use the lowercase key, such asheaders['content-type']. The returned object does not preserve header-name casing. - You need headers from an XHR or asset rather than the document: Listen for the page’s
responseevent and select the response by URL or status. - You are seeing request headers instead: Check that you are calling
headers()on anHTTPResponse, not anHTTPRequest.page.setExtraHTTPHeaders()sets outgoing request headers; it does not retrieve response headers. - Repeated headers do not appear as separate entries: Puppeteer combines duplicate values with commas except for
Set-Cookie, which is represented with newline separation in the cited method documentation.
Or skip the browser setup
If your goal is a clean screenshot rather than inspecting headers in a Puppeteer workflow, ScreenshotNeo provides a one-request screenshot API. For example, this cURL request saves a WebP screenshot of Stripe; replace the target URL as needed. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses identify the page verdict and billing status in headers. It also provides an MCP server with screenshot and PDF tools for AI agents. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 screenshots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
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.




