Headless vs Headed in Playwright: Key Differences Explained

Understand Playwright headless vs headed mode, when to use each, performance differences, and how to configure them for debugging and CI.

Thumbnail 1

Playwright can run your browser tests in two ways: with a visible window you can watch, or completely in the background with no window at all. Most teams configure this once and never think about it again, until a test starts failing in CI that works perfectly on their machine.

The confusion around headless vs headed in Playwright comes down to one thing. Teams pick a mode without understanding what each one actually does, and they pay for it later with flaky tests, wasted CI minutes, or debugging sessions that take twice as long.

This guide breaks down exactly how headless and headed mode work in Playwright, when to use each, how to configure them in playwright.config.ts and the CLI, and the real performance differences you will see in your pipeline.

What is the difference between headless and headed mode in Playwright?

Headless mode runs the browser without opening a visible window. Headed mode opens a full browser window you can see and interact with. That is the core difference between headless vs headed in Playwright, and it affects speed, resource usage, and debugging ability.

In headless mode, the browser engine executes everything normally (loading pages, running JavaScript, rendering the DOM) but skips painting pixels to a display. In headed mode, a native browser window opens and every frame is rendered visually on your screen.

Here is a quick side-by-side comparison so the distinction is clear before going deeper.

Aspect Headless mode Headed mode
Browser window Not visible Visible on screen
Default in Playwright Yes No (must opt in)
Speed Faster Slower
CPU / Memory usage Lower Higher
Visual debugging Not possible (use Trace Viewer) Full real-time visibility
Best for CI/CD, regression suites, parallel runs Debugging, test development, visual verification
Requires display server No Yes
Chromium binary (default) Chromium headless shell Full Chromium browser

Playwright defaults to headless because most automated runs do not need a live window. But when you need to watch a test interact with the page, headed mode is the right call.

Debug Playwright tests faster
Get AI failure analysis and visual traces in one dashboard.
Start free CTA Graphic

How headless and headed mode actually work under the hood

Understanding how Playwright connects to browsers makes the headless vs headed distinction clearer. The difference is not about which browser engine runs. It is about the rendering path.

Playwright talks to browser engines through protocols: the Chrome DevTools Protocol (CDP) for Chromium, and patched internal APIs for Firefox and WebKit. Both headless and headed mode use the same protocol layer. If you want a deeper look at how this communication layer works, Playwright architecture breaks it down layer by layer.

Note: Since Playwright 1.40+, Chromium ships two separate binaries. Headless mode uses a lightweight chromium headless shell, while headed mode uses the full Chromium browser. This means the two modes can have subtle rendering differences in font smoothing and GPU handling. You can opt into the "new headless mode" by setting channel: 'chromium' in your config, which uses the full browser binary even in headless runs.

In headless mode:

  • The browser process starts without compositing pixels to a window.
  • Layout, JavaScript, network, and DOM all execute normally.
  • Screenshots, videos, and traces are still captured through internal APIs.

In headed mode:

  • A native window opens, and every frame is painted to the display.
  • The GPU pipeline handles compositing, animations, and visual effects.
  • This rendering loop is what makes headed mode consume more resources.

The key takeaway: headless is not a "lite" browser. It is the same engine, just without a visible output surface.

When should you use headless vs headed mode in Playwright?

Use headless mode for speed and efficiency. Use headed mode for visibility and debugging. The right choice depends on what you are doing at that moment.

Use headless mode when:

  • Running tests in CI/CD. Pipelines on GitHub Actions, Jenkins, or GitLab CI run on machines with no display server. Headless is the only option that works out of the box.
  • Executing large regression suites. Fewer resources per test means more parallel workers. This directly improves total execution time.
  • Web scraping or data extraction. You do not need a visible window to collect data.
  • Smoke tests and health checks. Quick validations where visual feedback is unnecessary.

Use headed mode when:

  • Debugging a failing test. Watching the browser step through each action reveals timing issues, wrong selectors, and layout shifts that logs alone cannot show. Playwright also offers --ui mode, which gives a visual inspector on top of headed execution.
  • Developing new test scripts. Seeing the browser react to your Playwright locators in real time speeds up authoring and lets you validate them visually.
  • Visual verification. Animations, hover states, CSS transitions, and drag interactions need a visible window to inspect properly. For structured visual checks, Playwright visual testing covers the snapshot workflow.
  • Demos and walkthroughs. When presenting test automation to stakeholders, a live browser window makes the value immediately obvious.

Tip: The recommended workflow for most teams: develop and debug tests locally in headed mode, then run them in headless mode inside CI. This gives you the best of both modes without any compromise.

How to configure headless and headed mode in Playwright

Playwright gives you three main ways to switch between headless and headed mode. You can set it in the config file, override it from the CLI, or pass it directly to browser.launch().

1. Using playwright.config.ts

This is the most common approach for Playwright test configuration. Set the headless property inside the use block.

playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    headlessfalse// launches a visible browser window
  },
});

Set headless: true (or simply remove the line, since true is the default) to go back to headless.

2. Using the CLI flag

Override the config for a one-off run without editing any files. This is the fastest way to disable headless Playwright for a quick debugging session.

