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

Run Playwright’s report server inside the container, bind it to 0.0.0.0, and publish port 9323. Then open http://localhost:9323 on your host. Do not double-click index.html: the HTML report needs a web server and its companion data, screenshots, videos, and traces.

The reliable Docker workflow

A Playwright HTML report is a directory, normally playwright-report/, not an independent HTML file. The working sequence is:

  1. Run the tests with the HTML reporter enabled.
  2. Start npx playwright show-report in the container.
  3. Bind the server to 0.0.0.0 so Docker can forward traffic to it.
  4. Publish container port 9323 to a host port.
  5. Open the published host port in a browser.

The smallest command that serves an existing report in a running container is:

npx playwright show-report playwright-report --host 0.0.0.0 --port 9323

From another terminal, start the container with:

docker run --rm -p 9323:9323 your-playwright-image

Visit http://localhost:9323. If port 9323 is already occupied, choose another host port while leaving the container port unchanged, for example -p 8080:9323, and browse to http://localhost:8080.

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

Generate the report before serving it

Use the HTML reporter

Run:

npx playwright test --reporter=html

Unless configured otherwise, Playwright writes the report to playwright-report/. You can select another output directory in the reporter configuration or with the PLAYWRIGHT_HTML_OUTPUT_DIR environment variable. Pass that directory to show-report:

npx playwright show-report path/to/report --host 0.0.0.0 --port 9323

Keep the complete report tree

The report references its data files and attachments. Preserve the entire directory, including screenshots, videos, traces, and other files produced by the tests. Copying only index.html removes the resources the interface needs and can make sections appear empty or broken.

Serve a zipped report

show-report can serve a report directory or a report zip. A zip is useful when a CI system produces a single downloadable artifact, but extract or pass the complete archive rather than selecting one HTML file from it.

A production-ready Docker image

Pin the Playwright Docker image to the version used by your project. The image and the installed Playwright package should match; mixing versions can cause browser or report incompatibilities.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
FROM mcr.microsoft.com/playwright:<pinned-version>-jammy
WORKDIR /work
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["sh", "-c", "npx playwright test --reporter=html && npx playwright show-report playwright-report --host 0.0.0.0 --port 9323"]

Build and run it:

docker build -t pw-report .
docker run --rm -p 9323:9323 pw-report

This compact image starts the report server only when the test command succeeds. If you want to inspect a report even when tests fail, use a shell command that records the test status, starts the server, and returns the original status after the server exits:

CMD ["sh", "-c", "npx playwright test --reporter=html; status=$?; npx playwright show-report playwright-report --host 0.0.0.0 --port 9323; exit $status"]

For a long-lived review environment, it is often cleaner to run the tests in one container or CI job, retain the resulting directory, and run show-report in a separate container that mounts that directory.

Docker networking details

Why 0.0.0.0 matters

Playwright’s report server defaults to listening on localhost. Inside a container, that loopback interface is inside the container. Docker’s port-forwarding rule cannot reach a process that listens only there. --host 0.0.0.0 makes the listener available on the container’s network interface, allowing -p to forward it.

Container port versus host port

Purpose Example Browser address
Default mapping -p 9323:9323 http://localhost:9323
Different host port -p 8080:9323 http://localhost:8080
Bind only to the host loopback interface -p 127.0.0.1:9323:9323 http://localhost:9323

The number on the right is the port inside the container and must match --port. The number on the left is the port exposed on your host. Binding to 127.0.0.1 is a safer choice on a shared network because it avoids publishing the report on every host interface.

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

Running Chromium tests in Docker

When the same container also runs Chromium tests, Playwright recommends Docker’s --init and --ipc=host runtime settings. They address process reaping and Chromium shared-memory constraints. Add them to the test-running container command:

docker run --rm --init --ipc=host -p 9323:9323 pw-report

Use these settings for the test workload; a container that only serves already-generated static report files does not need a browser.

Keeping the server alive and the files available

Mount a report generated elsewhere

If tests run in CI or in a separate container, mount the finished directory read-only into a small Playwright image:

docker run --rm -p 9323:9323 
  -v "$PWD/playwright-report:/work/playwright-report:ro" 
  mcr.microsoft.com/playwright:<pinned-version>-jammy 
  npx playwright show-report /work/playwright-report --host 0.0.0.0 --port 9323

The host directory must contain the whole report tree. A read-only mount prevents accidental changes while someone reviews it.

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.

Wait for the service before opening it

Container startup and report generation are separate phases. In automation, wait until the report process is listening before opening a browser or running a smoke check. A simple check is:

curl --fail http://127.0.0.1:9323/

If the check runs from another container, use the service name and the container port instead of localhost; localhost would refer to the checking container itself.

Stop and clean up

--rm removes the serving container when it stops. It does not delete a bind-mounted report on the host. Without a volume, a report generated inside an ephemeral container disappears when that container is removed.

Why opening index.html directly fails

Playwright’s own guidance says that opening the report locally does not work as expected because the report needs a web server. The interface loads data and attachments through web requests; a file:// URL does not provide the same origin and request behavior. Symptoms include a blank page, missing test details, absent traces, or broken screenshot and video links.

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

