The ConsoleMessage class represents messages logged by the page to the browser console. Listen for console messages using the page.on('console') event.
Overview
import { test } from '@playwright/test';
test('capture console messages', async ({ page }) => {
page.on('console', msg => {
console.log(`Console ${msg.type()}: ${msg.text()}`);
});
await page.goto('https://example.com');
await page.evaluate(() => console.log('Hello from the page'));
});
Methods
type()
Get the type of the console message.
Returns: string
Possible values:
'log'
'debug'
'info'
'error'
'warning'
'dir'
'dirxml'
'table'
'trace'
'clear'
'startGroup'
'startGroupCollapsed'
'endGroup'
'assert'
'profile'
'profileEnd'
'count'
'timeEnd'
page.on('console', msg => {
if (msg.type() === 'error') {
console.error('Page error:', msg.text());
}
});
text()
Get the text of the console message.
Returns: string
page.on('console', msg => {
console.log(msg.text());
});
args()
Get the list of arguments passed to the console method.
Returns: JSHandle[]
Each argument is represented as a JSHandle that can be evaluated:
page.on('console', async msg => {
const args = msg.args();
for (const arg of args) {
const value = await arg.jsonValue();
console.log(value);
}
});
location()
Get the location in the source code where the console method was called.
Returns: { url: string, lineNumber: number, columnNumber: number }
URL of the script where console was called
Line number in the script (0-based)
Column number in the script (0-based)
page.on('console', msg => {
const location = msg.location();
console.log(`Console at ${location.url}:${location.lineNumber}`);
});
timestamp()
Get the timestamp when the message was logged.
Returns: number
Timestamp in milliseconds since Unix epoch:
page.on('console', msg => {
const time = new Date(msg.timestamp());
console.log(`Message at ${time.toISOString()}: ${msg.text()}`);
});
page()
Get the page that emitted the console message.
Returns: Page | null
Returns null if the message came from a worker:
page.on('console', msg => {
const sourcePage = msg.page();
if (sourcePage) {
console.log(`Message from page: ${sourcePage.url()}`);
}
});
worker()
Get the worker that emitted the console message.
Returns: Worker | null
Returns null if the message came from a page:
page.on('console', msg => {
const worker = msg.worker();
if (worker) {
console.log(`Message from worker: ${worker.url()}`);
}
});
Examples
Filter by Message Type
test('capture errors only', async ({ page }) => {
const errors: string[] = [];
page.on('console', msg => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
await page.goto('https://example.com');
// Assert no errors occurred
expect(errors).toHaveLength(0);
});
Log with Source Location
page.on('console', msg => {
const location = msg.location();
console.log(
`[${msg.type()}] ${msg.text()} ` +
`(${location.url}:${location.lineNumber}:${location.columnNumber})`
);
});
Inspect Complex Objects
page.on('console', async msg => {
console.log(`Type: ${msg.type()}`);
// Get all arguments
const args = msg.args();
for (let i = 0; i < args.length; i++) {
const value = await args[i].jsonValue();
console.log(`Arg ${i}:`, value);
}
});
// In page
await page.evaluate(() => {
console.log('User:', { name: 'Alice', age: 30 });
});
Collect Console Timeline
test('console timeline', async ({ page }) => {
const timeline: Array<{ time: number, type: string, text: string }> = [];
page.on('console', msg => {
timeline.push({
time: msg.timestamp(),
type: msg.type(),
text: msg.text(),
});
});
await page.goto('https://example.com');
// Print timeline
timeline.forEach(entry => {
const time = new Date(entry.time).toISOString();
console.log(`${time} [${entry.type}] ${entry.text}`);
});
});
Distinguish Page vs Worker
page.on('console', msg => {
if (msg.page()) {
console.log('Page console:', msg.text());
} else if (msg.worker()) {
console.log('Worker console:', msg.text());
}
});
Best Practices
Always Check Message Type
Different message types may require different handling:
page.on('console', msg => {
switch (msg.type()) {
case 'error':
console.error(msg.text());
break;
case 'warning':
console.warn(msg.text());
break;
default:
console.log(msg.text());
}
});
Handle Async Operations
If you need to evaluate JSHandles, make the listener async:
page.on('console', async msg => {
const args = msg.args();
for (const arg of args) {
try {
const value = await arg.jsonValue();
console.log(value);
} catch (e) {
// Handle evaluation errors
}
}
});
Dispose JSHandles
JSHandles keep objects in memory. Dispose them when done:
page.on('console', async msg => {
const args = msg.args();
for (const arg of args) {
const value = await arg.jsonValue();
console.log(value);
await arg.dispose(); // Free memory
}
});