Playwright Test Report: Comprehensive Guide [2026]

Playwright reporters turn test results into terminal, HTML, or structured output. Learn how each reporter works and choose the right one for your tests.

Last updated: 22 July 2026 20 min read

Key Takeaways

  • Playwright reporters are built for different outputs. List, Line, and Dot show execution progress, while HTML, JSON, JUnit, and Blob serve post-run reporting needs.
  • For CI, combine reporters by purpose. Use compact terminal output for progress, JUnit for CI test results, and HTML for detailed failure investigation.
  • Sharded test runs need Blob reports from every shard before results can be merged. CI must also retain reports and debugging artifacts after jobs finish.

Playwright has eight built-in reporters, but they all solve very different problems. Some are designed for readable terminal output, others produce files that CI systems can process, while Blob reports make it possible to combine results from sharded test runs.

Most teams therefore need more than one reporter as their test suite grows. Whether you are new to Playwright reporters or have been working with them across large test suites, this article will help you understand the available options, their use cases, and how to configure them for different testing requirements.

What are Playwright Reporters?

Playwright reporters determine how test results are displayed or written after and during a test run. Depending on the reporter you choose, the output can appear directly in the terminal or be generated as an HTML, JSON, JUnit XML, or Blob report.

Playwright includes built-in reporters for common local and CI requirements. You can also run multiple reporters together, create a custom reporter when you need specific test data, or integrate third-party reporting tools for additional reporting capabilities.

How Do Playwright Reporters Work?

Playwright reporters work by receiving events from the test runner throughout test execution and converting that information into the configured output. The process works as follows:

  1. The test run starts: Playwright loads the reporter configured through the command line or the playwright.config file.
  2. The reporter receives test events: As tests run, Playwright passes execution events to the reporter. These can include when the test run begins, when individual tests start and finish, test status, duration, errors, and output written during execution.
  3. Test results are collected: When a test finishes, the reporter receives its result. This can include the final status, retry information, execution time, errors, and attachments such as screenshots or traces when they have been captured by the test configuration.
  4. The reporter processes the results: Each reporter handles this information differently. List and Dot reporters print progress to the terminal. JSON and JUnit convert results into structured formats. HTML creates a browsable report, while Blob preserves detailed test-run data that can later be merged with results from other runs.
  5. The final output is generated: Once execution finishes, the configured reporter completes its output. If multiple reporters are configured, the same test run can produce different outputs for different purposes, such as terminal feedback for developers and structured results for CI.

Built-in Playwright Reporters

Playwright provides eight built-in reporters for different reporting requirements. Some provide immediate feedback during a test run, while others generate output that can be reviewed, processed, or combined after execution.

Each reporter serves a different purpose, from tracking a local test run to producing results for CI pipelines and post-run analysis.

1. List Reporter

The List reporter prints each test on a separate line with its status and execution time. It gives you enough detail to follow individual tests without waiting for the entire run to finish.

For example, if you are debugging 20 checkout tests locally, you can see which tests have completed and identify the failed test directly from the terminal. You can also configure the reporter to print individual test steps or show failure details as soon as a test fails.

Use when: Running a focused set of tests where individual test names and progress are useful.

Avoid when: Running a large regression suite in CI. Printing a separate line for every test can create thousands of log entries and make failures harder to locate.

2. Line Reporter

The Line reporter keeps the terminal output compact by using the same line to show the most recently completed test. Unlike the List reporter, it does not keep adding a new line for every successful test.

This makes it useful when you still want to see which part of the suite is running but do not need a permanent terminal entry for every passing test. If a test fails, the failure is printed separately instead of being overwritten by the next progress update.

For example, during a 2,000-test regression run, the Line reporter lets you track execution progress without filling the terminal with 2,000 successful test entries.

Use when: You want live test progress with less terminal output than the List reporter.

Avoid when: Your CI system does not handle live terminal output well or when you need the complete list of executed tests preserved in the console logs.

3. Dot Reporter

The Dot reporter represents each completed test with a single character. A dot represents a passed test, while separate characters indicate failures, retries, flaky tests, timeouts, and skipped tests.

It is useful for large CI runs where the console should show that tests are progressing without printing every test name. Playwright uses Dot as the default reporter on CI for this reason.

For example, a regression suite with several thousand tests can still show continuous execution progress without producing several thousand lines of output. Detailed failures are reported separately.

