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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Short answer: configure Playwright Test to capture screenshots on failures, then upload the directory controlled by outputDir as a GitHub Actions artifact. A screenshot saved on the runner is not downloadable until the workflow uploads it. The two most common causes are a disabled or overridden use.screenshot setting and an artifact step that points at the wrong directory or never runs after the test command fails.

1. Enable failure screenshots in Playwright

Put the screenshot policy in the Playwright configuration that your CI command actually loads. The documented values are 'off', 'on', and 'only-on-failure'. For CI diagnostics, failure-only capture usually provides the useful evidence without creating an image for every passing test.

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

export default defineConfig({
  use: {
    screenshot: 'only-on-failure',
  },
});

only-on-failure does not mean “save a screenshot for every test.” A passing test should not be expected to leave a screenshot under this mode. If you need visual output for every test, use 'on'; use 'off' to disable screenshots.

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

Check for configuration overrides

Playwright projects can override a shared use block, and the command line can replace the output location. Inspect the effective project configuration, the config file selected by the invocation, and any project-specific settings. A correct setting in an unused configuration file has no effect.

2. Upload the directory after the test step

GitHub Actions does not automatically publish files created by Playwright. Add an artifact step whose path matches Playwright’s output directory and allow that step to run when tests fail.

- name: Run Playwright tests
  run: npx playwright test

- name: Upload Playwright test results
  if: ${{ !cancelled() }}
  uses: actions/upload-artifact@v5
  with:
    name: playwright-test-results
    path: test-results/
    if-no-files-found: warn
    retention-days: 14

The cancellation-aware condition is important. Without a condition, a later step can be skipped when npx playwright test exits non-zero. The sample keeps the upload step eligible after a test failure while still respecting workflow cancellation. Confirm that the action version matches your repository’s current conventions before copying it into a long-lived workflow.

Upload the right kind of output

Playwright’s HTML report directory and its test output directory are not necessarily the same. Screenshots, videos, and traces are written under outputDir; an HTML report is commonly generated elsewhere. If developers need both, upload both paths in separate artifact steps or use a parent directory that contains both.

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

3. Find the directory Playwright actually used

The default testConfig.outputDir is test-results under the package directory. Your configuration can change it, and --output <dir> can override it for a particular run.

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

export default defineConfig({
  outputDir: 'artifacts/pw',
  use: {
    screenshot: 'only-on-failure',
  },
});

With that configuration, the upload step must use artifacts/pw/, not test-results/:

- name: Upload Playwright output
  if: ${{ !cancelled() }}
  uses: actions/upload-artifact@v5
  with:
    name: playwright-output
    path: artifacts/pw/
    if-no-files-found: warn

Relative paths are resolved from the job’s workspace and its configured working directory. If tests run inside a subdirectory, make the upload path relative to that same workspace or use the appropriate subdirectory explicitly.

4. A practical diagnostic sequence

Confirm capture is enabled

Search the effective playwright.config.* for use.screenshot. Set it to 'only-on-failure' when failure evidence is the goal. Check project-level use blocks and command-line options for overrides.

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.

Confirm the test really failed

Failure-only capture is tied to a failed test. Do not use a passing test as proof that screenshot capture is broken when the policy is only-on-failure.

Confirm the loaded configuration

Monorepos and package-based workflows often contain several Playwright configurations. Verify the file loaded by the exact CI command and the package directory from which the command runs.

Confirm outputDir and --output

Look for a configured outputDir and inspect the workflow command for --output. The command-line value wins for that invocation, so the upload path must follow it.

Match the artifact path

If files exist on the runner but the downloaded artifact is empty, compare the configured output path, the job’s working-directory, and the upload step’s path. Keep if-no-files-found: warn while diagnosing so a missing directory is visible without hiding the earlier test failure.

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

Verify that the upload step ran

Open the workflow log and inspect skipped-step details. A normal later step may be skipped after a failing test command; use if: ${{ !cancelled() }} or another condition appropriate for your workflow.

