How do you wait for an element to become clickable in Playwright?

In Selenium, you can explicitly wait for an element to be clickable before interacting with it. What is the equivalent approach in Playwright to ensure an element is ready for clicking?

I’ve worked quite a bit with Playwright, and honestly, the idea of having to wait for an element to become clickable in Playwright like we used to do in Selenium is mostly unnecessary. Playwright bakes that logic right into locator.click().

When you do:*

const button = page.locator('#login-button');
await button.click();

Playwright automatically waits for the element to be visible, enabled, stable, and not covered—basically everything Selenium’s waitForClickable() used to do.

If you still want something explicit, you can pair the click with:

await button.waitFor({ state: 'visible' });
await button.click();

But in most cases, the default built-in waiting takes care of it.

Totally agree with @raimavaswani after years in testing, Playwright really does remove the need to manually wait for an element to become clickable in Playwright. One small thing to add: Playwright also lets you control the waiting behavior through timeouts.

For example, if a button takes a little longer to appear or enable, you can do:*

await button.click({ timeout: 5000 });

This gives the action up to 5 seconds to become interactable. So most of the ‘clickable’ waiting is already built-in, you just tune it when your app needs more time.

Adding to what @raimavaswani and @charity-majors said even with Playwright’s smart waits, edge cases can still appear. In my experience, failures usually happen when you try to wait for an element to become clickable in Playwright but the element lives inside an iframe or is under an overlay.

In those cases, I usually ensure the element is fully mounted and visible before interacting:*

const frame = page.frameLocator('#my-frame');
const button = frame.locator('#login-button');

await button.waitFor({ state: 'visible' });
await button.click();

This covers scenarios where the element is rendered late, animated in, or dynamically attached. Playwright handles most waits, but a little explicit waiting helps when the UI is layered or complex.