ScreenshotNeo

BlogEngineering

Puppeteer Console Message Location Explained

Use Puppeteer’s console event and `msg.location()` to find a message’s source URL and zero-based line and column, while handling missing values.

By the ScreenshotNeo team4 October 20266 min read

When a page emits Puppeteer’s console event, call msg.location() on the ConsoleMessage to get its source location. The returned object has optional url, lineNumber, and columnNumber fields. The numeric coordinates are zero-based, and any field may be undefined.

Get the console message location

Register a listener on a Puppeteer Page. This runnable example launches Chromium, navigates to a page that logs a message, prints its text and location, then closes the browser:

const puppeteer = require('puppeteer');

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

    page.on('console', msg => {
      const { url, lineNumber, columnNumber } = msg.location();
      console.log({
        type: msg.type(),
        text: msg.text(),
        url,
        lineNumber,
        columnNumber
      });
    });

    await page.goto('https://example.com', { waitUntil: 'load' });
    await page.evaluate(() => console.log('Page is ready'));
  } finally {
    await browser.close();
  }
})().catch(error => {
  console.error(error);
  process.exitCode = 1;
});

The documented interface is in Puppeteer’s ConsoleMessage API reference and ConsoleMessageLocation reference. Match those references to the Puppeteer version installed in your project: the live class and location pages have displayed different version labels.

Interpret the location fields

Field Meaning What to account for
url URL of the resource, when known May be undefined, for example when no resource URL is available.
lineNumber Source line, when known Zero-based; line zero is the first line. May be undefined.
columnNumber Source column, when known Zero-based; column zero is the first column. May be undefined.

These are source coordinates, not a ready-formatted editor link. If you display them to a person using one-based numbering, convert only defined values by adding one, and label that convention. Keep the raw Puppeteer values when passing them to code that expects zero-based coordinates.

function formatLocation(location) {
  const { url, lineNumber, columnNumber } = location;
  return {
    url: url ?? '(unknown URL)',
    line: lineNumber === undefined ? '(unknown line)' : lineNumber + 1,
    column: columnNumber === undefined ? '(unknown column)' : columnNumber + 1
  };
}

page.on('console', msg => {
  console.log(formatLocation(msg.location()));
});

Do not use a truthiness check for coordinates: zero is a valid first line or column. Check specifically for undefined.

Understand console events and message types

Puppeteer dispatches ConsoleMessage objects through the page’s console event. It covers JavaScript console API calls such as console.log() and console.dir(); the event documentation also describes page errors and warnings. Read msg.type() and msg.text() alongside the location so you know what the coordinates refer to. See the official PageEvent documentation.

A location is useful for identifying where the browser attributes a message. It does not guarantee that the URL is a local source file: it may point to a remote script, an inline page resource, or a generated or bundled resource. Source maps and editor navigation are separate concerns.

Choose between location() and stackTrace()

location() returns one primary source-location object. Use it for a compact log or a link to the reported source coordinate. stackTrace() is a separate method that returns an array of stack locations; inspect it when the primary location is insufficient and you need the message’s stack-location data.

page.on('console', msg => {
  const primary = msg.location();
  const stack = msg.stackTrace();

  console.log({
    text: msg.text(),
    primary,
    stack
  });
});

Do not assume the stack array is non-empty or that every location contains all coordinates. Treat each entry’s fields as optional too. The API documents the methods and return shapes; it does not promise that every browser message can be mapped to a useful source line.

Log locations reliably

  1. Attach the event listener before the action or navigation that may emit the message, so early messages are not missed.
  2. Read msg.location() inside the callback while you have the message object.
  3. Preserve undefined fields in structured logs, or replace them with explicit placeholders for display.
  4. Include message type and text with the location; coordinates without the message are hard to diagnose.
  5. For an editor-facing display, convert zero-based coordinates to one-based values deliberately and only after checking for missing values.

For repeatable diagnostics, consider collecting records rather than printing ad hoc strings:

const consoleMessages = [];

page.on('console', msg => {
  consoleMessages.push({
    type: msg.type(),
    text: msg.text(),
    location: msg.location(),
    stack: msg.stackTrace()
  });
});

Troubleshooting

Symptom Likely cause Fix
msg.location is not a function The callback value is not a Puppeteer ConsoleMessage, or code is using an API object from a different library or wrapper. Confirm the listener is page.on('console', msg => ...) on a Puppeteer Page, then check the API reference for your installed version.
URL or coordinates are undefined The browser did not provide that location component for the message. Handle absent values explicitly; use message text and type, and inspect stackTrace() if stack locations may help.
Line points one row earlier than expected Puppeteer coordinates are zero-based while many editors display one-based line numbers. Add one only for human-facing display. Keep zero-based values in machine-readable output.
No message was logged The listener may have been attached after the message, the page may not have emitted a console event, or navigation/action may not have completed as expected. Attach the listener before navigation or evaluation, and ensure the code path actually emits a console call.
Location points into bundled or minified code The browser reported the resource coordinate it knows; it may not correspond directly to authored source. Inspect the stack locations and configure source maps in the debugging environment where appropriate. Do not assume location() resolves source maps for you.

Performance, reliability, and cost

Reading the location in an event callback is a small diagnostic operation; the main cost of a Puppeteer workflow is generally the browser and page work around it. Avoid doing expensive synchronous processing in the callback if messages are frequent. For high-volume pages, collect only the fields needed and write or aggregate records outside the hot path.

Location data is best-effort: URL and coordinates are optional, so downstream loggers should accept missing values. This API reference does not specify a monetary price for the method itself; operational costs depend on how and where you run Puppeteer and Chromium. Browser launches, navigation, retries, and retained logs are the factors to budget and manage.

Or skip the browser setup

If your goal is to capture the page visually rather than inspect a console message, ScreenshotNeo is a website screenshot API and MCP server for developers. It returns a PNG, JPEG, WebP, or PDF from one GET request. Its API documentation covers the 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
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', image);
  • Cookie banners are accepted and removed before capture; more than 60 known consent platforms, newsletter popups, and chat widgets can be removed, with each step configurable.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 screenshots; all features are on every plan.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Does location() return a string?

No. It returns a location object with optional URL, line, and column fields.

Are line and column numbers one-based?

No. Puppeteer documents them as zero-based. Convert for display only when needed.

Should I use location() or stackTrace()?

Start with location() for the primary position. Use stackTrace() when you need the array of stack locations as well.