Selenium WebDriver Waits Explained: Implicit, Explicit and Fluent
Most flaky Selenium tests are timing problems. Learn how Selenium waits work, which type to use and how to replace slow sleeps with reliable conditions.
- Selenium waits make your script pause until the page is ready, instead of failing at the first missing element.
- An implicit wait is a global timeout for finding elements; an explicit wait waits for one specific condition.
- A fluent wait is an explicit wait with a custom polling interval and ignored exceptions.
- Prefer explicit waits and avoid mixing them with implicit waits or
time.sleep().
You write a Selenium test, run it, and it fails with NoSuchElementException. You run it again and it passes. The element was there, just not yet. This is the problem that Selenium waits solve.
Modern pages load data in the background, animate elements into view and re-render after clicks. A script that moves faster than the page will click too early, read stale text or miss an element entirely.
This guide explains the three kinds of Selenium waits with Python examples, a comparison table and a short list of habits that keep tests stable. The official Selenium waits documentation is the reference for all details.
Why Selenium waits matter
Selenium sends commands to the browser one by one. When your script asks for an element, the browser may still be loading. Without a wait, the command fails immediately. With a wait, Selenium keeps checking until the condition is true or the timeout ends.
The result is faster tests, because you wait only as long as needed, and more stable tests, because you never guess how long a page takes. This is one of the biggest fixes for the problems we describe in our test automation mistakes guide.
Implicit wait in Selenium
An implicit wait tells the driver to keep trying to find an element for up to a set time before it raises an error. You set it once, and it applies to every find_element call for that driver session.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("https://example.com/login")
driver.find_element(By.ID, "email").send_keys("user@example.com")
It is simple, but it only checks that an element exists in the page. It does not check that the element is visible or clickable, and it is global, so it hides slow spots across the whole suite.
Explicit wait in Selenium
An explicit wait waits for one condition on one element, using WebDriverWait and expected_conditions. This is the type you will use most.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type=submit]")))
button.click()
message = wait.until(EC.visibility_of_element_located((By.ID, "success")))
assert "Saved" in message.text
Useful conditions include:
presence_of_element_located: the element is in the DOM.visibility_of_element_located: the element is in the DOM and visible.element_to_be_clickable: visible and enabled, ready to click.text_to_be_present_in_element: the text appears.invisibility_of_element_located: a loader or spinner has gone.url_containsandtitle_is: navigation finished.
If the condition is not met in time, Selenium raises TimeoutException, which gives a clearer failure than a generic missing element error.
Fluent wait in Selenium
A fluent wait is an explicit wait where you control how often Selenium polls and which exceptions it ignores while waiting. In Python you configure it through the same WebDriverWait class.
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
wait = WebDriverWait(
driver,
timeout=20,
poll_frequency=0.5,
ignored_exceptions=[NoSuchElementException, StaleElementReferenceException],
)
row = wait.until(lambda d: d.find_element(By.CSS_SELECTOR, "table tr.done"))
Use it for slow or noisy elements such as live search results, a table that refreshes or a spinner that appears and disappears. In Java the same idea is exposed as a separate FluentWait class.
Implicit vs explicit vs fluent: comparison table
| Aspect | Implicit | Explicit | Fluent |
|---|---|---|---|
| Scope | Whole driver session | One condition | One condition |
| Checks | Element exists | Any expected condition | Any condition |
| Polling control | No | Default interval | Custom interval |
| Ignores exceptions | Not configurable | Default set | You choose |
| Best for | Quick demos | Most real tests | Slow or unstable elements |
Best practices for Selenium waits
Do not mix implicit and explicit waits
Selenium’s documentation warns against combining them, because the timeouts can add up in unpredictable ways. Pick explicit waits and leave the implicit wait at zero.
Avoid time.sleep()
A fixed sleep wastes time when the page is fast and still fails when it is slow. Replace it with a condition. Wrapping waits in small helper functions keeps tests readable:
def click_when_ready(driver, locator, timeout=10):
WebDriverWait(driver, timeout).until(EC.element_to_be_clickable(locator)).click()
Wait for the right thing
Waiting for presence is not enough if you need to click. Wait for clickability. After an action, wait for a visible result, such as a success message or a changed URL, before the next step.
Handle stale elements
If a page re-renders, a stored element reference can become stale. Find the element again inside the wait rather than holding on to it.
Quick tip: Keep timeouts reasonable, around 10 seconds for normal pages. If a step needs 60 seconds, investigate the application rather than extending the wait.
Selenium waits compared with Playwright
Tools such as Playwright wait automatically for elements to be ready before acting, which removes much of this work. If you are weighing options, our list of the best test automation tools in 2026 compares them. New to Python? Start with the Python tutorial for beginners.
Final thoughts
Good Selenium waits are the quickest way to cut flaky tests (for comparison, Playwright runs built-in actionability checks before every action). Use explicit waits for most steps, a fluent wait for slow or noisy elements, keep implicit waits off and never rely on fixed sleeps. Review your slowest and flakiest tests first, and replace each guess with a clear condition.
Frequently asked questions
What are the types of Selenium waits?
Selenium offers implicit waits, explicit waits and fluent waits. Explicit and fluent waits wait for a specific condition, while implicit waits set a global element search timeout.
Should I use implicit or explicit wait in Selenium?
Use explicit waits for most tests because they target a clear condition. Avoid combining them with implicit waits.
What is the difference between explicit and fluent wait?
A fluent wait is an explicit wait with a custom polling frequency and a configurable list of ignored exceptions.
Why is time.sleep bad in Selenium tests?
It waits a fixed time whether or not the page is ready, so tests are slower when the page is fast and still flaky when it is slow.
What happens when a Selenium wait times out?
Selenium raises a TimeoutException, which tells you the condition was not met within the allowed time.
Keep learning
Need help with testing, WordPress or SEO?
We help teams ship better software and grow their sites. Tell us what you are working on and we will suggest a clear next step.