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

Debug a headless-browser failure by collecting evidence in order: reproduce the smallest failing case, inspect the action and page state, correlate console and network activity, then compare the result with the original CI environment. In Playwright, the Inspector and a headed run help you observe a live failure; a recorded trace and Trace Viewer preserve the evidence for later, especially when the failure occurs in CI.

What headless debugging actually requires

Headless mode means the browser runs without a visible window. Playwright runs browsers headless by default, while headless: false switches a launch to headed mode. The mode is only one variable in a larger system: browser version, operating system, viewport, permissions, network, authentication state, timing and test data can all affect the result.

A screenshot alone rarely identifies the cause. Reliable diagnosis combines the failed assertion and call log with the DOM at that moment, actionability information, browser and test console messages, network requests and the framework’s own launch or API logs.

A repeatable debugging workflow

1. Read the failure before changing anything

Start with the assertion, expected value, received value, call log and source line. The call log often tells you whether Playwright was waiting for a locator, attempting an action, retrying an assertion or failing during setup. Copy the exact URL, test name and browser project so you can reproduce the same path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Record the first failing action, not merely the final timeout.
  • Note whether the failure is a locator error, assertion mismatch, navigation error, browser-launch error or test-process error.
  • Preserve the CI job’s browser, operating-system and environment details.

2. Reproduce one failing test

Narrow the run to one test and, where practical, one browser project. A reduced reproduction makes the sequence visible and prevents unrelated tests from changing shared state. Keep the original URL, credentials, feature flags and test data; a simplified environment can hide the defect.

Use Playwright’s debug mode to open the Inspector for an interactive run. The Inspector can pause between actions, step through the test, edit locators live, pick locators from the page and show actionability logs. Debug mode launches the browser headed and uses a default timeout of zero, so a pause is useful for inspection but should not be mistaken for normal timing.

3. Make the browser visible when interaction is the question

If you need to see a menu, dialog, redirect or responsive layout, launch headed:

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

const browser = await chromium.launch({
  headless: false,
  slowMo: 150
});
const page = await browser.newPage();
await page.goto('https://example.com');
// Inspect the visible page or connect browser developer tools.
await browser.close();

slowMo makes actions easier to observe, but it changes timing. A headed success therefore does not prove that the headless failure is fixed. After making a change, rerun with the original headless configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

4. Record a trace for failures you cannot watch

Tracing is usually the most useful artifact for a CI-only failure. A Playwright trace gives you a time-ordered run that you can open in Trace Viewer. Move through each action and inspect its DOM snapshot, action details, source location, errors, console output, network requests and recorded screenshots when screenshot recording is enabled.

import { test, expect } from '@playwright/test';

test('checkout', async ({ page }, testInfo) => {
  await page.goto('https://example.com');
  await expect(page.getByRole('heading', { name: 'Checkout' })).toBeVisible();
});

Configure your project to retain a trace on the first retry or on failure, according to your team’s artifact policy. Open the resulting trace with the Trace Viewer supplied by your installed Playwright version. Keep traces from the failing CI job rather than replacing them with a local reproduction.

5. Correlate the failed action with page and network evidence

At the failed step, answer four questions:

  1. Does the expected element exist in the DOM snapshot?
  2. Does the action log show a wrong locator, an invisible element, an obstructed element or a failed navigation?
  3. Do browser or test console messages appear immediately before the failure?
  4. Did a required request fail, return an unexpected status or deliver different data?

Trace Viewer exposes these evidence types; it does not automatically assign a root cause. For example, a missing button may be a bad locator, a feature flag, a failed API request or a page that never finished initializing. Use the timestamp and action sequence to distinguish them.

6. Turn on verbose framework logs

When control flow or launch behavior is unclear, enable Playwright’s API logging:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
DEBUG=pw:api npx playwright test

For a browser that fails to launch, Playwright’s CI guidance identifies the browser-focused namespace as useful:

DEBUG=pw:browser npx playwright test

Debug namespaces and commands can vary by installed framework version. Confirm them against the documentation for that version, and avoid copying launch flags from an unrelated anecdote.

Choose the evidence that matches the question

