Installing the Claude Code webapp-testing Skill Cleanly

Installing the Claude Code webapp-testing Skill Cleanly

·8 min read·Updated on May 3, 2026

A skill that drives Chromium

webapp-testing is an official Anthropic skill, living in the anthropics/skills repo, that gives Claude Code control of a real browser — a Chromium instance driven through Playwright to test an app locally.

The concept: instead of writing Playwright scripts by hand, you describe what you want to test in natural language, and Claude writes and runs the script in a real browser. You can log in manually, then hand over. It takes screenshots, reads the DOM, captures console logs, debugs authenticated flows — everything static analysis can't do.

The problem: none of the available guides gives a clean install method. They all propose something that pollutes the system or breaks within two weeks.

What's wrong with the usual methods

For Playwright in Python, the official consensus is clear:

  1. Never pip install system-wide. PEP 668 blocks it by default on Ubuntu, Debian, Fedora and most modern distros — you get error: externally-managed-environment, and that's a good thing.
  2. Not pipx. pipx is designed for standalone CLIs, whereas Playwright is used as an imported library (from playwright.sync_api import ...). pipx isolates it so well you can't import it from an external script.
  3. Always --with-deps on Linux when installing browsers. Otherwise Chromium crashes with cryptic errors about missing .so files (audio, font and rendering libs). The flag runs apt install behind the scenes — hence the sudo prompt — but it's the right route.

The best practice for a normal Playwright project is one venv per project. But for a global Claude Code skill that doesn't work: Claude invokes the skill from any directory, with no way to know which venv to activate.

The fix: a dedicated venv inside the skill folder

The pattern that holds: a venv embedded directly in the skill folder, plus a patch in SKILL.md telling Claude "use THIS python, not the system one". The skill becomes self-contained, the system Python stays pristine, and rm -rf ~/.claude/skills/webapp-testing uninstalls everything cleanly, including the 600 MB of Chromium.

1. Fetch the skill

The anthropics/skills repo contains plenty of other things (PDF/DOCX/PPTX document skills, an MCP server generator). Sparse checkout takes only what you need:

cd /tmp
git clone --depth 1 --filter=blob:none --sparse \
  https://github.com/anthropics/skills.git anthropics-skills-tmp
cd anthropics-skills-tmp
git sparse-checkout set skills/webapp-testing
cp -r skills/webapp-testing ~/.claude/skills/
cd .. && rm -rf anthropics-skills-tmp

~/.claude/skills/webapp-testing/ then contains:

webapp-testing/
├── SKILL.md         # Main instructions
├── LICENSE.txt
├── examples/        # console_logging.py, element_discovery.py, static_html_automation.py
└── scripts/         # with_server.py (multi-server lifecycle)

Claude Code detects the skill on next startup, but it doesn't work yet: Playwright isn't installed.

2. Dedicated venv inside the skill

python3 -m venv ~/.claude/skills/webapp-testing/.venv
~/.claude/skills/webapp-testing/.venv/bin/pip install --upgrade pip
~/.claude/skills/webapp-testing/.venv/bin/pip install playwright

Everything stays inside .venv/. Typing python3 in a terminal still gives the pristine OS Python. Reference stack here: Python 3.12.3, pip 26.1, Playwright 1.59.0.

3. Chromium + system dependencies

~/.claude/skills/webapp-testing/.venv/bin/playwright install --with-deps chromium

--with-deps is critical on Linux: it runs sudo apt install to lay down the shared libs Chromium needs (libnss3, libatk1.0, libxkbcommon, libgbm, and about twenty more). Without it, the browser crashes at launch with error while loading shared libraries: libnss3.so.

The download is ~280 MB: Chrome for Testing (170 MB) and Chrome Headless Shell (112 MB), stored in ~/.cache/ms-playwright/ rather than the venv. That's Playwright's default and it's the right call: another Playwright project reuses the same browser cache.

4. Patch SKILL.md

This is the step nobody mentions, and the one that makes the install actually work. By default SKILL.md tells Claude to run scripts with python3 — the system Python, which has no Playwright. Result: ModuleNotFoundError: No module named 'playwright', and half a session spent figuring out why.

Add a section at the top of SKILL.md pointing to the right interpreter:

