Implicit vs Explicit vs Fluent Wait in Selenium (With Code)

Advertisement

Quick Answer

All three waits solve the same problem — Selenium runs faster than the page — but they differ in scope and control:

  • Implicit wait — one global timeout applied to every element search. It only waits for elements to exist.
  • Explicit wait — waits for a specific condition (visible, clickable, text present…) on a specific element, using WebDriverWait.
  • Fluent wait — an explicit wait where you also choose the polling interval and which exceptions to ignore.

Use explicit waits for almost everything, keep the implicit wait at zero, and use a fluent wait only when you need custom polling.

Comparison at a Glance

Aspect Implicit wait Explicit wait Fluent wait
Scope Every findElement in the session One condition, where you call it One condition, where you call it
Waits for The element to exist in the DOM Any condition — visible, clickable, text, URL… Any condition, including custom ones
Syntax driver.manage().timeouts().implicitlyWait(…) new WebDriverWait(driver, timeout) new FluentWait<>(driver)
Polling Handled by the browser driver Every 500 ms (default) You choose
Ignored exceptions — NotFoundException by default; configurable You choose
Returns The element (or throws NoSuchElementException) The condition's result (or throws TimeoutException) Same as explicit
Best for Rarely — simple scripts Almost every real case ⭐ Unpredictable timing, custom polling

One Scenario, Three Ways

Scenario: after clicking "Search", results load via AJAX and a spinner is shown. You need to click the first result.

Implicit wait

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

driver.findElement(By.id("search")).click();

driver.findElement(By.cssSelector(".result a")).click();   // may fail

The element may exist while the spinner still covers it, so the click can fail with ElementClickInterceptedException. An implicit wait can't wait for "clickable" or "spinner gone".

Explicit wait ⭐

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

driver.findElement(By.id("search")).click();

wait.until(
    ExpectedConditions.invisibilityOfElementLocated(
        By.className("spinner")
    )
);

wait.until(
    ExpectedConditions.elementToBeClickable(
        By.cssSelector(".result a")
    )
).click();

Waits for exactly the conditions that matter, and continues as soon as they're true.

Fluent wait

Wait<WebDriver> fluent = new FluentWait<>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofSeconds(1))
        .ignoring(NoSuchElementException.class)
        .ignoring(StaleElementReferenceException.class);

driver.findElement(By.id("search")).click();

fluent.until(
    d -> d.findElement(By.cssSelector(".result a"))
).click();

Useful when results can take anything from 2 to 30 seconds and re-render while loading — you control how often it checks and which exceptions to ride through.

How Explicit and Fluent Waits Relate

WebDriverWait extends FluentWait: it's a fluent wait with sensible defaults (500 ms polling, ignoring NotFoundException). Both return as soon as the condition is true — neither "uses up" the full timeout. And WebDriverWait can be customised too:

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

wait.pollingEvery(Duration.ofMillis(250));

wait.ignoring(StaleElementReferenceException.class);

So the practical difference is mainly style: FluentWait makes the configuration explicit and works with any object, not just a WebDriver.

Why You Shouldn't Mix Implicit and Explicit Waits

An explicit wait's conditions call findElement internally. With an implicit wait also set, each of those calls can itself wait for the implicit timeout — so the total time becomes unpredictable. The Selenium documentation gives the example of a 10-second implicit wait plus a 15-second explicit wait timing out only after about 20 seconds. The same problem makes "wait until invisible" checks painfully slow.

Best practice: set the implicit wait to 0 (the default) and put explicit waits in reusable helpers.

A Reusable Wait Helper

public final class WaitUtils {
    private static final Duration TIMEOUT = Duration.ofSeconds(10);

    public static WebElement visible(WebDriver driver, By locator) {
        return new WebDriverWait(driver, TIMEOUT)
                .until(ExpectedConditions.visibilityOfElementLocated(locator));
    }

    public static WebElement clickable(WebDriver driver, By locator) {
        return new WebDriverWait(driver, TIMEOUT)
                .until(ExpectedConditions.elementToBeClickable(locator));
    }

    public static void gone(WebDriver driver, By locator) {
        new WebDriverWait(driver, TIMEOUT)
                .until(ExpectedConditions.invisibilityOfElementLocated(locator));
    }
}

Page objects call WaitUtils.clickable(driver, submit).click(), so synchronisation lives in one place.

Why Thread.sleep() Is Not a Wait Strategy

Thread.sleep(3000) always waits exactly 3 seconds: too long on a fast machine, too short on a slow CI agent. It makes suites slow and still flaky. Replace every sleep with a condition.

Fluent Wait in Selenium: Full Java Example

FluentWait is the most configurable wait in Selenium. You choose the maximum time, how often to check, which exceptions to ignore while checking, and a custom message for the timeout. Use it when you wait for something more specific than "element is visible" — for example, an order status that changes from "Processing" to "Shipped". This example compiles with Selenium 4.25:

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

import java.time.Duration;

public class FluentWaitExample {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("https://example.com/orders");

            Wait<WebDriver> wait = new FluentWait<>(driver)
                    .withTimeout(Duration.ofSeconds(30))          // give up after 30 s
                    .pollingEvery(Duration.ofMillis(500))         // check every 0.5 s
                    .ignoring(NoSuchElementException.class)       // keep polling while it's missing
                    .ignoring(StaleElementReferenceException.class)
                    .withMessage("Order status never became 'Shipped'");

