Selenium Waits

Quick answer: use an explicit wait — new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.elementToBeClickable(locator)) — for anything that loads or changes. Keep the implicit wait at zero, don't mix the two, and never use Thread.sleep() as synchronisation.

Why Synchronisation Matters

Web pages load and change asynchronously — AJAX calls, animations, single-page-app rendering. Your script runs much faster than the page, so without synchronisation Selenium tries to use elements that don't exist yet, aren't visible yet, or have just been replaced. The result is timing-related failures such as:

Selenium WebDriver provides three kinds of waits: implicit, explicit and fluent. See them side by side in the Selenium Wait Simulator.

Advertisement

Implicit Wait

An implicit wait is a global setting: every findElement / findElements call keeps retrying for up to the given time before giving up.

WebDriver driver = new ChromeDriver();

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));   // Selenium 4 syntax

If the element appears after 2 seconds, findElement returns after 2 seconds — it doesn't always wait the full 10.

Limitations

  • It only waits for the element to exist in the DOM — not for it to be visible, clickable, or to have the right text.
  • It slows down "absence" checks. findElements() for an element that shouldn't be there waits the full timeout before returning an empty list.
  • It applies to everything, so you can't tune it per element.

Older tutorials use implicitlyWait(10, TimeUnit.SECONDS) — that form is deprecated in Selenium 4; use Duration.

Explicit Wait ⭐

An explicit wait waits for a specific condition on a specific element, polling until it's true or the timeout expires. It uses WebDriverWait with ExpectedConditions:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement button = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit"))
);

button.click();

As soon as the condition is true, execution continues. If it never becomes true, Selenium throws a TimeoutException.

The old constructor new WebDriverWait(driver, 10) with a number of seconds was removed in Selenium 4 — pass a Duration.

The ExpectedConditions You'll Use Most

Condition Waits until… Use before
visibilityOfElementLocated The element is in the DOM and visible Reading text, asserting
elementToBeClickable Visible and enabled Clicking
presenceOfElementLocated In the DOM (may be invisible) Reading attributes only
invisibilityOfElementLocated A loader or overlay has gone Continuing after a spinner
textToBePresentInElementLocated The element contains the text Checking a status message
urlContains / titleIs Navigation finished Asserting on the next page
numberOfElementsToBe A list has fully loaded Counting rows or results
frameToBeAvailableAndSwitchToIt An iframe is ready — and switches into it Working inside iframes
alertIsPresent A JavaScript alert is open Handling alerts
stalenessOf An old element has been removed After an action that re-renders content

Custom Conditions

When no built-in condition fits, pass a lambda:

// Wait until the cart badge shows "3"
wait.until(d ->
    d.findElement(By.id("cart-count")).getText().equals("3")
);

Fluent Wait

A fluent wait lets you configure three things yourself:

  • withTimeout() — the maximum wait time.
  • pollingEvery() — how often to check the condition.
  • ignoring() — which exceptions to ignore while polling.
Wait<WebDriver> fluent = new FluentWait<>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofSeconds(2))
        .ignoring(NoSuchElementException.class)
        .ignoring(StaleElementReferenceException.class);

WebElement report = fluent.until(
    d -> d.findElement(By.id("report-ready"))
);

Ignore only the specific exceptions you expect — ignoring(Exception.class) hides real problems.

Fluent waits are useful when something appears at unpredictable times, such as a report that takes 5–30 seconds to generate, or when an element re-renders repeatedly while loading.

How the Three Relate

  • Wait is an interface with an until() method.
  • FluentWait is the class that implements it, with configurable timeout, polling and ignored exceptions.
  • WebDriverWait extends FluentWait with sensible defaults: polling every 500 ms and ignoring NotFoundException.

So an explicit wait is a fluent wait with defaults — both return as soon as the condition is true.

Use WebDriverWait for almost everything, and reach for FluentWait only when you need different polling or ignored exceptions.

Full comparison: Implicit vs Explicit vs Fluent Wait.

Don't Mix Implicit and Explicit Waits

With both set, an explicit wait's internal findElement calls also wait for the implicit timeout, so total waiting times become unpredictable — the Selenium documentation explicitly warns against it.

The common best practice:

implicit wait = 0, explicit waits everywhere they're needed

These are usually wrapped in helper methods in your base page.

Waiting for a Page to Load

driver.get() already waits for the browser's load event. You can cap how long that may take:

driver.manage().timeouts().pageLoadTimeout(
    Duration.ofSeconds(30)
);

But in modern apps, content often arrives after the load event through AJAX. So wait for something that proves the page is really ready — a heading, a table row, the URL, or the title:

wait.until(ExpectedConditions.titleIs("Dashboard – My Shop"));

wait.until(
    ExpectedConditions.visibilityOfElementLocated(
        By.cssSelector("table.orders tbody tr")
    )
);

// Or check the document's ready state
wait.until(d ->
    "complete".equals(
        ((JavascriptExecutor) d)
            .executeScript("return document.readyState")
    )
);

Why Avoid Thread.sleep()?

Thread.sleep(3000) pauses for exactly 3 seconds every time:

  • Too short on a slow CI agent → the test fails.
  • Too long on a fast machine → every run wastes time.
  • It hides the real synchronisation problem instead of solving it.

Replace every sleep with a condition-based wait.

If a test only passes with a sleep, the missing condition is usually a loader disappearing or an element becoming clickable.

See Test Passes Locally, Fails in Jenkins.

What About setSpeed()?

setSpeed() belongs to the old Selenium RC API (Selenium 1) and Selenium IDE, where it added a delay between every command.

It doesn't exist in Selenium WebDriver — if you see it in an interview question, explain that it's legacy, and that WebDriver uses condition-based waits instead of global slow-downs.

From Real Projects

Synchronisation mattered most for me when our Selenium suites ran in parallel and across Chrome and Firefox — timing that worked in a single run didn't always hold. Waiting for a specific condition, rather than a fixed pause, is what made scripts reliable on both browsers. On Canolog, the many forms and screens across sales, inventory, finance and service are where keeping page details in POM classes and reusable steps in a business library paid off. Avoid mixing implicit and explicit waits in the same framework; the combined timing is hard to predict.

FAQs

What Is Synchronisation in Selenium?

Making the script wait for the page to be ready before interacting with it, so timing differences don't cause failures. Selenium provides implicit, explicit and fluent waits.

What Is an Implicit Wait?

A global setting that makes every element lookup retry for up to a given time:

driver.manage().timeouts().implicitlyWait(
    Duration.ofSeconds(10)
);

What Is an Explicit Wait?

A wait for a specific condition on a specific element, using WebDriverWait and ExpectedConditions, such as elementToBeClickable.

What Is a Fluent Wait?

A wait with a configurable timeout, polling interval and list of ignored exceptions, built with the FluentWait class.

Which Wait Should I Use?

Explicit waits for almost everything, with the implicit wait left at zero. Use a fluent wait only when you need custom polling or ignored exceptions.

Can I Use Implicit and Explicit Waits Together?

You shouldn't. Mixing them makes timeouts unpredictable.

Why Should Thread.sleep() Be Avoided?

It always waits the full time, slows every run, and still fails on slower machines. Condition-based waits adapt to the application's speed.

What Is the Difference Between setSpeed() and Thread.sleep()?

setSpeed() was a Selenium RC/IDE command that delayed every command; it doesn't exist in WebDriver. Thread.sleep() is Java's fixed pause. Neither should be used for synchronisation in WebDriver tests.