Do not “fix” this by copying files into an arbitrary static folder while leaving out hidden or adjacent data. Start Playwright’s report server, or serve the complete report through a correctly configured static host that preserves its paths.

CI retention and sharing choices

Method Best for Trade-off
Local Docker port Immediate inspection by one developer Access ends when the container stops; usually reachable only from that machine
CI artifact Build-by-build retention and review inside the CI system Reviewers may need to download and extract the artifact; access follows CI permissions
Static hosting A stable URL for a team or external reviewer Requires storage, deployment, and deliberate access control

Upload the complete artifact

In CI, run tests in a compatible Linux environment or Playwright container, then upload the entire playwright-report/ directory. Do not upload only index.html. Artifact retention and visibility settings determine who can inspect the report.

Publish a stable URL

Playwright documents static website hosting, including Azure Storage static websites, as an option for reports that need a shareable address. Configure authentication or restricted access when appropriate rather than making test evidence public by default.

Protect sensitive test data

  • Screenshots can contain customer data, account details, or secrets rendered by the application.
  • Traces can include URLs, request information, and page content.
  • Videos may reveal credentials entered during a test.
  • Choose private CI artifacts or authenticated hosting when the report is not public.

Troubleshooting common failures

Symptom Likely cause Fix
Browser cannot connect to localhost:9323 The container is not running, the port was not published, or the process listens on container loopback only Confirm the container is running, add -p 9323:9323, and start show-report with --host 0.0.0.0
Address already in use Another process owns the host port Use a different host port, such as -p 8080:9323, and open that host port
Report page is blank or assets are missing index.html was opened with file://, or only part of the directory was copied Serve the directory with show-report and preserve every generated file
show-report says the directory is missing The report output path differs, the working directory is wrong, or a volume was mounted at the wrong path List the directory inside the container and pass its absolute path; check PLAYWRIGHT_HTML_OUTPUT_DIR
Container exits immediately The test command failed and the image uses &&, or the report server was never the foreground process Inspect test logs; use the status-preserving shell pattern above if you need the failed run’s report
Tests fail before a report is produced Dependencies, browser binaries, or the image/package versions do not match Run npm ci, use the browser image expected by the project, and align the Playwright package and image versions
Chromium crashes or runs out of shared memory The container lacks recommended runtime settings Run the test container with --init --ipc=host
Another container cannot reach the report It is using localhost, which points to itself Use the serving container’s Docker DNS name and port 9323, or publish the port to the host and connect through the host gateway

Performance, reliability, and cost considerations

Generation time versus viewing time

Report serving is lightweight once the files exist. Most time is spent running tests and collecting screenshots, videos, and traces. Keep the serving image separate from browser execution when you want a small, predictable review service.

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

Large reports

Full-page screenshots, videos, and traces increase artifact size and transfer time. Retain them when they are needed for diagnosis, but apply your CI retention policy and avoid copying the same report repeatedly between stages.

Port stability

Use the documented default 9323 for local conventions and simple links. In parallel CI jobs, assign different host ports or let each job run in its own network namespace; the container-side port can remain 9323.

Version alignment

Pin the base image tag rather than relying on a moving tag. Keep the version in the image aligned with the Playwright dependency declared by the project, then update both deliberately.

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

Or skip the browser setup

If your report is already available at a public or otherwise reachable HTTP(S) URL, ScreenshotNeo can capture that page without installing Playwright browsers in your own environment. It accepts a URL and returns PNG, JPEG, WebP, or PDF. The API removes cookie-consent banners, newsletter popups, and chat widgets before capture; bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Each response identifies the result with X-Page-Verdict and X-Billed headers.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

The example below uses the documented request shape; replace the example URL with the reachable URL where you publish your report:

Best Value
Docker Container Linux Devops Programming Coding T-Shirt
  • Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
  • Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem
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 API documentation for authentication and parameters. It also provides full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 shots per month without a card. Paid plans start at $5 for 3,000 shots; higher plans are Growth ($15 for 15,000), Pro ($39 for 60,000), Scale ($99 for 250,000), and Business ($249 for 1,000,000). Yearly billing provides two months free, and every feature is available on every plan. Sign up free for 1,000 screenshots a month with no card.

Practical checklist

  • Generate the report with --reporter=html.
  • Confirm the complete report directory exists inside the container.
  • Run show-report against that directory.
  • Bind to 0.0.0.0.
  • Publish container port 9323 and open the mapped host port.
  • Keep the Playwright package and image versions aligned.
  • Add --init --ipc=host when the container runs Chromium tests.
  • Retain the complete directory in CI and protect reports containing sensitive data.

Frequently Asked Questions

Can I expose the report on a different container port?

Yes. Pass another value to --port and publish the same container port, for example --port 9000 with -p 9000:9000. The host and container values do not have to be 9323.

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

Does show-report modify the report files?

It serves the directory; it does not replace the test artifacts. Mounting the directory read-only is suitable for a review-only container.

Is a Docker port enough to make a report public?

No. A published port makes the service reachable according to the host and network firewall rules. Public sharing also requires a routable host, firewall configuration, and access controls.

What should I archive when a test fails?

Archive the complete HTML report directory produced by that run, including attachments. If your container currently exits on a failed test because of &&, use the status-preserving command so the report server still starts.

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.