            // Wait for a custom condition, not just "element visible"
            WebElement status = wait.until(d -> {
                WebElement el = d.findElement(By.id("order-status"));
                return el.getText().equals("Shipped") ? el : null; // null = keep waiting
            });
            System.out.println("Status: " + status.getText());
        } finally {
            driver.quit();
        }
    }
}
SettingWhat it does
withTimeout(Duration.ofSeconds(30))Maximum time to wait before throwing TimeoutException
pollingEvery(Duration.ofMillis(500))How often the condition is checked (WebDriverWait uses 500 ms by default)
ignoring(NoSuchElementException.class)Exceptions to swallow while polling — the element may not exist yet
withMessage("…")Text added to the TimeoutException, so a failure explains itself
until(d -> …)Your condition. Returning null or false means "keep waiting"; anything else ends the wait and is returned

FluentWait vs WebDriverWait: WebDriverWait is a FluentWait that already ignores NoSuchElementException and polls every 500 ms — so for normal cases, new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.visibilityOfElementLocated(...)) is enough. Reach for FluentWait when you need a custom polling interval, extra ignored exceptions or a custom condition.

Which Wait Should You Use?

  1. Default: explicit wait with the right ExpectedConditions.
  2. Unpredictable timing or re-rendering content: fluent wait (or a customised WebDriverWait).
  3. Implicit wait: leave at 0 in frameworks; acceptable only in small scripts that never use explicit waits.
  4. Thread.sleep(): never for synchronisation.

See how each one behaves on a timeline in the Selenium Wait Simulator. For all ExpectedConditions and page-load waits, see Selenium Waits & Synchronisation.

The Interview Answer

"An implicit wait is a global timeout for every findElement call, and it only waits for the element to exist. An explicit wait uses WebDriverWait with ExpectedConditions to wait for a specific condition, like clickable or visible, on a specific element. A fluent wait is the same idea but lets me set the polling interval and ignored exceptions — WebDriverWait actually extends FluentWait. In frameworks I keep the implicit wait at zero, because mixing it with explicit waits makes timeouts unpredictable, and I put explicit waits in reusable helpers. I never use Thread.sleep for synchronisation."

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. Explicit waits for specific conditions are the safest default for most frameworks.

📚 Official documentation: Selenium docs: Waiting strategies · Selenium documentation

Waits in Selenium: ExpectedConditions Cheat Sheet

An explicit or fluent wait is only as good as the condition you give it. These are the ExpectedConditions you'll use most:

ConditionWaits untilTypical use
visibilityOfElementLocated(by)The element is in the DOM and visibleReading text, checking a message
elementToBeClickable(by)The element is visible and enabledBefore every click
presenceOfElementLocated(by)The element is in the DOM (may be hidden)Hidden inputs, elements you only read attributes from
invisibilityOfElementLocated(by)The element is hidden or goneWaiting for a spinner or loader to disappear
textToBePresentInElementLocated(by, text)The element contains the textStatus labels that change after an action
urlContains(fraction)The current URL contains the textAfter login or a redirect
frameToBeAvailableAndSwitchToIt(by)The frame is ready, then switches into itPayment forms and embedded widgets
alertIsPresent()A JavaScript alert is openConfirm and delete dialogs
numberOfElementsToBe(by, n)Exactly n elements matchSearch results or table rows after filtering
stalenessOf(element)The old element is detached from the pageWaiting for a page or table to re-render
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".spinner")));
wait.until(ExpectedConditions.elementToBeClickable(By.id("submit"))).click();

Frequently Asked Questions

What is the difference between implicit and explicit wait?

An implicit wait is a global timeout for every element search and only waits for the element to exist. An explicit wait waits for a specific condition on a specific element, such as visibility or clickability.

What is the difference between explicit and fluent wait?

Both wait for conditions. A fluent wait lets you set the polling interval and ignored exceptions explicitly; WebDriverWait is a fluent wait with defaults (500 ms polling) and can be customised too.

Can I use implicit and explicit waits together?

You shouldn't — it causes unpredictable wait times. Keep the implicit wait at zero and use explicit waits.

What is the default polling time of WebDriverWait?

500 milliseconds.

Which wait is best for AJAX-loaded content?

An explicit wait for the condition that proves the content is ready — for example the spinner becoming invisible and the result becoming clickable.

What exception does each wait throw?

An implicit wait leads to NoSuchElementException when the element never appears; explicit and fluent waits throw TimeoutException.

What is fluent wait in Selenium?

A fluent wait is an explicit wait you configure yourself: the maximum timeout, how often to poll (for example every 500 ms) and which exceptions to ignore while polling, such as NoSuchElementException. In Selenium 4, WebDriverWait is itself a FluentWait with sensible defaults.

What is the syntax of implicit wait in Selenium 4?

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); The older version that takes a number and a TimeUnit is deprecated in Selenium 4.

Is Thread.sleep() a wait in Selenium?

No. Thread.sleep() pauses for the full time every time, whether the page is ready or not, so tests get slower and still fail when the page takes longer. Use an explicit wait, which continues as soon as the condition is met.