How to Inspect Security Details for a Puppeteer Response
Use Puppeteer’s HTTPResponse.securityDetails() to inspect TLS and certificate metadata, handle null results, and keep response headers and status checks separate.
Call securityDetails() on the Puppeteer HTTPResponse you want to inspect. It returns a SecurityDetails object for a response received over a secure connection, or null when those details are unavailable. When present, it exposes the connection protocol, certificate issuer and subject, subject alternative names, and certificate validity timestamps. It is TLS and certificate metadata, not a complete security verdict for the site.
This guide uses the Puppeteer API documented at version 25.12.0 when the research was prepared. Check the API reference for the version installed in your project: SecurityDetails and HTTPResponse.
1. Get the response and inspect its security details
Save this as inspect-security.mjs, install Puppeteer with npm install puppeteer, and run it with node inspect-security.mjs https://example.com. The script handles both a missing navigation response and a response without secure-connection details.
import puppeteer from 'puppeteer';
const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
const response = await page.goto(url, { waitUntil: 'domcontentloaded' });
if (response === null) {
console.log('Navigation produced no HTTPResponse object.');
} else {
const details = response.securityDetails();
if (details === null) {
console.log('No secure-connection details are available for this response.');
} else {
console.log({
url: response.url(),
status: response.status(),
protocol: details.protocol(),
issuer: details.issuer(),
subject: details.subjectName(),
subjectAlternativeNames: details.subjectAlternativeNames(),
validFrom: details.validFrom(),
validTo: details.validTo(),
});
}
}
} finally {
await browser.close();
}
The response === null case is separate from response.securityDetails() === null. Puppeteer documents that page.goto() can return null for navigations such as about:blank or a same-URL navigation that only changes the hash.
2. Read each field correctly
| Call | What it returns | How to use it |
|---|---|---|
protocol() |
The security protocol in use, such as TLS 1.2. |
Record the negotiated protocol reported for this response. |
issuer() |
The certificate issuer name. | Use it as issuer metadata, not as proof by itself that a certificate is trustworthy. |
subjectName() |
The certificate subject name. | Inspect the subject value reported by the browser. |
subjectAlternativeNames() |
The certificate SAN list. | Use it to inspect the names represented in the response’s certificate metadata. |
validFrom(), validTo() |
Unix timestamps for the start and end of certificate validity. | Convert to dates for display; the values are timestamps, not formatted date strings. |
For readable UTC dates in JavaScript, convert seconds to milliseconds:
const validFromDate = new Date(details.validFrom() * 1000).toISOString();
const validToDate = new Date(details.validTo() * 1000).toISOString();
3. Inspect responses from page traffic
The navigation response is useful when you need the document response returned by page.goto(). To observe other traffic, register a response listener. Keep the handler synchronous for simple metadata inspection:
page.on('response', response => {
const details = response.securityDetails();
console.log({
url: response.url(),
status: response.status(),
protocol: details?.protocol() ?? null,
});
});
Attach the listener before navigating or triggering the request of interest so the event is not missed. A page can make many requests for scripts, styles, images, and APIs; filter by URL or resource type if you only need a subset. Puppeteer’s Page events document the response event.
4. Separate TLS metadata from HTTP checks
securityDetails() answers a narrow question: which secure-connection and certificate metadata Puppeteer exposes for this response. Other observations come from other HTTPResponse methods:
| Question | Use |
|---|---|
| What certificate and protocol metadata is available? | response.securityDetails() |
| What HTTP response status was returned? | response.status() |
| What response headers were returned? | response.headers() |
| What remote endpoint was reported? | response.remoteAddress() |
| Was the response served from cache or a service worker? | response.fromCache() and response.fromServiceWorker() |
Header names in Puppeteer’s returned headers object are lowercase. Duplicate header values are generally combined with commas; Set-Cookie values are separated by newlines. Use headers to inspect policies such as content security policy, and use securityDetails() for the documented TLS and certificate fields. These fields alone do not provide a complete certificate-chain report or an overall security audit.
5. Account for redirects, HTTP errors, and failed requests
A 404 or 503 is still an HTTP response. Check response.status(); do not treat every non-2xx status as a failed network request. Redirects complete one request and issue another for the destination, so the final response from page.goto() may describe the destination rather than the original URL.
At the request lifecycle level, requests emit request and then requestfinished after the response body has downloaded. A network failure instead emits requestfailed; in that case there may be no HTTP response on which to call securityDetails(). See the official Page event reference and HTTPRequest API.
6. Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
response is null. |
The navigation did not produce an HTTP response object, as can happen with about:blank or a same-URL hash-only navigation. |
Handle this before calling response methods. Navigate to a URL that makes a document request if you need an HTTP response. |
securityDetails() is null. |
The response has no secure-connection details available, for example because it was not received over a secure connection. | Keep the null check and report that metadata is unavailable; do not substitute guessed certificate fields. |
| The status is 404 or 503, but no request failure event occurred. | HTTP error statuses are completed HTTP responses, not necessarily network failures. | Inspect response.status() and handle the status according to your application’s policy. |
| The details belong to an unexpected host. | The navigation redirected, or the inspected response came from a subresource. | Log response.url(), filter response events, and inspect the response corresponding to the host you care about. |
| Expected fields are missing from an ad hoc “security report.” | securityDetails() intentionally exposes documented connection and certificate metadata, not every security property. |
Inspect response headers, status, remote address, and cache or service-worker state separately where relevant. |
| The script exits before printing results. | An exception occurred before cleanup, or the browser did not launch in the current environment. | Keep browser cleanup in finally, surface launch/navigation errors in your application, and check the Puppeteer installation and runtime environment. |
7. Reliability, performance, and cost considerations
- Reliability: treat the navigation response and its security details as optional values. Redirects, failed requests, non-2xx statuses, and subresource traffic have different meanings.
- Performance: the documented calls read metadata already associated with the response. For a page-wide audit, avoid retaining every response object or logging every resource indefinitely; filter early and store only fields your task needs.
- Versioning: compare the methods against the API reference for your installed Puppeteer release. The docs reviewed for this article displayed version 25.12.0.
- Cost: Puppeteer is browser automation code you run in your own environment. This method itself does not imply a hosted screenshot charge. Account for your own browser runtime and infrastructure costs.
8. Or skip the browser setup
If your goal is a screenshot rather than inspecting the TLS metadata yourself, ScreenshotNeo returns a screenshot or PDF from one GET request. Its screenshot API does not expose the Puppeteer SecurityDetails fields described above; use Puppeteer when that metadata is what you need.
See the ScreenshotNeo API documentation for request options. For example, this cURL request saves a WebP screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
- Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers indicate the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for AI agents and MCP clients. - The free plan includes 1,000 screenshots monthly with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
9. FAQ
Does securityDetails() validate that a website is safe?
No. It returns documented TLS and certificate metadata for a response. A security assessment needs additional checks and a clearly defined scope.
Should I inspect the navigation response or every response?
Inspect the navigation response for the document returned by page.goto(). Listen for response events when you need subresources or API responses, and filter them to the URLs relevant to your task.
Can I use this method on an HTTP response?
You can call the method, but it may return null when secure-connection details are unavailable. Always handle that result.
Does a redirect hide the original response?
page.goto() returns the response associated with the navigation’s final result. Observe response events if you need to record each redirect hop.


