npx playwright show-report: open, share and host the HTML report from CI
By TurnSignal · October 6, 2026 · 5 min read
In short
npx playwright show-reportserves the last HTML report fromplaywright-report/. Pass a folder or, in Playwright 1.63, the.zipyou downloaded from CI.- Don't open
index.htmlstraight from disk: Playwright's CI guide says the report needs a web server, andshow-reportis that server. - Use
--hostand--port(defaultlocalhost:9323) to change where it listens; in CI setopen: 'never'so nothing waits for a browser. - The report describes one run. For which failures are new, which tests are flaky over weeks and which never reported, you need results kept across runs.
What show-report does
The HTML reporter writes a self-contained folder at the end of a run. npx playwright show-report starts a small local web server for that folder and opens it in your browser. With no argument it opens the last report from the default folder, playwright-report/ in the current directory:
npx playwright show-report
If your config writes the report somewhere else (the outputFolder option of the html reporter, or the PLAYWRIGHT_HTML_OUTPUT_DIR environment variable), pass that folder:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['html', { outputFolder: 'my-report', open: 'never' }]],
});
npx playwright show-report my-report
open: 'on-failure'). In CI, set open: 'never' or PLAYWRIGHT_HTML_OPEN=never so the run never tries to start a browser.Opening a report downloaded from CI
In CI you usually upload playwright-report/ as a build artifact. On GitHub Actions the workflow Playwright generates already does this with actions/upload-artifact, and you download the artifact as a zip from the run summary page.
Playwright 1.63's show-report accepts that zip directly, as long as index.html is at the top level of the archive. Playwright extracts it to a temporary folder and serves it:
npx playwright show-report playwright-report.zip
On older versions, extract the zip first and pass the folder. Run the command in a project that already has @playwright/test installed, so npx uses that version instead of downloading one.
Why double-clicking index.html is not enough
Playwright's own CI guide says that opening the report locally does not work as expected without a web server. Parts of the report, traces in particular, are loaded by the page after it opens, and browsers restrict what a page opened from file:// may load. show-report serves the folder over http://localhost, so everything works, including the trace viewer behind each test.
Host and port
show-report listens on localhost port 9323 by default. Both can be changed:
npx playwright show-report --host 0.0.0.0 --port 8080
--host 0.0.0.0 makes the report reachable from other machines on your network, for example from a dev container or a VM. Anyone who can reach that port can read the report, including errors, screenshots and traces, so only do this on a network you trust. The host and port reporter options (or PLAYWRIGHT_HTML_HOST and PLAYWRIGHT_HTML_PORT) set the same values for the report that opens at the end of a local run.
Viewing traces from the report
When a test recorded a trace, the report shows a trace icon next to it. Click it to step through every action with the DOM snapshot, console and network requests at that moment. To get traces only when they help, record them on the first retry or keep them on failure:
use: {
trace: 'on-first-retry', // or 'retain-on-failure'
},
You can also open a single trace.zip without the report: npx playwright show-trace trace.zip, or drag it into trace.playwright.dev. Playwright documents that trace.playwright.dev loads the trace entirely in your browser and does not send it anywhere.
One report from sharded runs
When you shard (--shard=1/4 … --shard=4/4), each machine writes its own report. Opening four reports is slow and easy to get wrong. Make each shard write a blob report, download them into one folder, and merge them into a single HTML report that show-report can open:
# on each shard (playwright.config.ts: reporter: process.env.CI ? 'blob' : 'html')
npx playwright test --shard=1/4
# in a final job, with every shard's blob-report downloaded into ./all-blob-reports
npx playwright merge-reports --reporter html ./all-blob-reports
npx playwright show-report
Playwright's sharding guide has the full GitHub Actions workflow. The GitHub Actions setup guide on this blog walks through it step by step.
Sharing the report with your team
Downloading a zip and running a command is fine for the person debugging. It is a lot to ask of everyone else on a pull request. Teams usually do one of three things:
- Keep it as an artifact and link the run in the pull request. Simple, private to people with access to the CI, and limited by your artifact retention.
- Publish it as a static site. The report folder is plain files, so any static host works; Playwright's CI intro shows an example with Azure Storage static websites. Put access control in front of it: reports can contain error messages, screenshots and traces of your app.
- Send results to a service that keeps them across runs, so people get a link and a short verdict instead of a zip.
If you host the report under a strict Content Security Policy that blocks inline scripts, set doNotInlineAssets: true (or PLAYWRIGHT_HTML_DO_NOT_INLINE_ASSETS=1) so the JavaScript and CSS are written as separate files. If you upload the data folder with attachments to a different place than the report, attachmentsBaseURL tells the report where to find them.
What one report can't tell you
The HTML report is excellent at one thing: everything about a single run. The questions after a red pull request are usually about many runs:
- Did my change break this, or was it already failing on main? The report of your branch knows nothing about main.
- Is this test flaky, or is this the first time? The report sees the retries in this run, not the last hundred runs.
- Where did the missing tests go? If a shard was killed, for example out of memory, its part of the report may never be written, and those tests are simply not there.
TurnSignal answers those with one more reporter next to the HTML report: reporter: [['html', { open: 'never' }], ['turnsignal']]. Every run opens with a verdict, each failure is labelled new, also failing on main or known flaky, tests from a crashed runner are listed as Missing, and on GitHub the verdict is posted as a pull request comment. Traces open in the browser from the run page, without downloading a zip. The reporter never changes your exit code. The docs have the setup.
Questions people ask
Where does Playwright save the HTML report?
In playwright-report/ in the current working directory, unless you set outputFolder on the html reporter or the PLAYWRIGHT_HTML_OUTPUT_DIR environment variable.
Can I open a Playwright report zip without extracting it?
Yes, in Playwright 1.63: npx playwright show-report playwright-report.zip works when the archive has index.html at its top level. On older versions, extract it and pass the folder.
Why does the trace not open when I open index.html directly?
The report needs to be served by a web server. npx playwright show-report <folder> serves it on localhost, and traces open from there.
How do I stop the report from opening after every run?
Set open: 'never' on the html reporter, or PLAYWRIGHT_HTML_OPEN=never. The default is 'on-failure'.
Sources
- Playwright docs: Reporters (HTML reporter, show-report, options)
- Playwright docs: CI intro (downloading, viewing and hosting the HTML report)
- Playwright docs: Sharding and merging reports
- Playwright docs: Trace viewer
Playwright details were checked against Playwright 1.63 and its documentation on October 6, 2026.
Try TurnSignal on your next run
Add one reporter line next to your existing reporters. Free to start, no credit card, no repository access.