ScreenshotNeo

BlogHow-to

How to Show the Browser Window in Playwright

Run Playwright with a visible browser using headed mode, configure it for tests, debug interactively, and fix common display problems.

By the ScreenshotNeo team1 October 20266 min read

Playwright launches browsers headlessly by default. To show the browser window in a direct Playwright script, pass headless: false to the browser launch call:

import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com');
await page.waitForTimeout(3000);
await browser.close();

The same launch option works with Firefox and WebKit. Add slowMo when you want each action to be easier to follow. In Playwright Test, use npx playwright test --headed for one run, or set use.headless to false in the test configuration. Playwright documents these options in its debugging guide and test CLI reference.

1. Show the window in a standalone Playwright script

Install Playwright, then launch the browser with headless: false:

npm install playwright
npx playwright install
// show-browser.mjs
import { chromium } from 'playwright';

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

const page = await browser.newPage({
  viewport: { width: 1280, height: 800 }
});

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
await page.waitForTimeout(5000);
await browser.close();

Run it with:

node show-browser.mjs

headless: false controls whether the browser UI is visible. slowMo adds a delay to Playwright operations; it is useful for demonstrations and debugging, but it is not required to display the window.

Use another browser engine

import { firefox, webkit } from 'playwright';

const firefoxBrowser = await firefox.launch({ headless: false });
await firefoxBrowser.close();

const webkitBrowser = await webkit.launch({ headless: false });
await webkitBrowser.close();

Keep the window open while you inspect it

A script exits when it reaches the end, so close the browser only after your inspection or interaction is complete. A simple pause is enough for a short debugging session:

await page.pause();

page.pause() opens Playwright’s inspector and waits for you to resume. For a fixed delay, use await page.waitForTimeout(10000); avoid fixed delays in production tests when a locator or web assertion can express the condition directly.

2. Run Playwright Test in headed mode

For a single test run, add the --headed flag:

npx playwright test --headed

You can combine it with a project, file, or test filter:

npx playwright test tests/login.spec.ts --headed
npx playwright test --project=chromium --headed
npx playwright test -g "shows the dashboard" --headed

This changes the browser visibility for that invocation without changing your checked-in configuration.

3. Make headed mode the default in Playwright Test

Set use.headless to false in playwright.config.ts:

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

export default defineConfig({
  testDir: './tests',
  use: {
    headless: false,
    baseURL: 'http://localhost:3000'
  }
});

The Playwright Test default is headless mode. A command-line --headed run is convenient when you only occasionally need a visible window; configuration is better when a team regularly debugs tests locally. The configuration reference describes the use.headless setting.

4. Choose between headed, debug, and UI modes

Method Command or setting What you get
Headed run npx playwright test --headed A visible browser for the test run.
Persistent headed configuration use: { headless: false } Every test run in that configuration opens a browser window.
Debug mode npx playwright test --debug Headed mode plus the inspector, one worker, disabled timeout, and stop-after-failure behavior.
UI Mode npx playwright test --ui A visual test runner with actions, timeline, DOM snapshots, logs, errors, and network activity.

--ui shows Playwright’s test interface; it is different from making the browser itself headed. Use --debug when you need step-by-step inspection, and --ui when you want to explore test runs and traces. See the UI Mode documentation.

5. A complete headed test example

// tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('opens a visible page', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveTitle(/Example Domain/);
  await page.pause();
});
npx playwright test tests/example.spec.ts --headed

Use locators and assertions to wait for real conditions. A visible window does not change Playwright’s waiting behavior, browser context isolation, or test assertions.

6. Headed mode in containers, CI, and remote environments

A visible browser needs a graphical environment. On a normal desktop, Playwright can open a window directly. A container, SSH session, or CI runner may have no display server, so headless: false can fail even though the code is correct.

  • Run headed tests on a machine with a desktop display.
  • Use your environment’s display forwarding or virtual display setup when a graphical session is available.
  • Keep CI runs headless unless you specifically provide a protected display environment.

Playwright UI Mode can be exposed from Docker or Codespaces with --ui-host=0.0.0.0. Treat that as a network exposure: the documentation warns that traces, passwords, and secrets could become accessible to other machines. Bind it only in a suitable protected environment and avoid exposing it to an untrusted network.

7. Browser channels and headless behavior

Playwright uses a regular Chromium build for headed operation and a separate headless shell for its default headless mode. The browser guide also documents a newer Chrome-like headless mode through the chromium channel. Chrome and Edge channels can therefore behave differently from the default headless shell. If a rendering difference matters, test the channel you plan to use in production and keep the browser version pinned through your normal Playwright installation process.

8. Troubleshooting

Symptom Likely cause Fix
No window appears in a script The launch call still uses the default headless setting. Pass { headless: false } to chromium.launch(), firefox.launch(), or webkit.launch().
--headed is ignored You are running a standalone Node script instead of Playwright Test. Use the launch option in the script, or invoke the test with npx playwright test --headed.
Browser fails in Docker or CI No graphical display is available. Run headless, or provide a correctly configured protected display environment.
Window opens and closes immediately The script reached its end and closed the browser. Add an awaited interaction, page.pause(), or a temporary delay before browser.close().
Actions are too fast to follow Automation runs at full speed. Add slowMo to the launch options or use --debug.
UI Mode is visible but the browser is not UI Mode and headed mode are separate features. Use --headed as well when you need the browser window.
Different output between Chrome and Chromium Browser channels use different builds or headless implementations. Choose the intended channel explicitly and compare in that same channel.

9. Performance, reliability, and cost considerations

  • Headed mode adds the work of displaying a browser window and is generally best for local debugging, demonstrations, and investigating a failure.
  • Use headless mode for unattended CI when you do not need visual inspection.
  • slowMo deliberately slows operations, so remove it from normal runs.
  • Prefer locator waits and web assertions over arbitrary sleeps; they are less sensitive to network and rendering timing.
  • For repeatable debugging, record the browser engine, channel, viewport, and Playwright version used by the run.

Showing a local browser window does not create a screenshot service or an archival image. If your goal is to capture a URL reliably, use a capture API instead of maintaining browser display infrastructure.

10. Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF, so you do not need to install Playwright or provide a graphical environment for a capture.

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 ScreenshotNeo API documentation for request options and response details. Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, 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 lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

11. FAQ

Does headed mode require a special Playwright package?

No. It is a launch and test-run setting. Install the normal Playwright package and browsers.

Can I make only one test headed?

Yes. Run that test file with npx playwright test path/to/test.spec.ts --headed, or use a separate project configuration with use.headless: false.

Is headed mode required for screenshots?

No. Playwright can capture screenshots headlessly. Headed mode is useful when you need to see and debug the actions.

Why does a headed browser work locally but not on CI?

Local machines usually have a display server; many CI workers do not. Use headless mode in CI or configure a protected graphical environment.