Need Starting point Evidence
Step through one test interactively Inspector or debug mode Current action, locator picker, actionability logs and source line
Observe rendering or interaction Headed run with headless: false Visible layout, dialogs, focus and browser developer tools
Diagnose a past or CI failure Trace and Trace Viewer Timeline, DOM snapshots, actions, source, errors, console, network and screenshots
Understand launch or call flow Verbose framework logs API calls, browser startup and early-process failures
Use Puppeteer Puppeteer’s official debugging workflow Its headed-launch and Node/browser debugging tools; exact steps depend on the installed version

Choose based on four constraints: can you reproduce locally, must the evidence preserve CI conditions, do you need interactive control or post-run inspection, and is the question about page state, browser output, network activity or framework control flow?

Interpret common failure patterns

A locator or action fails

Inspect the locator and DOM snapshot at the exact action. Use the Inspector’s locator picker or live editing to test a more stable locator. Check actionability details for visibility, enabled state, attachment and obstruction. Prefer a locator tied to accessible role, label or a deliberate test identifier over a fragile CSS path.

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.
Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

The page looks wrong

Compare snapshots and screenshots immediately before and after the action. A headed run can reveal a collapsed menu, unexpected viewport, cookie dialog or focus problem. A screenshot proves only what was painted; use console and network evidence to explain why.

Data or assets are missing

Inspect requests associated with the failed action and their responses, then check console output for script or resource errors. Verify authentication, base URL, service availability, request interception and test data. A successful document navigation does not mean every API or image request succeeded.

The browser does not launch or the script stalls early

Run with framework and browser debug logging, then inspect the environment: browser binaries, permissions, sandbox settings, proxy, certificates, available resources and required system libraries. Separate a browser-process failure from a test that launched successfully but is waiting on navigation.

Only CI fails

Open the trace produced by the failing job first. Compare its browser project, viewport, timezone, locale, permissions, environment variables, network route and test data with local settings. A local headed success does not establish the CI cause; it may simply use different conditions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Headless versus headed: what changes

Headed mode is an observation aid, not a definitive oracle. Window compositing, timing, rendering, focus and developer-tool attachment can differ from headless execution. Use it to discover what the user or browser is doing, then reproduce the diagnosis under the original headless settings. Keep explicit viewport and browser settings so the comparison is meaningful.

Preserve useful artifacts without creating noise

  • Keep the failing trace, test output and relevant screenshots together as one CI artifact.
  • Record the exact test command and browser project used to create the artifact.
  • Redact credentials, tokens, personal data and sensitive request headers before sharing traces.
  • Capture only the logs needed for the failure; verbose output can obscure the first meaningful error.
  • After a fix, rerun the original failing test and a nearby regression case in headless mode.

Or skip the browser setup

If your task is simply to obtain a clean image or PDF of a website rather than debug your own automation, ScreenshotNeo provides a single HTTP endpoint at https://screenshotneo.com. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each 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. Its MCP server also gives AI clients such as Claude and Cursor take_screenshot, get_page_info and capture_pdf tools.

cURL

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 complete parameter reference in the ScreenshotNeo documentation. Options include full-page screenshots with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or a custom viewport, retina scale, PDF paper size and page ranges, HTML/CSS rendering, custom JavaScript and CSS, clicks, selector or network-idle waits, ad and tracker blocking, custom headers, cookies, user agents and authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it.

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

Debugging checklist

  1. Read the assertion, call log and source line.
  2. Reproduce one failing test with original conditions.
  3. Use Inspector or a headed run for live interaction questions.
  4. Capture a trace for CI or non-reproducible failures.
  5. Inspect DOM, actionability, console and network evidence together.
  6. Enable DEBUG=pw:api or browser logging when launch flow is unclear.
  7. Rerun headless after every diagnosis or code change.

Frequently Asked Questions

Does headless mode change the website itself?

It can change rendering, timing, focus and other execution conditions, so treat headed and headless runs as related but not identical environments.

Which artifact should I attach to a CI bug?

Attach the trace from the failing CI job, along with its test command and browser project. It preserves the environment-specific evidence that a local rerun may lose.

Can a trace replace server-side logs?

No. A trace shows browser-side actions, page snapshots, console output and requests; server logs may be required to explain backend errors or data differences.

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.

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.