How to Use Playwright UI Mode for Browser Testing
Launch Playwright UI Mode, select browser tests, inspect traces and locators, and choose the right debugging workflow for local development and CI.
Start Playwright UI Mode from a project configured for Playwright Test with npx playwright test --ui. It opens an interactive test runner where you can select tests, watch them rerun as you edit, inspect action timelines and page snapshots, and refine locators. Use UI Mode for interactive local debugging; use --debug when you want the separate Playwright Inspector workflow, and configure trace capture in CI when you need failure evidence from automated runs.
1. Install and launch UI Mode
UI Mode is part of Playwright Test. If the project is not set up yet, create a starter project with the official command:
npm init playwright@latest
Follow the prompts to choose JavaScript or TypeScript and configure the project. Then run the UI runner from the project directory:
npx playwright test --ui
This is the core command. The UI opens with test files in a sidebar. Select a test file, describe block, or individual test to run a focused selection, or run the full suite from the sidebar. When you edit a test, UI Mode can watch the change and rerun the relevant tests.
For more reliable debugging, first make sure your test environment is ready: required services should be running, environment variables should be present, and any test data should be available. If your Playwright projects use setup tests as dependencies, run those setup tests first. UI Mode does not automatically take setup tests into account, so dependent tests may fail if setup has not run.
2. Select and filter tests
Use the sidebar to choose what to run. Filters help reduce a large suite to the cases that matter:
- Text: find tests by their title or matching text.
- Tags: filter on tags such as
@smoke. - Project: focus on a browser or configured Playwright project.
- Status: narrow results to passed, failed, or skipped tests.
To make a tagged test available to the tag filter, add the tag to its title, for example:
import { test, expect } from '@playwright/test';
test('checkout submits a valid order @smoke', async ({ page }) => {
await page.goto('http://localhost:3000/checkout');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByRole('status')).toContainText('Order received');
});
Change the URL and expected page content to match your app. A focused run is useful while iterating; run the broader suite before you consider a fix complete, since a locator or setup change can affect other tests.
3. Read a run in the timeline
Select a completed test and use its trace-style timeline to understand the sequence of events. The timeline represents navigations and actions. Hover over an action to see the page snapshot from that moment. The detail panes help answer different questions:
| View | What to inspect | Useful question |
|---|---|---|
| Actions | Locator, action duration, and DOM changes | Which interaction failed or took unexpectedly long? |
| Before and After snapshots | Page state on either side of an action | Was the target present before the click? Did the action change the page? |
| Logs and network | Messages filtered to the selected timeline range | Did the app log an error or did a request fail around this step? |
| Errors | Test error and its position on the timeline | Where did the test stop, and what assertion or action reported the failure? |
Start at the failing action, then compare the before and after snapshots. Check whether the test interacted with the expected element, whether the page had reached the expected state, and whether logs or network activity point to an application issue. The timeline is evidence about this run; it does not by itself establish why the application behaved that way.
4. Inspect and refine a locator
Use Pick locator to select an element in the DOM snapshot. UI Mode proposes a locator and shows it in the locator playground, where you can refine it and see the matching element highlighted. Copy the reviewed locator into your test.
Prefer locators that express user-visible meaning, such as role and accessible name, when those match the intent of the test. For example, getByRole('button', { name: 'Place order' }) describes what a user finds. A generated locator is a starting point: check that it uniquely identifies the intended element and will remain meaningful if layout or styling changes.
// Prefer an accessible, user-facing locator when it fits the test intent.
await page.getByRole('button', { name: 'Place order' }).click();
If a locator matches multiple elements, narrow it using a meaningful parent or additional accessible information rather than blindly accepting a positional selector. If the picker cannot identify the intended target, check the snapshot and current DOM state first: the element may not yet exist, may be inside a frame, or may be hidden in that state.
5. Choose UI Mode, Inspector, headed runs, or CI traces
| Workflow | Command or configuration | Use it for |
|---|---|---|
| UI Mode | npx playwright test --ui |
Interactive test selection, watch mode, and reviewing steps and snapshots during development. |
| Playwright Inspector | npx playwright test --debug |
A separate step-through debugging session with a browser and Inspector. The documented debug defaults include headed mode, one worker, and no test timeout. |
| Headed execution | npx playwright test --headed |
Run tests with a visible browser. This controls browser visibility; it does not open the interactive UI Mode runner. |
| CI trace capture | Configure the trace option in Playwright config |
Keep diagnostic traces from automated runs for later review in Trace Viewer or the HTML report. |
These workflows overlap in that they help diagnose browser tests, but they expose different controls. UI Mode is suited to choosing and exploring tests. Inspector is suited to stepping through a test with its dedicated debugging interface. A headed run simply shows the browser. CI traces preserve evidence from a remote run where an interactive local session is not available.
Playwright cautions that recording traces for every test is performance heavy. Consider capturing traces on the first retry or retaining them on failure instead of recording every passing test. The precise behavior depends on the installed Playwright version and its configuration.
6. Use UI Mode in a container or remote environment
In Docker or GitHub Codespaces, the UI server may need to listen on an address reachable outside the container. The documented pattern is:
npx playwright test --ui --ui-host=0.0.0.0 --ui-port=8080
--ui-host=0.0.0.0 binds the UI endpoint so other machines on the network can reach it, and --ui-port=8080 chooses a fixed port. Binding to all interfaces can expose UI Mode and its traces, passwords, and secrets to other machines on that network. Use this only in a trusted, controlled environment, and avoid exposing the endpoint to an untrusted network. If you only need local access, omit the host override and use the default local setup.
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
npx playwright test --ui cannot find tests or config |
The command is running outside the Playwright project or the project has not been initialized. | Change to the directory containing the Playwright configuration and test files. If this is a new project, initialize Playwright Test first. |
| A dependent test fails before reaching its main assertions | A setup test or prerequisite service/data has not run; UI Mode does not automatically account for setup tests. | Run required setup tests first and confirm services, credentials, and test data are available. |
| A test is missing from the visible list | A text, tag, project, or status filter excludes it. | Clear or broaden the filters, check the selected project, and verify the test is not skipped or filtered by configuration. |
| The locator picker proposes an unstable or ambiguous locator | The selected DOM node has no unique user-facing identity, or several matching elements exist. | Refine it in the locator playground; prefer a role and accessible name or another locator that reflects the test intent. Confirm the match in the snapshot. |
| The browser does not appear | The run is headless or you expected a visible-browser option to launch UI Mode. | Use --headed for a visible browser run or --ui for the interactive runner. Use --debug for Inspector. |
| The UI cannot be reached from outside a container | The server is bound only to a local interface or the selected port is not reachable. | In a trusted, controlled environment, use the documented host and port flags and check container port forwarding. Remember that binding to 0.0.0.0 exposes the endpoint to the network. |
| Tests become slower when trace recording is enabled | Trace recording adds overhead, particularly when enabled for every test. | Capture traces on first retry or retain them on failure, then inspect those traces for failures. |
8. Performance, reliability, and cost
UI Mode is a local development tool, so its practical cost is the time and resources used to run the browser suite. Focused selections reduce iteration work, while a full suite gives broader confidence. Test duration can also depend on your app, browser projects, and test setup. Trace recording has overhead; use failure-oriented capture in CI when full-time tracing would be too expensive in runtime or storage.
For dependable results, keep the local environment close to the one your tests expect, run prerequisites explicitly, and inspect failures in context rather than treating a suggested locator or a single green focused test as complete proof. Keep UI Mode access private when running remotely because traces can contain sensitive data.
9. Or skip the browser setup
If your goal is to capture a website image or PDF rather than exercise your app’s browser tests, ScreenshotNeo provides a website screenshot API and MCP server. It does not replace Playwright Test for browser testing. It gives you a direct capture request without setting up a browser runner. See the ScreenshotNeo API documentation.
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
With ScreenshotNeo, cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; and an MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 screenshots.
Sign up for free and get 1,000 screenshots a month with no card.
10. Frequently asked questions
Does UI Mode replace the Playwright HTML report?
No. UI Mode is an interactive runner for development. The HTML report is useful for reviewing a completed run, including in CI workflows.
Can I use UI Mode to debug only one failing test?
Yes. Select the file, describe block, or individual test in the UI, and use filters to narrow the list further.
Should I use --debug and --ui together?
They launch distinct debugging workflows. Choose UI Mode for the interactive runner and Inspector when you want its step-through debugging session.
Can I safely expose UI Mode to the public internet?
The documentation warns that network binding can expose traces and secrets to other machines. Restrict access to a trusted, controlled environment.