terminal
# Run all tests in headed mode
npx playwright test --headed

# Run a specific test file in headed mode
npx playwright test tests/login.spec.ts --headed

# Open Playwright UI mode (headed + visual inspector)
npx playwright test --ui

The --headed flag temporarily overrides whatever is set in playwright.config.ts. The --ui flag opens Playwright's built-in UI mode, which provides a visual test explorer alongside headed execution.

3. Using browser.launch() in a script

When using Playwright as a library (outside the test runner), pass the option directly to run Playwright in a headless browser or a headed one.

script.js
import { chromium } from 'playwright';

const browser = await chromium.launch({
  headlessfalse// or true
});

Per-project configuration

You can also set different modes for different projects in the same config file. This is useful when running Playwright browser testing across Chromium, Firefox, and WebKit, each with its own mode.

playwright.config.ts
import { defineConfigdevices } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name'chromium-headless',
      use: { ...devices['Desktop Chrome'], headlesstrue },
    },
    {
      name'chromium-headed',
      use: { ...devices['Desktop Chrome'], headlessfalse },
    },
  ],
});

Using the new headless mode (Chromium)

If you want headless runs to use the exact same full Chromium binary as headed mode, set the channel to 'chromium'. This eliminates the Playwright headless false vs true difference in rendering behavior.

playwright.config.ts
import { defineConfigdevices } from '@playwright/test';
export default defineConfig({
  projects: [
    {
      name'chromium',
      use: {
        ...devices['Desktop Chrome'],
        channel'chromium'// uses full browser even in headless
      },
    },
  ],
});

Note: The new headless mode removes the rendering differences between headless and headed for Chromium. This is especially useful if your tests involve GPU-dependent rendering, font smoothing, or canvas operations. It was introduced in Chrome 112 and is the recommended approach for teams that need consistent behavior across both modes.

Performance: headless vs headed in Playwright

This is where the practical difference between headless vs headed in Playwright becomes measurable. The short answer: headless mode is faster and lighter.

Why headless is faster

Headless mode skips the entire rendering pipeline that paints content to your screen. That means:

  • No GPU compositing.
  • No window management overhead.
  • No paint frames sent to the display.

For a single test, the difference might feel small. But across 500 tests running in parallel, it compounds quickly. Teams with large suites often see 30% to 50% reduction in total pipeline time just by confirming headless is enabled.

Resource comparison

Metric Headless mode Headed mode
Avg. memory per browser context ~80 MB to 120 MB ~150 MB to 250 MB
CPU usage during test execution Lower (no paint thread) Higher (UI compositing active)
Parallel workers on 4-core CI 4 to 6 comfortably 2 to 3 before slowdown
Canvas-heavy operations Up to 10x faster (per Chromium team benchmarks) Baseline
Screenshot capture Via internal API (fast) Via internal API (fast)

Reproducible benchmark script

Want to see the difference on your own machine? Save this script as benchmark.js and run it with node benchmark.js. It measures exactly how long it takes to launch the browser, navigate, and close it 10 times in both modes.

benchmark.js
const { chromium } = require('playwright');

async function runBenchmark(headless) {
  const start = performance.now();
  for (let i = 0i < 10i++) {
    const browser = await chromium.launch({ headless });
    const page = await browser.newPage();
    await page.goto('https://playwright.dev');
    await browser.close();
  }
  const end = performance.now();
  console.log(`${headless ? 'Headless' : 'Headed'} took: ${((end - start) / 1000).toFixed(2)}s`);
}

(async () => {
  console.log('Running benchmark...');
  await runBenchmark(true);  // Headless
  await runBenchmark(false); // Headed
})();

Tip: If memory is a bottleneck in your CI runners, switching from headed to headless and increasing the worker count is one of the quickest wins you can get. You are essentially removing the display overhead and reinvesting those resources into parallelism.

Performance graph data

Headless vs headed mode in CI/CD pipelines

CI environments are where the headless vs headed decision has the most impact. The vast majority of production pipelines run headless by default.

Why headless dominates CI

Most CI runners (GitHub Actions, Jenkins agents, GitLab CI runners) operate in server environments with no display server. Running headed mode on these machines requires installing a virtual display like Xvfb on Linux, which adds setup complexity and resource overhead.

Headless mode works natively on these environments without any display dependency.

If you are setting up Playwright in a CI system for the first time, the Playwright CI/CD integrations guide covers GitHub Actions, Jenkins, and GitLab CI step by step.

A minimal CI config for headless execution

.github/workflows/playwright.yml
# .github/workflows/playwright.yml
namePlaywright Tests
on: [pushpull_request]
jobs:
  test:
    runs-onubuntu-latest
    steps:
      - usesactions/checkout@v4
      - usesactions/setup-node@v4
        with:
          node-version20
      - runnpm ci
      - runnpx playwright install --with-deps --only-shell
      - runnpx playwright test

The --only-shell flag skips downloading the full Chromium browser since you only need the headless shell in CI. This reduces install time and disk usage.

When headed mode is justified in CI