**IMPORTANT — Python interpreter to use**:
This skill ships with its own dedicated venv at
`~/.claude/skills/webapp-testing/.venv` with Playwright + Chromium
pre-installed. **Always invoke scripts with this interpreter**, never
the system `python3` (which won't have Playwright):

\`\`\`bash
~/.claude/skills/webapp-testing/.venv/bin/python scripts/with_server.py --help
~/.claude/skills/webapp-testing/.venv/bin/python /tmp/your_automation.py
\`\`\`

When the helper `with_server.py` invokes child commands, also pass this
interpreter explicitly (e.g. `... -- ~/.claude/skills/webapp-testing/.venv/bin/python your_automation.py`).

Claude reads SKILL.md every time the skill triggers: the note lands straight in its context, and it consistently uses the right python.

5. Smoke test

~/.claude/skills/webapp-testing/.venv/bin/python -c "
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
    b = p.chromium.launch(headless=True)
    page = b.new_page()
    page.set_content('<h1>hello</h1>')
    print('h1:', page.locator('h1').inner_text())
    b.close()
print('OK')
"

Expected output: h1: hello then OK. A crash on shared libraries means --with-deps didn't run properly (sudo refused or apt unavailable) — re-run with explicit sudo.

Why not npx skills add

Several guides suggest npx skills add https://github.com/anthropics/skills --skill webapp-testing, or the marketplace plugin (/plugin marketplace add anthropics/skills). That installs the skill — essentially what the sparse git clone does — but it doesn't handle the Playwright install. You end up with a skill Claude Code detects that crashes on first use.

Alternative with uv

uv (by Astral) has become the reference for managing Python: faster than pip (10× on installs), native venv management, auto-dependency scripts via PEP 723.

curl -LsSf https://astral.sh/uv/install.sh | sh   # if not already installed

uv venv ~/.claude/skills/webapp-testing/.venv
uv pip install --python ~/.claude/skills/webapp-testing/.venv/bin/python playwright
~/.claude/skills/webapp-testing/.venv/bin/playwright install --with-deps chromium

Identical result, twice as fast to install. The SKILL.md patch is still required.

Using it

You address the skill in natural language:

"Start my Next.js dev server on port 3000 and use webapp-testing to check
that the homepage loads with no console errors."

"Run webapp-testing on localhost:5173, screenshot the login page, then try
signing in with test@example.com/password and verify we land on the
dashboard."

"With webapp-testing, navigate to the checkout form and list all the input
field selectors — I want to write an E2E test."

Claude detects the skill at startup, calls the right interpreter thanks to the SKILL.md patch, and writes then runs the Playwright script on the fly.

The official SKILL.md provides a clear decision tree:

  • Static app (plain HTML) → read the HTML file directly to identify selectors, then a simple Playwright script.
  • Dynamic app, server already running → "recon → action" pattern: page.goto(url), page.wait_for_load_state('networkidle'), screenshot/inspect, identify selectors, execute.
  • Dynamic app, server to launch → the scripts/with_server.py helper, which handles multi-server lifecycle (frontend + backend in parallel).

The most important rule: always wait_for_load_state('networkidle') before inspecting the DOM on a dynamic app. Otherwise Claude reads a half-rendered DOM and writes a test that fails one time in three.

What to take away

Playwright's docs recommend venv but don't cover the "global skill" case. Venv-per-project is the right reflex in normal development; for a skill invocable from anywhere, a venv embedded in the skill is the only clean way.

The SKILL.md patch is 90% of the install's stability. Without that note, Claude hits the system python3 and crashes. Eight lines change everything.

Chromium binaries in ~/.cache/ms-playwright/ are shared. You download Chromium once per machine, regardless of how other projects install Playwright.

--with-deps is non-negotiable. Skipping sudo to save time costs twenty minutes debugging libnspr4.so.

This skill covers most of what you'd want the Playwright MCP for. An @playwright/mcp setup remains more powerful for interactive exploration (persistent browser state, accessibility tree in the response), but it's heavier to set up and costlier in tokens. For "check this flow works", the skill is more direct.

Limitations

It's a development aid, not an E2E testing framework for production. For a real E2E suite with CI/CD, sharding, retries and reports, pytest-playwright in a dedicated project is still the answer. The skill is for the daily loop: "I changed this component, quickly check nothing broke on flow X".

And everything Claude sees in the browser (DOM, console output, form data) goes to the Anthropic API. Use it on dev environments with test data, not on production with real customer data.

ShareLinkedInXBluesky

Related articles