Implicit vs Explicit vs Fluent Wait in Selenium (With Code)
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();
}
}
}
| Setting | What 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?
- Default: explicit wait with the right
ExpectedConditions. - Unpredictable timing or re-rendering content: fluent wait (or a customised
WebDriverWait). - Implicit wait: leave at 0 in frameworks; acceptable only in small scripts that never use explicit waits.
- 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
ExpectedConditionsyou'll use most:
Condition Waits until Typical use visibilityOfElementLocated(by)The element is in the DOM and visible Reading text, checking a message elementToBeClickable(by)The element is visible and enabled Before 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 gone Waiting for a spinner or loader to disappear textToBePresentInElementLocated(by, text)The element contains the text Status labels that change after an action urlContains(fraction)The current URL contains the text After login or a redirect frameToBeAvailableAndSwitchToIt(by)The frame is ready, then switches into it Payment forms and embedded widgets alertIsPresent()A JavaScript alert is open Confirm and delete dialogs numberOfElementsToBe(by, n)Exactly n elements match Search results or table rows after filtering stalenessOf(element)The old element is detached from the page Waiting 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;
WebDriverWaitis 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
NoSuchElementExceptionwhen the element never appears; explicit and fluent waits throwTimeoutException.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,WebDriverWaitis itself aFluentWaitwith 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 aTimeUnitis 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.Related