Use when: Running large suites in CI where compact console output is more useful than individual test names.

Avoid when: You are debugging a smaller set of tests and need to see exactly which test is running. A stream of status characters gives very little context until a failure is reported.

4. HTML Reporter

The HTML reporter generates a report that you can open in a browser after the test run. It is better suited to investigation than terminal reporters because you can navigate through the completed test results instead of searching through CI logs.

A practical use case is a failed nightly regression run. The HTML report can be retained as a CI artifact and opened later to inspect the affected tests and available attachments from that specific execution.

The default report is written to the playwright-report directory. You can change the output folder and control whether the report opens automatically after execution.

Use when: You need a browsable report for investigating completed test runs or sharing test results with other engineers.

Avoid when: Another system needs to programmatically process the results. HTML is intended for human inspection, so JSON or JUnit is a better output for downstream processing.

5. Blob Reporter

The Blob reporter stores detailed information about a test run in a format that Playwright can process later. Its main use case is report merging for tests executed across multiple shards.

Consider a regression suite split across 10 CI machines. Each shard produces its own results, so generating an HTML report independently on every machine leaves you with 10 separate reports. Blob reports can be collected after all shards finish and merged to generate one report for the complete test run.

Blob reports are therefore usually an intermediate reporting format rather than the report someone opens to investigate a failure.

Use when: Tests are sharded across multiple CI jobs and the results need to be combined into one report.

Avoid when: You only need a report from a single test run and have no requirement to merge results. Generating Blob output adds an unnecessary intermediate step in that case.

6. JSON Reporter

The JSON reporter produces structured test-run data that can be read and processed programmatically. This makes it useful when Playwright results need to feed another script, internal service, or reporting system.

For example, you may need to extract failed tests after every run and send their metadata to an internal dashboard. Processing JSON is much more reliable for this than parsing terminal output.

One configuration detail matters here: if an output file is not configured, the JSON report is written to standard output. On a large test run, that can flood the CI logs with the complete JSON result.

Use when: Test results need to be processed by your own scripts, services, or data pipelines.

Avoid when: You only need a report that engineers can read directly. Raw JSON is difficult to inspect manually and provides little benefit if nothing consumes the structured data. Also avoid leaving the output file unconfigured for large CI runs if you do not want the complete report printed to stdout.

7. JUnit Reporter

The JUnit reporter generates test results in JUnit-style XML. The format is widely understood by CI and test-management systems, which makes it useful when Playwright results need to be published through an existing CI reporting interface.

For example, if a pipeline already collects JUnit XML from unit and integration tests, Playwright can produce the same format. The CI system can then display the browser test results alongside the rest of the test suite without requiring a separate reporting flow.

As with JSON, the output location should be configured explicitly when the report needs to be retained as a file.

Use when: Your CI platform or another downstream system expects JUnit XML test results.

Avoid when: You need Playwright-specific test data that the JUnit format does not represent well. Converting everything into a common XML format is useful for compatibility but can be limiting when a downstream workflow needs richer Playwright result data.

8. GitHub Reporter

The GitHub reporter is designed for tests running in GitHub Actions. When a test fails, it creates annotations that surface the failure directly in the GitHub interface.

This is useful for a pull request validation workflow because developers can see test failures without first opening the raw workflow logs. It can also be combined with another reporter if the pipeline needs a separate report for later investigation.

There is one important limitation. Playwright does not recommend using the GitHub reporter with a matrix strategy because failure annotations from multiple matrix jobs can multiply and clutter the GitHub file view.

Use when: Playwright tests run in GitHub Actions and failure annotations would help developers review failed pipeline runs.

Avoid when: Running Playwright through a large GitHub Actions matrix. Repeated annotations from parallel jobs can create more noise than useful failure context.

How to Configure Playwright Reporters

Playwright reporters can be configured for a single test run from the command line or added to the Playwright configuration file when you want to use the same reporter across runs.

Step 1: Choose the Reporter

Start by choosing the reporter based on how you need to use the test results. For example, use List for readable terminal output, HTML for a browsable report, or JUnit when your CI system expects XML results.

Step 2: Configure the Reporter from the Command Line

Use the –reporter option when you need a reporter for a specific test run without changing the project configuration.

npx playwright test --reporter=html

This runs the tests with the HTML reporter.

