Skip to main content

Reporter & attachments

Browser logging has three destinations. Each is controlled by its own option and can be set to true (always), false (never) or 'on-failure'.

DestinationOptionDefaultColours
Console (sink)print'on-failure'Follow colors (auto-detected)
Report attachmentattach'on-failure'Never. Plain text
Per-test filefilefalseNever. Plain text
info

Files and attachments never contain ANSI escape sequences, whatever colors says, and control characters in logged text are escaped.

The browser-log attachment​

For a failed test, the HTML report and any reporter that lists attachments show an attachment named browser-log (text/plain) with the same timeline as the console block. With attachFormat: 'jsonl' it is named browser-log.jsonl (application/x-ndjson).

use: { browserLog: { attach: true } } // attach for passing tests too

Per-test files​

use: {
browserLog: {
file: 'on-failure',
fileFormat: 'jsonl',
fileDir: 'logs/browser',
},
}
  • With fileDir, files are named <test title>-<id>[-retryN][-repeatN].<ext> where <ext> is txt or jsonl. The id is derived from the test, so the same test always maps to the same name and retries and repeats never overwrite each other.
  • Without fileDir, the file is browser-log.txt / browser-log.jsonl in the test's output directory (testInfo.outputPath()), which Playwright manages.
  • The logger creates the directory if needed and never deletes or cleans any directory.
Playwright cleans its output folder

Playwright empties outputDir at the start of each run. Files written there disappear with it. Use fileDir outside test-results for logs you want to keep.

JSONL format (schema v1)​

One JSON object per line. Every event has:

FieldTypeMeaning
v1Schema version.
seqnumberMonotonic sequence number within the session.
tnumberMilliseconds since the session started (monotonic clock).
tsstringWall-clock ISO timestamp.
kindstringThe event kind, see below.
pagenumber?Page id (page#N). Only set when the session has more than one page.
stepstring[]?Enclosing test.step titles, outermost first. For step events: the parent steps only.

Fields are not in a guaranteed order. Kinds and their extra fields:

kindExtra fields
actioncategory (action/wait/query/navigation), target (page, frame, locator, elementHandle, keyboard, mouse, touchscreen, clock, context, browser, dialog, download), subject?, method, args, redacted?, status (ok/error/pending), durationMs?, slow?, error? (name, message), location? (file, line, column)
navigationurl
pageevent (opened/popup/closed/crashed), url?, opener?
consolelevel, text, location?
pageerrormessage, stack?
networkmethod, url, resourceType, status?, durationMs?, failure?
dialogdialogType, message
downloadurl, suggestedFilename
stepphase (start/end), title, status? (passed/failed/skipped), durationMs?
notemessage
apitext (a copied apiLog block, see below)
droppedcount (events lost to maxEvents)

A real line (a masked fill):

{"v":1,"seq":3,"t":134.396,"ts":"2026-10-29T19:41:56.965Z","step":["Log in"],"kind":"action","category":"action","target":"locator","subject":"locator('#password')","method":"fill","args":"***","redacted":true,"status":"ok","durationMs":29}

All values are redacted before they are stored, so the JSONL is safe to hand to tooling under the same rules as the text.

Find the slowest actions of a run, or every failed action, with jq:

jq -s 'map(select(.kind=="action")) | sort_by(-.durationMs) | .[:5][] | {method, subject, durationMs}' logs/browser/*.jsonl
jq -c 'select(.kind=="action" and .status=="error")' logs/browser/*.jsonl

API lines in the browser log​

With includeApiLog: true (the default) the lines printed by apiLog during a test are copied into the browser-log attachment and files as api events, so a failing end-to-end test shows its HTTP calls in the same timeline. They are never printed twice and are not part of the live console output or the failure block. An API-only test (no browser activity) produces no browser-log output at all.

If you want API lines in the report without any browser activity, attach them yourself with a sink:

import { test } from 'playwright-logger-pro/fixtures';

const lines: string[] = [];
test.use({ apiLog: { colors: false, sink: (line) => lines.push(line) } });

test.afterEach(async ({}, testInfo) => {
if (lines.length) await testInfo.attach('api-log', { body: lines.join('\n'), contentType: 'text/plain' });
lines.length = 0;
});

The curl.sh attachment​

When apiLog.curl is on and a test produced curl commands, the request fixture attaches curl.sh (text/plain) to the report, whatever the test status, and keeps the file in the test's output directory. This is the format: 'verbose' file. It holds the plain, redacted commands: no ANSI codes, *** in place of every masked value. Its header is #!/bin/sh, the spec file and line of the test (relative to the config's rootDir or testDir, control characters removed) and a generic comment; the test title is not in the file. The console notice is curl.sh: attached to the test report (see "curl.sh" in the HTML report; also saved in this test's output folder) and names no path, because Playwright's output folder is derived from the test title. See API logging › The curl.sh file. Turn it off with apiLog: { curlFormat: { file: false } }.

With the default compact format the scripts are curl.sh (or curl-{n}-{METHOD}-{lastPathSegment}.sh, text/x-shellscript), attached only for a failed test or with details: 'always', and each masked value is a ${VAR} placeholder with a guard instead of ***: export the variables, then run bash curl.sh. See Compact output.

Reporters​

ReporterBehaviour
list, line, dotThe failure block is worker stdout, which these reporters forward to the terminal, with ANSI colours when colors is on.
htmlShows the browser-log attachment on the failed test. The attachment is plain text.
githubThe block is in the job log, where Actions renders ANSI colours.
json, junit, blob, customAttachments and stdout are reported according to each reporter's own rules.

The console block is written through sink (default console.log), so it appears in the worker's stdout. If your CI log viewer does not render ANSI colours, set colors: false or NO_COLOR=1.

Sharding and merge-reports​

The attachment is part of the test result, so sharded runs and merge-reports keep it. Files written with fileDir are written on the machine that ran the test; collect them as artifacts from every shard.

Step locations in the trace viewer​

Wrapper frames are hidden from Playwright's stack attribution. Steps and errors in the HTML report and the trace viewer point at your spec file, and this also applies to request.* calls of the apiLog fixture. If locations ever point into node_modules, see Troubleshooting.