ScreenshotNeo

BlogHow-to

How to Read the Stack Trace of a Puppeteer Console Message

Capture Puppeteer console messages, inspect their locations and stack entries, and distinguish page logs from uncaught exceptions and Node.js errors.

By the ScreenshotNeo team4 October 20267 min read

A Puppeteer console message exposes its text, type, arguments, message location, and stack locations through a ConsoleMessage. Listen for the page’s console event, then inspect text(), type(), location(), and stackTrace(). Treat location() as the message location and stackTrace() as an array of locations associated with that message; neither is the same thing as Node.js’s Error.stack.

First identify which failure channel you have: a page console message, an uncaught page exception, or a failure in your Node.js Puppeteer script. They have different event and debugging paths.

Capture and inspect a console message

Browser-side calls such as console.warn() do not automatically print in the Node.js process. Attach a listener to the Puppeteer Page and read the message object there.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();

    page.on('console', msg => {
      console.log('type:', msg.type());
      console.log('text:', msg.text());
      console.log('location:', msg.location());
      console.log('stack trace:', msg.stackTrace());
      console.log('arguments:', msg.args().length);
    });

    await page.goto('https://example.com');
    // Keep the page open until the actions that produce relevant messages finish.
  } finally {
    await browser.close();
  }
})().catch(error => {
  console.error('Node.js script error:', error);
  process.exitCode = 1;
});

This is a CommonJS example. In an ES module, replace the first line with import puppeteer from 'puppeteer';. Install Puppeteer in your project with npm install puppeteer. The exact location fields available depend on the Puppeteer version; inspect the returned objects for the version you have installed.

Understand the message fields

Accessor What to use it for What not to assume
text() The message text for logs and searching. It does not by itself identify the cause.
type() The documented console category, such as error, warn, or trace. A type such as error does not mean you have a complete exception stack.
args() The message’s associated arguments when the text alone is insufficient. Do not assume every argument is a plain string.
location() The location associated with the console message. Do not describe it as the full stack.
stackTrace() An array of locations on the console message’s stack. It is not an Error.stack string; handle it as location entries.

For structured logging, keep the accessors separate instead of flattening everything into one string. The API describes stack locations as ConsoleMessageLocation[]. Consult the API reference for the installed Puppeteer version before depending on individual location-object fields.

Choose the event that matches the problem

A console event is useful when page code calls a console API. Puppeteer’s PageEvent reference also describes console messages emitted for page errors or warnings. An uncaught exception in page JavaScript has its own pageerror event. Errors thrown by your Puppeteer script belong to Node.js and need server-side logging or a Node.js debugger.

What happened Puppeteer path Next step
Page code called a console API page.on('console', ...) Inspect message text, type, location, stack locations, and arguments.
An exception escaped in page code page.on('pageerror', ...) Inspect the exception and debug the browser-side code path.
The automation script failed Node.js error handling Log or debug the Node.js exception; a page console listener will not capture it.
page.on('pageerror', error => {
  console.error('Uncaught page exception:', error);
});

page.on('console', msg => {
  if (msg.type() === 'error' || msg.type() === 'warn') {
    console.error({
      type: msg.type(),
      text: msg.text(),
      location: msg.location(),
      stackTrace: msg.stackTrace(),
    });
  }
});

These listeners report evidence; they do not diagnose the root cause automatically. Use the message and its locations to find the relevant browser-side code, then reproduce the issue and inspect that code in its execution context.

Read the stack locations systematically

  1. Start with the message. Record type() and text() so you know what the page reported.
  2. Check the message location. Use location() as the location associated with the console message.
  3. Review each stack entry. Iterate over the array from stackTrace(). Do not treat the array as a string or assume it has the same format as an exception stack.
  4. Correlate with the page code. Use the locations to investigate the page-side path that produced the message. If an uncaught exception is involved, inspect the separate pageerror event too.
  5. Check the execution context. Decide whether the issue is in browser client code, browser internals, or Node.js automation code before choosing a debugger.
page.on('console', msg => {
  const locations = msg.stackTrace();

  console.log(`<${msg.type()}> ${msg.text()}`);
  console.log('message location:', msg.location());

  for (const [index, location] of locations.entries()) {
    console.log(`stack location ${index}:`, location);
  }
});

This output pattern preserves the API’s structured values. It intentionally does not assume that every message has a nonempty stack array or that every location object contains a usable source position.

Make logging useful without losing context

For ongoing automation, capture the event fields together and label them as page output. Avoid logging only msg.text() if you need to trace where a message came from. Also avoid assuming that console arguments are all strings; preserve or inspect the values through args() where needed.

page.on('console', msg => {
  const record = {
    source: 'page-console',
    type: msg.type(),
    text: msg.text(),
    location: msg.location(),
    stackTrace: msg.stackTrace(),
    argumentCount: msg.args().length,
  };

  console.dir(record, { depth: null });
});

Install listeners before the page action that may trigger the message. If you attach them after navigation or after clicking a control, earlier events will already have passed.

Common problems and fixes

Symptom Likely cause Fix
Browser console output is missing from the terminal The page’s console API writes in the browser context; it does not directly log to Node.js. Register page.on('console', ...) and forward the fields you need.
No message arrives The listener was attached after the message, or the page action producing it has not run. Attach the listener before navigation or interaction, and ensure the relevant action occurs while the page is open.
The error does not appear in the console listener An uncaught page exception is being treated as though it were an ordinary console call. Also attach page.on('pageerror', ...).
The stack output looks like an object or array stackTrace() returns location entries, rather than an Error.stack string. Iterate over the entries and inspect them according to the installed API version.
There is no useful Node stack in page output The failure may be in Node.js, or the console message may not carry the exception information you expected. Wrap the automation flow in Node.js error handling and use the Node.js debugger for server-side failures.
Location data is sparse or not what you expected The API contract provides location values, but does not promise every message has rich or identical source detail. Log both location accessors and the message context; do not make your parser depend on undocumented fields.

Reliability, performance, and cost considerations

Console listeners are event handlers, so keep them focused. Excessive synchronous logging or retaining large amounts of event data can make an automation run harder to manage. Attach listeners early, keep the page alive through the work that can emit messages, and close the browser in a cleanup path.

For repeatable diagnosis, record the Puppeteer version alongside logs because API references and available details vary by version. Do not treat a missing console message as proof that the page succeeded: uncaught exceptions and Node.js failures are separate channels, and each needs its own handler.

For local Puppeteer automation, account for the browser process and the time needed to load the target page. A screenshot API can be an alternative when the goal is capturing a page image rather than instrumenting browser JavaScript. ScreenshotNeo offers a website screenshot API and MCP server; its billing rules say bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billed status.

Or skip the browser setup

If your goal is a screenshot rather than inspecting page JavaScript, ScreenshotNeo returns an image or PDF from one GET request. Cookie banners, popups, and chat widgets are removed before capture; 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, and paid plans start at $5 for 3,000. Every feature is on every plan. 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://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}`);

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Is stackTrace() the same as Error.stack?

No. Puppeteer documents it as an array of console-message stack locations, while Error.stack is an exception property.

Does page.on('console') catch every page failure?

No. Use pageerror for uncaught page exceptions and Node.js error handling for failures in the automation process.

Should I parse individual location fields?

Only against the API types for your installed Puppeteer version. Preserve the returned location objects unless your version’s documentation supports a specific field-level dependency.

References