ScreenshotNeo

BlogHow-to

Playwright screenshot is black: Chromium launch and GPU fixes

Diagnose black Playwright screenshots by checking the capture, browser mode, launch logs, and CI environment before changing Chromium flags.

By the ScreenshotNeo team4 October 20266 min read

A black Playwright screenshot is a symptom, not a diagnosis. First verify what was captured and whether the page rendered; then compare headed mode with the default headless browser and with Playwright’s newer Chromium headless mode. Record launch logs and the environment before trying a Chromium flag. Playwright’s documentation does not identify one universal GPU flag that fixes black screenshots.

1. Confirm the capture and page state

Check that the file exists, is non-empty, and is the screenshot from the run you are investigating. Confirm the target URL, viewport, and whether the call requests a viewport capture or a full-page capture. If possible, open the image and determine whether the whole image is black or only a region is.

Capture options can change dimensions or background behavior, but they do not generally repair a page that rendered black. For example, fullPage captures the full page, omitBackground makes the default background transparent, and scale selects CSS-pixel or device-pixel output. See the Page screenshot API.

const fs = require('node:fs');
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
  await page.goto('https://example.com', { waitUntil: 'load' });
  console.log({ url: page.url(), title: await page.title() });
  await page.screenshot({ path: 'debug.png' });
  console.log('bytes:', fs.statSync('debug.png').size);
  await browser.close();
})();

Replace the URL with the failing page. If the page may be blank or incomplete, preserve a trace with screenshots and DOM snapshots. A trace helps inspect what happened during navigation and capture; it does not by itself identify a GPU cause.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  await context.tracing.start({ screenshots: true, snapshots: true });
  const page = await context.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: 'trace-check.png' });
  await context.tracing.stop({ path: 'trace.zip' });
  await browser.close();
})();

See Playwright tracing for trace options and viewing guidance.

2. Compare headed and headless browser modes

Playwright runs browsers headlessly by default. Its default Chromium headless execution uses a separate headless shell; setting channel: 'chromium' opts into the newer headless mode described in the browser documentation. A headed run and a channel comparison are diagnostic experiments, not guaranteed fixes.

Compare default headless with the Chromium channel

const { chromium } = require('playwright');

(async () => {
  for (const options of [{}, { channel: 'chromium' }]) {
    const browser = await chromium.launch({ headless: true, ...options });
    const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
    await page.goto('https://example.com', { waitUntil: 'load' });
    const name = options.channel || 'headless-shell';
    await page.screenshot({ path: `${name}.png` });
    console.log(name, await page.title());
    await browser.close();
  }
})();

Run headed mode where a display is available:

const browser = await chromium.launch({ headless: false });

On Linux CI, Playwright says headed execution requires an X server such as Xvfb. For a controlled comparison, keep the URL, viewport, browser version, and page state identical. Change only the mode under investigation.

3. Record the environment and launch diagnostics

Rendering can vary with host OS, browser version, browser settings, hardware, power source, and headless mode. Record the Playwright version, browser and channel, OS or container image, and whether the run is headed. Keep screenshot comparisons in the same environment where possible; Playwright’s visual comparisons guide warns that rendering differs across environments and recommends using the same environment as the baseline.

Enable browser launch logs before changing arguments:

DEBUG=pw:browser npx playwright test

On Windows PowerShell, set the environment variable for the command using the shell’s environment-variable syntax. Inspect the launch output and browser errors. Preserve the original configuration, then change one justified variable at a time so results remain interpretable.

4. Check installation and CI dependencies

In minimal Linux containers or CI images, confirm that the Playwright browser and its operating-system dependencies are installed. Playwright documents this command for Chromium:

npx playwright install --with-deps chromium

For headed Linux CI, also ensure Xvfb is available. Compare the same job in its normal and diagnostic browser modes before attributing the symptom to GPU acceleration. See the official continuous integration guide.

5. Change Chromium launch arguments cautiously

Playwright exposes launch settings such as headless, channel, chromiumSandbox, and custom args. Its BrowserType documentation cautions: “Use custom browser args at your own risk, as some of them may break Playwright functionality.” Do not copy a GPU flag as a universal remedy. If evidence points to a specific environment interaction, test one argument in isolation, save the before-and-after logs and screenshots, and remove the argument if it does not help.

const browser = await chromium.launch({
  headless: true,
  // Add a single evidence-based argument here only for a controlled test.
  args: []
});

Consult BrowserType launch options for the current supported options. Avoid replacing Playwright’s managed launch configuration wholesale: custom arguments can interfere with the browser behavior Playwright expects.

6. Troubleshooting by symptom

Symptom Likely check Next step
The output file is missing, empty, or stale Wrong path, failed run, or inspecting an earlier artifact Log the output path, verify file size and timestamp, and use a unique filename per diagnostic mode.
The page and screenshot are both blank or black Navigation or page state may not have completed Log the final URL and title, preserve a trace, and inspect its snapshots and browser activity.
Only full-page output is affected Capture dimensions or page content that loads while scrolling Compare a viewport screenshot with fullPage; inspect the page state and lazy-loaded content before changing launch settings.
Headed and headless results differ Mode-specific rendering or display setup Compare the same run with the Chromium channel. On Linux CI, verify Xvfb for headed mode.
Only a minimal Linux container fails Browser or OS dependencies may be missing Install Chromium and dependencies with npx playwright install --with-deps chromium.
A custom launch argument changes the result or breaks automation The argument may affect browser or Playwright behavior Remove it, return to the baseline, and retest one argument at a time with launch logs.
Visual output differs across machines OS, browser version, settings, hardware, power, or headless mode differ Run comparison and baseline generation in the same environment; record version and mode.

7. Reliability, performance, and cost considerations

For a reliable diagnosis, preserve the browser version, environment, mode, URL, viewport, and trace alongside the image. Avoid treating a single successful flag experiment as proof of a general fix. A mode or launch change can alter rendering and automation behavior, so validate the actual page and any dependent interactions after changing configuration.

Headed runs require a display environment on Linux CI, and collecting traces or multiple diagnostic screenshots adds artifacts and execution steps. Use these selectively to investigate failures; keep routine screenshot comparisons on a consistent, documented environment. The cited Playwright documentation does not publish a universal black-screenshot fix, performance benchmark, or cost figure.

Or skip the browser setup

ScreenshotNeo takes a screenshot through one API request, with API documentation for options:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with response headers indicating the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Learn about ScreenshotNeo.

Sign up free for 1,000 screenshots a month, no card required.

FAQ

Does a black screenshot prove Chromium’s GPU acceleration is broken?

No. It is a symptom with several possible causes, and the reviewed Playwright documentation does not define one GPU-specific diagnosis or universal flag.

Which headless mode does Playwright use by default?

Chromium’s separate headless shell. The chromium channel opts into the newer headless mode.

Can screenshot options fix a black rendered page?

Options such as full-page capture, scale, and transparent background change capture behavior; they are not documented as general rendering fixes.