For another reporter, replace html with the required reporter name:

npx playwright test --reporter=list

Command-line configuration is useful for temporary changes. For example, you may normally use a compact reporter but switch to HTML while investigating a failing test run.

Step 3: Add the Reporter to the Playwright Configuration

For a reporting setup that should apply to every test run, configure the reporter in playwright.config.ts.

import { defineConfig } from '@playwright/test';



export default defineConfig({

  reporter: 'html',

});

Playwright will now use the HTML reporter whenever the test suite runs with this configuration.

Step 4: Add Reporter-Specific Options

Some reporters accept additional configuration. For example, the HTML reporter can be configured so the report does not automatically open after the test run:

import { defineConfig } from '@playwright/test';



export default defineConfig({

  reporter: [

    ['html', { open: 'never' }]

  ],

});

Reporter-specific options should be configured based on where the tests run. Automatically opening an HTML report may be useful locally but serves no purpose in a CI job.

Step 5: Run the Tests and Access the Output

Run the test suite normally:

npx playwright test

The output depends on the configured reporter. Terminal reporters print results during execution, while file-based reporters generate their configured output after the run.

For example, the HTML reporter creates a report that can be opened with:

npx playwright show-report

Once the basic reporter configuration is in place, you can configure multiple reporters for the same test run when different consumers need different forms of output.

How to Generate Multiple Reports in Playwright

A single reporter is often not enough when test results have more than one consumer. A CI system may need JUnit XML to publish test results, while developers need an HTML report to investigate failures from the same run.

Playwright can run multiple reporters together without executing the test suite again.

Step 1: Open the Playwright Configuration

Open playwright.config.ts and locate the reporter option. Instead of passing a single reporter, configure an array containing each reporter you need.

Step 2: Add Multiple Reporters

The following configuration generates an HTML report and a JUnit XML file from the same test run:

import { defineConfig } from '@playwright/test';



export default defineConfig({

  reporter: [

    ['html', { outputFolder: 'playwright-report', open: 'never' }],

    ['junit', { outputFile: 'test-results/results.xml' }],

  ],

});

The HTML report can be used to investigate individual failures, while results.xml can be passed to a CI system that accepts JUnit results.

Step 3: Run the Test Suite

Run Playwright as usual:

npx playwright test

Both reporters receive results from the same execution. Playwright does not run the tests separately for each configured reporter.

Step 4: Retain the Required Outputs

In CI, generating the files is only part of the setup. The report directories or files must also be uploaded as pipeline artifacts if you need access to them after the job finishes.

This is particularly important for HTML reports. If the CI runner is removed after execution and the playwright-report directory is not retained, the report is lost with the job.

The same setup can include a terminal reporter alongside file-based reporters. For example, Dot can keep the CI logs compact while HTML is retained for debugging and JUnit feeds the CI test-results interface.

How to Merge Playwright Reports from Sharded Test Runs

When a large Playwright suite is split across multiple shards, each shard runs only part of the test suite. That creates a reporting problem: each job has its own results, while the team usually needs one report for the complete run.

The Blob reporter is designed for this workflow.

Step 1: Configure the Blob Reporter

Set the Blob reporter in playwright.config.ts:

import { defineConfig } from '@playwright/test';


export default defineConfig({

  reporter: 'blob',

});

Each shard will now generate its own Blob report after execution.

Step 2: Run the Tests Across Shards

For example, the suite can be split into four shards:

npx playwright test --shard=1/4

The remaining jobs run:

npx playwright test --shard=2/4

npx playwright test --shard=3/4

npx playwright test --shard=4/4

Each shard produces results for only the tests assigned to that shard.

Step 3: Collect the Blob Reports

Upload the Blob report from every shard as a CI artifact, then download all of them into the same directory in a separate merge job.

The important part is that the merge job must have access to the results from every shard. If one shard fails before its report is uploaded, the final report will not represent the complete test run.

Step 4: Merge the Reports

Once all Blob reports are available in one directory, merge them into a single HTML report:

npx playwright merge-reports --reporter html ./all-blob-reports

Playwright reads the results from the separate shard runs and generates one combined report.

Step 5: Retain the Final Report

Upload the merged HTML report as a CI artifact so it remains available after the merge job finishes.

This gives you one place to review the complete run instead of opening a separate report for each shard.

How to Create Custom Playwright Reporters