There are edge cases where headed mode in CI makes sense.

  • Visual regression testing. Some teams prefer headed mode to ensure pixel-accurate rendering. That said, Playwright's screenshot API works in headless mode too.
  • Record-and-replay debugging. When CI tests fail intermittently, recording a video in headed mode can reveal layout flashing or race conditions that headless Trace Viewer may not fully expose.

For most teams, though, headless is the default and the correct choice for CI.

Track CI test failures clearly
Centralized dashboards with AI failure insights for Playwright.
Start free CTA Graphic

Common pitfalls when switching between headless and headed mode

Knowing when to use each mode is half the story. The other half is avoiding traps that cause tests to behave differently across Playwright browser automation modes.

1. Tests pass in headed but fail in headless

This is the most common complaint when switching between headless vs headed Playwright runs. It usually happens because:

  • Font rendering differs. The headless shell uses a different font rasterizer. If your visual assertions compare pixel-level screenshots, fonts can cause mismatches.
  • Viewport defaulting. Headed mode may pick up your OS display settings. Headless uses the viewport size from your config. Always explicitly set viewport in playwright.config.ts.

playwright.config.ts
use: {
  viewport: { width1280height720 },
}

2. Tests become flaky only in headless

The root cause is rarely the mode itself. Common culprits:

  • Missing waits. In headed mode, the human eye tolerates small delays. Headless mode runs faster, which can expose race conditions. Use Playwright's built-in auto-wait and web-first assertions instead of hardcoded timeouts.
  • External dependencies. API calls, third-party scripts, or CDN resources that load inconsistently. Mock these in your tests.
  • Canvas or WebGL content. The default headless shell handles GPU differently. Switching to channel: 'chromium' fixes most of these issues.

The flaky test benchmark report shows that timing and environmental factors account for over half of all flaky tests, and these often surface when switching between headless and headed mode.

A flaky test is a test that passes and fails intermittently without any code change. In the context of headless vs headed mode, flakiness typically comes from timing differences, not the mode itself.

3. Visual tests break after switching modes

This happens when baselines were captured in one mode and tests run in another. The GPU pipeline difference between the headless shell and the full browser causes pixel-level changes.

Fix: Always capture baselines and run tests in the same mode. Or use the new headless mode (channel: 'chromium') so both modes use the identical browser binary.

4. Headed mode does not open on CI

If you set headless: false but run on a CI server with no display, Playwright will throw an error. The fix is either switching back to headless for CI or installing xvfb-run to simulate a display:

terminal
xvfb-run npx playwright test

Most teams avoid this entirely by keeping headless: true in config and only using --headed locally.

Tip: If you are experiencing mode-related flakiness and need real-time insight into failures across your CI runs, TestDino's Playwright observability platform groups recurring failures, classifies root causes with AI, and lets you track trends across headless and headed runs.

Ship tests that stay stable
AI-powered failure grouping and flaky test tracking in CI.
Start free CTA Graphic

Conclusion

Choosing between headless vs headed in Playwright is not about picking a "better" mode. Both exist because they solve different problems at different stages of your workflow.

Headless mode wins in CI/CD environments. It uses fewer resources, runs faster, and works on servers that have no display at all. Headed mode wins when you need to see what is happening. Debugging, test development, and visual verification all become easier with a live browser window.

The best approach is straightforward: run headless in your pipelines and switch to headed when something breaks and you need to investigate. Playwright makes toggling between the two as simple as a single config line or a CLI flag.

FAQs

Does Playwright run in headless mode by default?
Yes. Playwright runs in headless mode by default. No browser UI appears on screen. You can switch to headed mode by setting headless: false in your playwright.config.ts or by passing --headed via the CLI.
What is headless mode in Playwright?
Headless mode in Playwright runs the browser without a graphical user interface. It is faster since it skips rendering pixels to a display. It uses fewer resources, making it the standard choice for CI/CD pipelines.
When should I use headed mode in Playwright?
Use headed mode when debugging failing tests, verifying UI interactions visually, or writing new test scripts. It opens a real browser window so you can observe every step of the test in real time.
Is headless mode faster than headed mode in Playwright?
Yes. Headless mode is notably faster because it eliminates the rendering overhead of painting a browser window. The performance gap grows larger as suite size and parallelism increase.
How do I switch between headless and headed mode in Playwright?
You can toggle modes in playwright.config.ts by setting use: { headless: false } for headed mode. Alternatively, use the CLI flag npx playwright test --headed. To revert to headless, set headless: true or remove the flag.
Pratik Patel

Founder & CEO

Pratik Patel is the founder of TestDino, a Playwright-focused observability and CI optimization platform that helps engineering and QA teams gain clear visibility into automated test results, flaky failures, and CI pipeline health. With 12+ years of QA automation experience, he has worked closely with startups and enterprise organizations to build and scale high-performing QA teams, including companies such as Scotts Miracle-Gro, Avenue One, and Huma.

Pratik is an active contributor to the open-source community and a member of the Test Tribe community. He previously authored Make the Move to Automation with Appium and supported lot of QA engineers with practical tools, consulting, and educational resources, and he regularly writes about modern testing practices, Playwright, and developer productivity.

Get started fast

Step-by-step guides, real-world examples, and proven strategies to maximize your test reporting success