The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →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:
- Run the tests with the HTML reporter enabled.
- Start
npx playwright show-reportin the container. - Bind the server to
0.0.0.0so Docker can forward traffic to it. - Publish container port
9323to a host port. - 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.
#1 Best Overall
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.
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.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRunning 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.
Rank #3
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.
Recommended Free Tools
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.
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.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.
The example below uses the documented request shape; replace the example URL with the reachable URL where you publish your report:
Best Value
- 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-reportagainst that directory. - Bind to
0.0.0.0. - Publish container port
9323and open the mapped host port. - Keep the Playwright package and image versions aligned.
- Add
--init --ipc=hostwhen 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.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →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.
Quick Recap
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.

