Playwright · Reliable end-to-end tests

How does Playwright auto-waiting work?

Mediumauto-waitingactionabilityflakinessUpdated Oct 2026
Quiz this track

Short answer

Before acting, Playwright waits for the element to be attached, visible, stable, enabled and able to receive events. Web-first assertions retry until they pass or the timeout expires.

Auto-waiting is the reason most Playwright tests need no explicit sleeps. When you call an action on a locator, Playwright resolves it and runs a set of actionability checks. If a check fails, it retries until the element is ready or the timeout is reached.

The actionability checks

  • Attached: the element exists in the DOM
  • Visible: it has a non-empty bounding box and is not hidden
  • Stable: it has not moved for at least two animation frames
  • Receives events: no other element is covering the action point
  • Enabled: it is not disabled for the requested action
  • Editable: an input is not readonly when filling is requested
ts
await page.getByRole("button", { name: "Publish" }).click();
await expect(page.getByRole("status")).toHaveText("Published");
The click waits for actionability and the assertion waits for the resulting UI.

Auto-waiting covers the element and the browser, not your business logic. It will not know that a background job, a webhook or a database write has finished. For those cases, assert on a visible signal or use expect.poll against the external state.

If an action times out, read the error: it names the check that failed and the locator that was resolved. Increasing the timeout is rarely the right fix for an element that is covered, hidden or missing because of a product bug.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What does the stability check protect against?
  2. 2Does auto-waiting wait for network requests?
  3. 3Why is increasing the timeout often the wrong fix?
  4. 4When would you use expect.poll instead?

Say it in the interview

When I act on a locator, Playwright waits until the element is attached, visible, stable, enabled and actually receiving events, then performs the action. Assertions also retry, so I rarely need explicit sleeps. It does not wait for my backend or a background job, so for that I assert on a visible signal or poll the external state. If something times out, I read which actionability check failed rather than just raising the timeout.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Playwright mock interview and get scored feedback on depth, clarity and confidence.