How to Get HTTP Headers from a Puppeteer Response
Read response headers with Puppeteer’s `HTTPResponse.headers()`. Learn where the response comes from, how to handle lowercase names and repeated headers, and how to avoid common navigation mistakes.
Call headers() on Puppeteer’s HTTPResponse object. It returns an object whose header-name keys are lowercase:
const response = await page.goto('https://example.com');
if (response) {
const headers = response.headers();
console.log(headers['content-type']);
console.log(headers);
}
For example, read headers['content-type'], not headers['Content-Type']. The method returns a Record<string, string>. Duplicate header values are combined into a comma-separated value, except Set-Cookie, whose values are separated by a newline. See the official Puppeteer HTTPResponse.headers() reference.
1. Get the response from a page navigation
For a top-level navigation, page.goto(url) returns the navigation’s HTTPResponse when there is one. It can return null, including when navigating to about:blank or changing only the URL hash on the same page. Check the result before calling headers().
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
const response = await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
});
if (!response) {
console.log('This navigation did not produce an HTTP response.');
} else {
console.log('URL:', response.url());
console.log('Status:', response.status());
console.log('Successful (2xx):', response.ok());
console.log('Content type:', response.headers()['content-type']);
console.log('All response headers:', response.headers());
}
} finally {
await browser.close();
}
Install Puppeteer in your project with npm install puppeteer. The example uses JavaScript modules; in a CommonJS project, replace the import with const puppeteer = require('puppeteer');. Consult the API documentation matching the Puppeteer version installed in your project when version-specific behavior matters.
2. Read headers after a click-triggered navigation
When a click causes a navigation, start waiting for that navigation and click in the same Promise.all. This avoids a timing race where the click happens before the navigation listener is ready.
const [response] = await Promise.all([
page.waitForNavigation(),
page.click('a.next'),
]);
const headers = response?.headers();
if (headers) {
console.log(headers['content-type']);
}
The response can still be null, so optional chaining or an explicit check is appropriate. See the official Puppeteer Page reference for navigation behavior and examples.
3. Inspect responses for other page requests
page.goto() gives you the main navigation response. To inspect responses for subresources or other requests made by the page, listen for the page’s response event:
page.on('response', response => {
console.log({
url: response.url(),
status: response.status(),
headers: response.headers(),
});
});
Register the listener before navigating if you need to observe responses from the initial page load. This listener runs for multiple responses, so filter by URL or another condition if you only need a particular resource.
4. Understand header names and repeated values
The result is a JavaScript object, not a list of original header lines. Puppeteer lowercases header names, and repeated values are combined according to the API’s documented behavior.
| Need | Use | What to expect |
|---|---|---|
| Read the content type | response.headers()['content-type'] |
Use the lowercase key. |
| Read all response headers | response.headers() |
An object mapping names to string values. |
| Repeated ordinary header | Read the corresponding object value | Duplicate values are combined into a comma-separated value. |
Repeated Set-Cookie |
Read headers['set-cookie'] |
Values are separated by a newline in this API’s returned value. |
Do not assume the original capitalization is preserved, or that every repeated header is available as a separate array entry. If downstream code needs to interpret a combined value, account for the header’s syntax rather than splitting indiscriminately on commas.
5. Response headers versus request headers
These Puppeteer APIs work in different directions:
| API | Object | Purpose |
|---|---|---|
response.headers() |
HTTPResponse |
Reads headers received in a response. |
request.headers() |
HTTPRequest |
Reads headers associated with an outgoing request. |
page.setExtraHTTPHeaders({...}) |
Page |
Configures extra headers sent with requests initiated by that page. |
page.setExtraHTTPHeaders() is not a way to read response headers. Puppeteer lowercases the configured extra header names and does not guarantee their order. See the official references for HTTPRequest.headers() and Page.setExtraHTTPHeaders().
6. Related response information
An HTTPResponse also exposes methods such as status(), ok(), url(), and request(). Use these when you need the status code, whether the response was successful (2xx), its URL, or the request associated with it. For response headers themselves, headers() is the direct method. The HTTPResponse class reference lists the response methods.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Cannot read properties of null |
page.goto() or waitForNavigation() returned null. |
Check the response before calling headers(). Some navigations, such as about:blank or a hash-only change, do not produce a response. |
headers['Content-Type'] is undefined |
Header names in the returned object are lowercase. | Use headers['content-type']. |
| The headers are for the wrong request | You inspected the main navigation response when you needed a subresource response, or vice versa. | For the main navigation, use the result of page.goto(). For other page responses, listen to the response event and filter by URL. |
| A click navigation is missed | The click occurred before the navigation wait was attached. | Start page.waitForNavigation() and page.click() together with Promise.all. |
| Repeated values do not appear as an array | headers() returns string values in an object; repeated values are combined. |
Handle the documented comma-separated representation, and the newline-separated Set-Cookie representation, as appropriate. |
| You changed extra headers but are still looking for response headers | setExtraHTTPHeaders() configures outgoing request headers. |
Read the received response with response.headers(). |
8. Performance, reliability, and cost
Reading the headers from an existing HTTPResponse does not require another network request. For reliable capture, attach response listeners before navigation, await navigation-triggering actions together with their waits, and handle the possibility of a missing response. Avoid logging all headers indiscriminately in production if responses can contain sensitive values; select only the fields your application needs.
Running Puppeteer requires a browser and the surrounding execution environment. If your task is only to obtain a screenshot rather than inspect response metadata, a hosted screenshot API can avoid managing that browser setup. For the browser-based header inspection shown above, Puppeteer provides the response object directly.
Or skip the browser setup
If your goal is a screenshot rather than response-header inspection, ScreenshotNeo returns an image or PDF from one API request. It does not expose Puppeteer response headers; it is an alternative for screenshot capture.
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 details. Cookie banners, 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 take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan.
FAQ
Can I get headers from a response without navigating the main page?
Yes. Listen for the page’s response event and inspect the relevant HTTPResponse, filtering by URL or another condition.
Does headers() preserve header-name capitalization?
No. Puppeteer documents that header-name keys are lowercase.
Does a successful response mean the page loaded as expected?
response.ok() indicates a 2xx response. It does not by itself establish that the page content matches your application’s expectations; check the page or response body for that.