Built-in reporters cover most reporting requirements, but they cannot account for every workflow. A custom reporter is useful when test results need to be processed in a way that none of the standard output formats support.

For example, you may need to send only failed test results to an internal service, record additional test metadata, or produce an output format required by an existing reporting system.

Step 1: Create the Reporter File

Create a file such as my-reporter.ts. A custom reporter can implement the reporter methods that are relevant to your requirement.

The following example records failed tests and prints a summary when the run finishes:

import type {

  Reporter,

  TestCase,

  TestResult

} from '@playwright/test/reporter';



class FailureReporter implements Reporter {

  private failures: string[] = [];



  onTestEnd(test: TestCase, result: TestResult) {

    if (result.status !== 'passed') {

      this.failures.push(test.title);

    }

  }



  onEnd() {

    console.log(`Failed tests: ${this.failures.length}`);



    for (const test of this.failures) {

      console.log(`- ${test}`);

    }

  }

}



export default FailureReporter;

This example uses onTestEnd() to inspect the result of every completed test. The reporter stores tests that did not pass and uses onEnd() to print the final failure summary.

Step 2: Choose the Reporter Events You Need

A custom reporter does not need to implement every available method. Add handlers only for the points in the test run where your reporting logic needs data.

Common reporter methods include:

  • onBegin() for logic that should run when the test suite starts.
  • onTestBegin() for actions required when an individual test starts.
  • onTestEnd() for processing the result of a completed test.
  • onStdOut() and onStdErr() for handling output produced during execution.
  • onEnd() for generating a final summary or completing post-run reporting.

For example, a reporter that only exports failed tests may need onTestEnd() and onEnd(). Adding logic for every lifecycle event would make the reporter harder to maintain without improving the output.

Step 3: Configure the Custom Reporter

Add the reporter file to playwright.config.ts:

import { defineConfig } from '@playwright/test';


export default defineConfig({

  reporter: './my-reporter.ts',

});

The custom reporter will now receive events whenever the test suite runs.

You can also run it alongside a built-in reporter:

import { defineConfig } from '@playwright/test';



export default defineConfig({

  reporter: [

    ['./my-reporter.ts'],

    ['html', { open: 'never' }],

  ],

});

This is useful when the custom reporter handles a specific integration while the HTML reporter remains available for failure investigation.

Step 4: Keep Reporting Logic Separate from Test Logic

A reporter should consume test results rather than control test execution. Avoid placing retry decisions, test setup, or application cleanup inside reporter methods.

Reporter hooks can also run frequently. For a large suite, performing a slow network request inside onTestEnd() for every test can add unnecessary work to the reporting process. Collecting the required results and processing them in batches at the end of the run is usually more practical.

Note: A custom reporter is worth building when the reporting logic itself is specific to your workflow. If the requirement is simply to export test results in a standard format, check whether JSON, JUnit, or another built-in reporter already provides the required data before maintaining a separate reporter implementation.

How to Choose the Right Playwright Reporter

The right reporter depends on what needs to happen with the test results. A reporter that works well while debugging locally may create unnecessary output in CI, while a format designed for another system may be difficult for an engineer to investigate directly.

RequirementReporterWhy it fits
Follow individual tests during a local runListKeeps test names and results visible in the terminal
Track a larger run without filling the terminalLineShows current progress with less persistent output
Keep CI console output compactDotReduces thousands of test results to status characters
Investigate completed test runsHTMLProvides a browsable report for reviewing individual results
Combine results from sharded runsBlobPreserves results that can be merged after all shards finish
Process test results with scripts or internal systemsJSONProvides structured test data that can be parsed directly
Publish results to a CI system that accepts JUnit XMLJUnitProduces a widely supported test-results format
Surface failures directly in GitHub ActionsGitHubAdds test failure annotations to the GitHub workflow

You may also need more than one reporter for the same test run. For example, Dot can keep the CI logs readable, JUnit can publish results to the CI platform, and HTML can be retained for debugging failed tests.

Configure each reporter for a specific requirement rather than generating multiple report formats by default.

Using Playwright Reporters in CI/CD Pipelines

Reporting in CI requires more than selecting a reporter in playwright.config.ts. The test process ends when the job finishes, so any report you want to inspect later must be written to a file and retained outside the runner.

