Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Capture Playwright browser diagnostics by registering listeners before navigation or the action that can produce them. Use page.on('console') for JavaScript console messages, page.on('pageerror') for uncaught exceptions, page.on('response') for HTTP status codes, and page.on('requestfailed') when a request never receives an HTTP response. For failures that need timeline and page context, enable a Playwright Test trace and inspect it in Trace Viewer.

The complete listener pattern

This Node.js example records the message type, values, URL, timestamp, uncaught exception stack, HTTP errors, and transport-level request failures. Attach every handler before page.goto() or the interaction under investigation.

import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage();

page.on('console', async msg => {
  const values = [];
  for (const arg of msg.args()) {
    try {
      values.push(await arg.jsonValue());
    } catch {
      values.push('[unserializable console argument]');
    }
  }
  console.log(JSON.stringify({
    kind: 'console',
    type: msg.type(),
    text: msg.text(),
    values,
    url: page.url(),
    at: new Date().toISOString()
  }));
});

page.on('pageerror', error => {
  console.error(JSON.stringify({
    kind: 'pageerror',
    message: error.message,
    stack: error.stack,
    url: page.url(),
    at: new Date().toISOString()
  }));
});

page.on('response', response => {
  if (response.status() >= 400) {
    console.error(JSON.stringify({
      kind: 'http',
      status: response.status(),
      url: response.url(),
      at: new Date().toISOString()
    }));
  }
});

page.on('requestfailed', request => {
  console.error(JSON.stringify({
    kind: 'requestfailed',
    url: request.url(),
    error: request.failure()?.errorText,
    at: new Date().toISOString()
  }));
});

await page.goto('https://example.com', { waitUntil: 'networkidle' });
await browser.close();

The Page API documents these events and the ConsoleMessage methods used above. Console arguments are remote JavaScript values, so jsonValue() can fail for values that cannot be serialized; keep a fallback rather than allowing logging itself to break your test.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What each event actually means

Console messages

page.on('console') receives browser console calls such as log, debug, info, warning, and error. Use msg.type() and msg.text() to filter or format them. A console error is a message deliberately written to the console; it is not automatically an uncaught exception.

Uncaught page exceptions

page.on('pageerror') fires when an exception escapes page JavaScript. Record both error.message and error.stack. A page can throw without calling console.error, so listening only for console messages misses this class of defect.

HTTP responses

page.on('response') fires when the browser receives an HTTP response. Inspect response.status() for 3xx, 4xx, and 5xx responses. A 404 or 503 is still an HTTP response, not a transport failure.

Requests that never obtain a response

page.on('requestfailed') is for failures such as DNS errors, refused connections, aborted requests, or other network problems where no HTTP response was received. The Request API explicitly distinguishes HTTP errors from failed requests: a 404 or 503 completes normally and does not trigger requestfailed solely because of its status.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Capture logs for one page

Page listeners are the narrowest and easiest scope. They are appropriate when a test owns one tab or when you want diagnostics tied to a specific navigation.

  1. Create the page.
  2. Register listeners.
  3. Navigate or perform the action that can emit events.
  4. Flush or persist your structured records before closing the browser.

Registering after goto() can lose startup errors, early console messages, and failed requests. For a click that opens a popup, attach listeners before the click when possible, and coordinate the popup with page.waitForEvent('popup').

Cover popups and multiple tabs with BrowserContext listeners

A context-wide listener observes pages created in that context, which is useful for popups, new tabs, and flows that switch windows. The BrowserContext API documents the context console event as available from Playwright v1.34 and weberror for unhandled page exceptions from v1.38.

const context = await browser.newContext();

context.on('console', msg => {
  console.log('[context console]', msg.type(), msg.text());
});

context.on('weberror', webError => {
  console.error('[context page error]', webError.error().message);
});

context.on('response', response => {
  if (response.status() >= 400)
    console.error('[context http]', response.status(), response.url());
});

context.on('requestfailed', request => {
  console.error('[context network]', request.url(), request.failure()?.errorText);
});

Context listeners broaden coverage, but add an identifier such as page.url(), a test name, or a page label to every record so simultaneous tabs remain distinguishable. If popup request observation must begin before the popup’s first request, use context request listeners or routing rather than waiting for the popup page event.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Retrieve recent messages after an action

Recent-history methods are useful when you do not want a live stream:

await page.getByRole('button', { name: 'Submit' }).click();

for (const message of await page.consoleMessages()) {
  console.log(message.type(), message.text());
}

for (const error of await page.pageErrors()) {
  console.error(error.message, error.stack);
}

page.consoleMessages() and page.pageErrors() were added in Playwright v1.56 and return up to 200 recent entries. They are a bounded buffer, not an archive. Documentation for v1.59 adds clearing stored console messages and filtering messages since navigation; check the API reference for the exact methods available in your installed version before using those additions. If you need every event, use listeners and write records as they arrive.