Download and inspect the artifact

After the run, open the Actions run’s artifact list and download the artifact. Check its directory layout and filenames. If it contains a report but no screenshots, the workflow may be uploading only the report directory rather than the test output directory.

5. Use traces when a screenshot is not enough

A screenshot shows the final rendered state, but it does not show the sequence of actions, locator resolutions, network activity, or console details. Playwright recommends its Trace Viewer for CI failures instead of relying only on videos and screenshots.

With one retry enabled, a practical CI configuration is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { defineConfig } from '@playwright/test';

export default defineConfig({
  retries: process.env.CI ? 1 : 0,
  outputDir: 'test-results',
  use: {
    screenshot: 'only-on-failure',
    trace: process.env.CI ? 'on-first-retry' : 'off',
  },
});

on-first-retry records a trace for a test that is retried. If you do not use retries, retain-on-failure can retain traces for failed tests. Other documented retention choices include retain-on-first-failure. Choose the mode that preserves the failed attempt you need to diagnose; tracing every test can add substantial runtime and storage overhead.

To inspect a downloaded trace locally, run:

npx playwright show-trace path/to/trace.zip

The trace can also be opened through the HTML report when the attachment is present. Trace files and reports can contain page content, URLs, headers, and other diagnostic data, so apply your repository’s security and retention policy before publishing them as artifacts.

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

6. Match the fix to the symptom

Symptom Likely check Fix
No screenshot exists on the runner Capture mode, test result, loaded config, and output directory Set screenshot: 'only-on-failure', verify the test failed, and inspect the effective outputDir.
Screenshot exists on the runner but no artifact is downloadable Upload step condition or path Use a cancellation-aware condition and point path at the actual output directory.
HTML report downloads but screenshots or traces are absent Report directory differs from test output directory Upload the directory controlled by outputDir as well as the report directory.
A retry passes and the original failure evidence is needed Screenshot and trace retention policy Select a trace mode and retry policy that retain the failed attempt, such as on-first-retry with one retry or a failure-retaining mode without retries.
Artifact is empty Working directory, path spelling, or no failed tests Compare the job workspace with the configured path and keep if-no-files-found: warn while troubleshooting.

7. Sharding and parallel jobs

When a workflow shards tests, each shard produces its own report data and attachments. Give each shard a distinct artifact name so later jobs do not overwrite one another. Playwright’s sharding guidance uses per-shard blob-report artifacts and a later merge job; blob reports can include attachments such as traces and screenshot diffs. The same principle applies to failure screenshots: upload every shard’s output, then merge or inspect the artifacts deliberately.

8. Capture volume, runtime, and retention choices

Setting What it captures Typical use
screenshot: 'off' No screenshots Fast runs where traces or logs are sufficient
screenshot: 'only-on-failure' Failure screenshots Default diagnostic evidence for CI
screenshot: 'on' Every test Visual archives or investigations that require passing-state images
trace: 'on-first-retry' Traces for retried tests CI with retries enabled
trace: 'retain-on-failure' Retained traces for failures Failure evidence when retries are disabled

More screenshots and traces increase artifact size and upload time. Keep failure-only screenshots for routine runs, use traces for interaction history, and set an artifact retention period that matches your debugging and compliance needs.

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

9. Or skip the browser setup

If your goal is a clean image of a URL rather than Playwright interaction debugging, ScreenshotNeo provides a single-request screenshot API. It accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for the complete parameter reference. This cURL request saves a WebP image:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python equivalent:

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 request:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF output with paper size, margins, landscape mode and page ranges, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors, delays or network idle, ad/tracker/request/resource blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed links for public images, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

Plans include a free allowance of 1,000 screenshots per month with no card, Starter at $5 for 3,000, Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000. Yearly billing provides two months free, and every feature is included on every plan.

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

Create a free ScreenshotNeo account to get 1,000 screenshots a month without adding a card.

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.