Modern web apps load content asynchronously. If Selenium tries to click an element before it exists, the test fails with NoSuchElementException. Waits tell Selenium to pause until a condition is met.
The Problem
driver.get("https://app.example.com/dashboard")
# ❌ fails if the table hasn't loaded yet
rows = driver.find_elements(By.CSS_SELECTOR, "table tbody tr")
Implicit Wait
driver.implicitly_wait(10) # seconds — set once per sessionTells Selenium to poll the DOM for up to 10 seconds before raising NoSuchElementException. Simple, but applies globally to every find_element call — which can mask real bugs.
Explicit Wait (Preferred)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, timeout=10)
# Wait until element is visible
el = wait.until(EC.visibility_of_element_located((By.ID, "results")))
# Wait until element is clickable
btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".submit-btn")))
btn.click()
# Wait for text to appear
wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "Done"))
# Wait for URL to change
wait.until(EC.url_contains("/dashboard"))Explicit waits target a specific element for a specific condition — much more precise.
Common Expected Conditions
| Condition | Use when |
|---|---|
visibility_of_element_located | Element must be visible |
element_to_be_clickable | Element must be enabled and visible |
presence_of_element_located | Element in DOM (may be hidden) |
text_to_be_present_in_element | Text appears inside element |
url_contains | URL changes after navigation |
staleness_of | Old element is replaced by a new one |
Wait Timing Visualiser
Async page load simulation
Ctrl+Enter
HTML
CSS
JS
Preview
Fluent Wait (Advanced)
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(
driver,
timeout=15,
poll_frequency=0.5, # check every 500ms
ignored_exceptions=[StaleElementReferenceException],
)
el = wait.until(EC.visibility_of_element_located((By.ID, "content")))Use fluent wait when elements are expected to go stale (e.g., after a partial page re-render).