A practical CI reporting setup should account for the following:

  • Keep console output manageable: Large suites can make List output difficult to scan. Dot or Line provides execution progress without filling the job logs with every passing test.
  • Store reports before the runner is removed: An HTML report generated inside a CI job is lost if its output directory is not uploaded as an artifact. The same applies to JSON, JUnit, and Blob files needed by later jobs.
  • Separate machine-readable and debugging output: JUnit may be required by the CI platform to publish test results, but it is not necessarily the best format for investigating a failed browser test. Multiple reporters can cover both requirements in the same run.
  • Collect all shard results before merging: When tests run across multiple CI jobs, each Blob report must reach the merge job. A missing shard report leaves the final merged report incomplete.
  • Set report retention deliberately: Test reports can become large when runs include traces, screenshots, and videos. Retaining every artifact from every successful run can quickly increase storage usage. Longer retention is generally more useful for failed or release-critical runs than routine successful executions.

The reporter configuration should match the pipeline that consumes it. A pull request check, a nightly regression suite, and a sharded cross-browser run may all need different reporting outputs even when they execute the same Playwright tests.

Common Challenges in Playwright Reporting

A report can be generated successfully and still be of little help when a test fails. Most reporting problems come from missing execution context, incomplete CI artifacts, or reports that become difficult to use as the test suite grows.

1. Missing Failure Artifacts

An HTML report cannot show a trace, screenshot, or video that was never captured during the test run. Reporter configuration and artifact configuration are separate, so enabling the HTML reporter alone does not guarantee that all debugging evidence will be available.

Configure traces, screenshots, and videos based on when they are actually needed. For example, retaining traces on the first retry can provide failure context without storing a trace for every successful test.

2. Reports Lost After CI Execution

A report may exist correctly inside the CI runner but disappear when the job ends. This commonly happens when the report is generated but its output directory is never uploaded as a pipeline artifact.

Any report needed after execution should be persisted before the runner is removed. This also applies to Blob reports that a later job needs for merging.

3. Incomplete Reports from Sharded Runs

Each shard only knows about the tests it executes. Opening the report from one shard therefore does not give you the result of the complete suite.

Generate Blob reports for the individual shards, collect all of them, and merge the results after every shard finishes. The merge process should also account for failed jobs so that one unsuccessful shard does not prevent its report artifact from being collected.

4. Too Much Data in Large Reports

As suites grow, retaining every trace, screenshot, and video can make reports expensive to store and slow to move between CI jobs. More artifacts also do not automatically make a failure easier to investigate.

Capture evidence around failure conditions instead of treating every execution the same. Successful tests usually need less retained data than failed or retried tests.

5. Results Without Enough Test Context

A failure such as Expected 200, received 500 says very little if the report does not make it clear which environment, project, browser, retry, or test data produced it.

Test names, project configuration, annotations, attachments, and failure messages should provide enough context to distinguish one execution from another. This becomes particularly important when the same test runs across several browser and operating system combinations.

6. Mixing Results from Different Runs

Report directories reused across CI runs can leave stale output behind if they are not cleaned or isolated correctly. The resulting report may contain files that do not belong to the current execution.

Give each run its own output location or clean the relevant report directories before execution. For merged reports, make sure the merge job only downloads Blob files produced by the run being processed.

Conclusion

Playwright reporters serve different requirements across local testing and CI. Terminal reporters provide quick execution feedback, while HTML, JSON, JUnit, and Blob reports support debugging, external processing, and distributed test runs.

As your test suite grows, the reporting setup should grow with it. Choose reporters based on how the results will be used, combine them when different outputs are required, and retain the failure context engineers need to investigate issues without rerunning the entire suite.

Version History

  1. Jul 22, 2026 Current Version

    Revamped the article with updated information, deeper technical insights, and practical examples to make the content more useful and remove generic AI-style explanations.

    Grandel Robert
    Reviewed by Grandel Robert Senior Automation Expert
Tags
Automation Testing Local Testing Playwright Real Device Cloud
Venkatesh Raghunathan
Venkatesh Raghunathan

Full Stack Software Developer

Venkatesh Raghunathan is a Full Stack Software Developer with 11+ years of experience in software development, test automation, and web application engineering. He writes about automation testing, development workflows, and practical engineering approaches that help teams build reliable software products.

Go Beyond Basic Test Reports
Debug failures with logs, screenshots, videos, and traces on real devices.