# Playwright: five install paths, a private monorepo root, and a main branch 25 days ahead of the newest tag

> microsoft/playwright holds the test runner, the automation library, the agent CLI and the MCP server, but the repository root is a private package called playwright-internal and the published version on npm is a different one. The practical decisions a reader faces are which of the five install paths to take, and whether to work from a tag or from main.

**microsoft/playwright** — Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.

- Repository: https://github.com/microsoft/playwright
- Website: https://playwright.dev
- Stars: 96,872 · Forks: 6,521
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/microsoft-playwright

## Five install paths share one README, and four of them are not the test runner

The README opens with a table that maps a purpose to a command, and the mapping is the single most useful thing in the file. End-to-end testing gets npm init playwright@latest. Coding agents get a global install of @playwright/cli. AI agents and LLM-driven automation get the MCP server through npx. Plain automation scripts get npm i playwright. Test authoring and debugging inside VS Code gets the extension from the Marketplace.

Adding the test runner by hand means two commands, and the second one is the one people forget:

```bash
npm i -D @playwright/test
npx playwright install
```

Consequence for the reader: the package and the browsers are separate downloads. Installing @playwright/test gives you a runner whose engine binaries are not on the machine yet, and a suite that fails to launch is usually a machine that skipped the install step rather than a version conflict.

## The root package is private, named playwright-internal, and wants node >= 20

The package.json at the root of the repository is not the thing you install. Its name is playwright-internal, it is marked private, its version is 1.64.0-next, and its description is A high-level API to automate web browsers. The author is Microsoft Corporation and the licence is Apache-2.0. The engines field requires node >= 20.

Consequence for the reader: cloning this repository does not give you a library to import. The four paths in the table point at four different published packages, and the monorepo under packages/ is where they are built. A team that vendors the source instead of depending on npm has to work out which subdirectory it actually wants, and the engines field tells you the floor for all of them: node 20 or later, with nothing written about which version the test runner itself was validated against.

## main carries 1.64.0-next while the newest release tag is v1.63.0

The three most recent releases are v1.62.0 on 2026-07-24, v1.62.1 on 2026-07-30, and v1.63.0 on 2026-09-04. The root manifest says 1.64.0-next, and the last push to main was on 2026-09-29. So the branch you clone is a next minor ahead of the newest tag, and it is not a patch release sitting on top of it.

Consequence for the reader: the gap between v1.62.1 and v1.63.0 is five weeks, which means a minor bump is where behaviour changes arrive, and main is already inside the following minor. Anyone tracking this project by cloning main is testing a version no one has published, and anyone pinning v1.63.0 is three weeks behind a branch that has been rewritten since. The repository is not archived and the last push was on 2026-09-29, so this is a moving target by design rather than a stalled one.

## Twelve test scripts, and one of them runs a released Playwright against itself

The scripts block is a map of the test surface. ctest, ftest, and wtest all run the same config at tests/library/playwright.config.ts with a different project filter, chromium-*, firefox-*, and webkit-*. Then there are configs for webview, android, electron, installation, stress, bidi, the html reporter, the web package, the MCP server, the browser extension, and Playwright's own test runner.

The entry worth reading twice is ttest. It does not call the local runner at all: it reaches into ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli and runs that copy against tests/playwright-test/playwright.config.ts. A stable, released version of the tool is used to test the tool.

The examples directory says the same thing about scope. It holds github-api, mock-battery, mock-filesystem, svgomg, todomvc, and webauthn, which is a spread that reaches past clicking through a page into intercepting a battery API, faking a filesystem, signing in with a hardware key, and talking to a hosting API.

Consequence for the reader: a behavioural difference you hit may belong to a project filter or a config rather than to the library, and the file that tells you which is the scripts block. The filters are globs, so ctest runs every chromium project at once and you cannot narrow to one without changing the command.

## browser_patches/ sits at the top level and nothing explains what it patches

Among the top-level entries there is a browser_patches/ directory, sitting next to packages/, tests/, utils/, docs/, and examples/. The README does not mention it. Nothing in the documentation says which engines are patched, at which upstream versions, or what changes.

What the README does commit to is the engine set itself: Chromium, Firefox, and WebKit, driven with a single API, across tests, scripts, and as a tool for AI agents. Three engines is the whole point of the project and also the source of its sharpest edges, because the intersection of what all three do is smaller than what any one of them does.

Consequence for the reader: when an engine behaves in a way that stock Chromium, Firefox, or WebKit would not, this repository gives you nowhere to look for the reason. That matters most for WebKit, where the gap between a released browser and the build under test is the sort of question that gets answered by bisecting a patch set you cannot read. A bug you can reproduce in a normal browser and not in Playwright is a question for the issue tracker, and the Online Playground linked from the README exists for exactly that kind of report.

