Your selector broke.
Your test didn't.

When a Playwright locator stops matching, healwright asks an AI model which element you meant, checks the answer against the live page, and caches it. The next run doesn't call the model at all.

Read the guide
  1. 1Run
  2. 2Break
  3. 3Scan
  4. 4Verify
  5. 5Heal
  6. 6Cache

Animated demo. A test clicks a Place order button using the selector #buy-now. A redesign ships and the selector matches nothing. Healwright scores the page's interactive elements, the model picks the button, the answer is checked for a single visible match with enough confidence, the click runs, and the fix is cached so the next run skips the model.

Most runs stop at step one

Healing only starts when your own locator fails. After the first heal the fix is cached, so the model is asked once per element, not once per run.

  1. Your locator runs first

    healwright tries your selector exactly as written. If the element shows up within a second, the action runs and nothing else happens.

    quickTimeout: 1000
  2. The cache is checked

    A fix found earlier for this element on this page is tried next. Commit .self-heal/healed_locators.json and your teammates and CI reuse it too.

    cacheFile
  3. The page is narrowed down

    Up to 1,000 interactive elements are collected and scored against your description. Only the best 40 are sent to the model, so the right one isn't lost to DOM order.

    maxCandidates: 40
  4. The model suggests locators

    It answers with up to three Playwright strategies, such as a test id, a role and name, or a label, each with a confidence score, in JSON that has to match a fixed schema.

    AI_PROVIDER
  5. Every suggestion is checked

    A suggestion is accepted only if it matches exactly one element, that element is visible, and its confidence clears your threshold.

    minConfidence
  6. The action runs and the fix is saved

    The working locator goes into the cache, and the heal is written to heal_events.jsonl with the model's reason and token count.

    reportFile

Keep healing honest

A heal that lands on the wrong element still passes. Decide how far the model is trusted, and keep a record of every heal.

Mode

In this example the model's best match scores 0.86.

Healed. The click runs and the test carries on.

The fix is cached for the next run and written to heal_events.jsonl with the model's reason and token count.

Fits the Playwright you already write

Wrap the page fixture once. After that every action takes a selector and a plain-English description, and when you leave the selector empty the description is enough.

Wrap the page fixture

One fixture file, then import test from it instead of @playwright/test. Healing turns on with SELF_HEAL=1.

// fixtures.ts
import { test as base } from '@playwright/test';
import { createHealingFixture, HealPage } from 'healwright';

export const test = base.extend<{ page: HealPage }>(
  createHealingFixture()
);

// SELF_HEAL=1 AI_API_KEY=… npx playwright test

Cloud models, or one on your own machine

Pick a provider with one environment variable. With Ollama the model runs locally, so page content never leaves your computer.

Provider

Behind a gateway? AI_BASE_URL points a built-in provider at Azure, OpenRouter, vLLM or LiteLLM.

Watch a real run

Broken locators found and fixed in a live Playwright session.

Start with the test that breaks most often.

Read the guide