Choose the right capture strategy

Need Recommended method Important limitation
One page during a test Page console, pageerror, response, and requestfailed listeners Handlers must be attached before the relevant action.
Several pages in one context BrowserContext console, weberror, request, and response listeners Events from many tabs need page/test metadata.
Recent diagnostics after an action page.consoleMessages() and page.pageErrors() At most 200 recent entries; version-dependent additions in v1.59.
Failure with action and network context Playwright Test tracing and Trace Viewer Tracing is an artifact workflow rather than a continuous log sink.
Interactive investigation Playwright Inspector or UI Mode Interactive tools do not replace a deliberately exported log stream.

Use Trace Viewer when a log line is not enough

Listeners tell you what happened; a trace helps explain what was happening around it. Configure tracing through Playwright Test when you need actions, snapshots, console output, errors, network details, and assertions in one failure artifact. The Trace Viewer provides timeline and action filtering, while the Playwright Test configuration is preferable for complete test diagnostics.

// playwright.config.js
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    trace: 'retain-on-failure'
  }
});

Run the test, then open the generated ZIP with the documented Trace Viewer command or the HTML report. For a temporary investigation, trace: 'on' captures every test, but retaining traces only on failure reduces storage and report noise. The lower-level context.tracing API captures browser operations and network activity; it does not record test assertions, which is why Playwright recommends test-level configuration for test suites. See the Tracing API.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make logs useful in CI

  • Use structured records. Store event kind, ISO timestamp, test name, browser project, page URL, action name, status, and request URL.
  • Separate severity. Keep all console types during diagnosis; filter to warning and error only when volume is a problem.
  • Protect secrets. Redact authorization headers, cookies, tokens, and query parameters before uploading logs.
  • Bound output. A page can produce thousands of messages. Apply a size limit or stream JSON Lines to an artifact file.
  • Preserve the original error. Keep stack traces and request failure text; do not replace them with a generic “browser error.”
  • Correlate actions. Set a variable before a click or navigation so each event states which operation was active.

Troubleshooting common capture failures

No console output appears

Attach page.on('console') before navigation, verify that the code executes in the page (not only in Node.js), and check that the page actually calls a console method. If you attached to one page while the application opened another, move the listener to the context or the new page.

A JavaScript failure is missing

Use pageerror, not just console. For multiple tabs, add context weberror and confirm your Playwright version supports it.

requestfailed never fires for a 404

This is expected. A 404 has an HTTP response, so inspect it in the response handler. Reserve requestfailed for requests that did not obtain a response.

Only the first page is covered

Register context listeners before creating pages, or attach equivalent handlers to every page as it is created. Context-level listeners are usually safer for popup-heavy applications.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The history methods are unavailable

Check the installed Playwright version. The bounded consoleMessages() and pageErrors() methods require v1.56 or newer; v1.59-specific clearing and since-navigation behavior may not exist in earlier releases.

The trace has no assertions

Use Playwright Test’s trace configuration instead of only context.tracing. The lower-level API does not capture test assertions.

Logs are too noisy or break serialization

Filter by msg.type(), cap the number of records, and catch failures from jsonValue(). Serialize stable fields such as text, URL, status, and error stack rather than attempting to stringify every browser object.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost considerations

Listeners add little overhead when they write compact records, but serializing large console arguments and retaining unlimited arrays can consume memory. Prefer streaming or bounded buffers in long-running suites. Traces consume considerably more disk than plain logs because they include snapshots and network context; retain them on failure and clean old artifacts in CI. Network event handlers observe what Playwright reports, not every internal browser diagnostic, so they should not be treated as a complete DevTools protocol dump.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For deterministic results, register listeners before navigation, use explicit waits for the event-producing action, and close the context only after asynchronous log writes finish. Record the URL at event time because a later navigation can make a delayed handler’s current URL misleading.

Or skip the browser setup

If your goal is a clean visual record of a page rather than JavaScript diagnostics, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

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)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo documentation for authentication, formats, options, and response headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Further debugging tools

For step-by-step interactive diagnosis, use Playwright Inspector or UI Mode. For request interception and deeper network workflows, consult Playwright’s Network guide. These tools complement, rather than replace, explicit listeners and retained artifacts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Can Playwright capture browser console output from an iframe?

A page console listener receives console messages reported by the page and its frames. Include the message location and URL in your records when you need to identify the originating frame.

Should I fail a test on every console.error?

Not automatically. Applications and third-party scripts may log expected errors. Define an allowlist or fail only for selected message text, uncaught page errors, or HTTP statuses relevant to the test.

Are Playwright logs the same as Chrome DevTools logs?

No. Playwright exposes documented page and context events, not every browser-internal diagnostic shown by DevTools.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.