## Auto-waiting deletes your timeouts, and storageState writes your login to a file

Two defaults change how a Playwright test fails compared with a test written against a driver you drive yourself. The first is that there are no artificial timeouts: Playwright waits for an element to become actionable, and assertions retry until the condition holds. A selector that matches nothing is no longer a fast failure, it is a wait.

Finding the selector is the other half of that bargain, and the locators are the part designed to survive markup churn:

```typescript
page.getByRole('button', { name: 'Submit' })
page.getByLabel('Email')
page.getByPlaceholder('Search...')
page.getByTestId('login-form')
```

None of those four depends on a CSS path or a DOM position. getByRole and getByLabel are anchored to what a user perceives, and the trade is that they need the page to carry the semantics they read, so an input without a label has nothing for getByLabel to find.

The second default is the isolation model. Each test gets a fresh browser context, equivalent to a fresh profile, and authentication is carried between tests through a file:

```typescript
// Save state after login
await page.context().storageState({ path: 'auth.json' });

// Reuse in other tests
test.use({ storageState: 'auth.json' });
```

Consequence for the reader: a broken selector costs you the assertion timeout instead of failing in a millisecond, so a suite that hangs is a suite with a bad locator, not a slow page. And the reuse mechanism writes cookies and origin-scoped storage to a JSON file in your working tree, which means the file has to be gitignored and treated as a credential rather than as a fixture.

## The CLI is argued against MCP on token cost, and the MCP server works from element refs

The README positions the two agent-facing entry points against each other. The CLI is described as more token-efficient than MCP, because commands avoid loading large tool schemas and accessibility trees into the model context. It installs globally and takes verbs as arguments:

```bash
playwright-cli open https://demo.playwright.dev/todomvc/ --headed
playwright-cli type "Buy groceries"
playwright-cli press Enter
playwright-cli screenshot
```

The MCP server takes the other approach and still arrives at determinism. The agent receives a structured accessibility tree rather than screenshots, and acts through element refs:

```json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}
```

Consequence for the reader: the trade is context size against expressiveness. Verbs keep the model holding a command line. Refs keep it holding a page description, which costs more per step but survives a layout the model cannot see. Neither route shares state with the other, so a workflow that mixes them drives two browser sessions.

## Conclusion

Pick Playwright when your tests need to run against all three engines from one suite and you want locators that survive markup changes, and take the npm packages rather than cloning this repository. Do not clone it expecting a library you can import, since the root package is private and named playwright-internal, and do not plan an upgrade around a tag you found in the tree, since main already carries the next minor. Before you commit, check three things: that the browser binaries you need are actually downloaded by npx playwright install, that the login state your suite shares through storageState is not a credential file you would rather not write to disk, and which of the five documented install paths the agent tooling in your workflow is supposed to use.

## FAQ

### How do I install Playwright?

For end-to-end testing, run npm init playwright@latest. To add the test runner to an existing project, run npm i -D @playwright/test and then npx playwright install, which is the step that downloads the browser binaries. For automation scripts without a test runner, the package is npm i playwright.

### How do I use Playwright for testing?

Import test and expect from @playwright/test, then drive the page fixture, for example page.goto followed by an assertion such as toHaveTitle or toBeVisible. Run the suite with npx playwright test; tests run in parallel across the configured browsers, headless by default, each in its own browser context.

### How do I use the Playwright CLI?

Install it with npm install -g @playwright/cli@latest, then run commands directly such as playwright-cli open with a URL, playwright-cli type, playwright-cli press, and playwright-cli screenshot. The command playwright-cli show opens a dashboard with live screencast previews of the running sessions and lets you take remote control of one.

### How do I install and use the Playwright MCP server?

Add it to your MCP client configuration with the command npx and the argument @playwright/mcp@latest, or run claude mcp add playwright npx @playwright/mcp@latest in Claude Code. The agent then works from a structured accessibility snapshot of the page and acts through element refs.

### How do I use Playwright with Claude Code?

The README points at two routes. For the MCP server, run claude mcp add playwright npx @playwright/mcp@latest. For the CLI, install @playwright/cli globally and point the coding agent at a task in natural language, such as testing the add todo flow on the demo site with playwright-cli.

### Is Playwright better than Selenium?

The repository does not compare itself to Selenium. It states that Playwright drives Chromium, Firefox, and WebKit with a single API, and that the test runner provides full browser isolation, auto-waiting, and web-first assertions. The trade between the two is left to you.

## Sources

- [Official documentation](https://playwright.dev)
- [Official README](https://github.com/microsoft/playwright#readme)
- [Project repository](https://github.com/microsoft/playwright)
- [Release notes](https://github.com/microsoft/playwright/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/microsoft-playwright
