Implicit Wait in Selenium: How It Works and Why to Avoid It (2026)

Implicit Wait in Selenium: How It Works and Why to Avoid It (2026)

Implicit wait in Selenium sets a global timeout applied to every find_element call: driver.implicitly_wait(10). The driver retries finding the element for up to 10 seconds before throwing NoSuchElementException. The problem: mixing implicit and explicit waits causes unpredictable behavior. Use explicit waits exclusively — set driver.implicitly_wait(0) and use WebDriverWait per element instead.

Key Takeaways

Implicit wait is global — it applies to every find_element call. Set once, applies everywhere. This sounds convenient but creates hidden timing side effects across your entire test suite.

Never mix implicit and explicit waits. When both are set, wait times can compound unpredictably. The Selenium WebDriver spec explicitly warns against this. Always disable implicit wait (driver.implicitly_wait(0)) if you use explicit waits.

Implicit wait only handles NoSuchElementException. It retries when the element isn't found yet. It does NOT wait for visibility, clickability, or specific conditions — you still get ElementNotInteractableException on hidden elements.

Use explicit wait instead. WebDriverWait(driver, 10).until(EC.element_to_be_clickable(...)) gives you condition-specific waits per element. More precise, more reliable, easier to debug.

time.sleep() is always wrong. Never use fixed sleeps. They waste time when elements load fast and still fail when the network is slow.

What is Implicit Wait in Selenium?

Implicit wait tells the Selenium WebDriver to poll the DOM for a specified amount of time when trying to find an element.

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)  # Wait up to 10 seconds globally

After this single line, every subsequent find_element call will:

  1. Try to find the element immediately
  2. If not found, retry every 500ms (approximately)
  3. Continue retrying until the element appears or 10 seconds elapse
  4. Raise NoSuchElementException if the element never appears
driver.implicitly_wait(10)

# These all use the 10-second implicit wait automatically
username = driver.find_element(By.ID, "username")       # Retries up to 10s
password = driver.find_element(By.NAME, "password")     # Retries up to 10s
submit = driver.find_element(By.CSS_SELECTOR, "#submit")  # Retries up to 10s

Implicit Wait vs Explicit Wait vs Fluent Wait

Feature Implicit Wait Explicit Wait Fluent Wait
Scope Global (all find_element) Per-element Per-element
Condition Element exists in DOM Any condition Any condition
Poll frequency ~500ms (browser default) Configurable Configurable
Handles visibility ❌ No ✅ Yes ✅ Yes
Handles clickability ❌ No ✅ Yes ✅ Yes
Mix safely with others ❌ No ✅ Yes ✅ Yes
Recommended ❌ Avoid ✅ Use this ✅ For complex cases

How to Set Implicit Wait

from selenium import webdriver

driver = webdriver.Chrome()

# Set implicit wait (seconds)
driver.implicitly_wait(10)

# Navigate and find elements
driver.get("https://example.com/login")
username = driver.find_element(By.ID, "username")
username.send_keys("testuser")

To disable implicit wait:

driver.implicitly_wait(0)  # Disable — set back to zero

What Implicit Wait Does NOT Handle

This is where most developers get burned. Implicit wait only catches NoSuchElementException. It does not wait for:

Visibility

driver.implicitly_wait(10)

# The element is in the DOM but hidden (display: none)
button = driver.find_element(By.ID, "hidden-button")  # Succeeds immediately!
button.click()  # ❌ ElementNotInteractableException — element is hidden

Clickability

driver.implicitly_wait(10)

# Element exists and is visible, but disabled
submit = driver.find_element(By.ID, "submit-btn")  # Succeeds immediately!
submit.click()  # ❌ ElementClickInterceptedException if button is disabled

AJAX Content

driver.implicitly_wait(10)

driver.find_element(By.ID, "load-more").click()

# Tries to find .new-item, but if the DOM element is removed and re-added
# during loading, implicit wait may find a stale reference
items = driver.find_elements(By.CSS_SELECTOR, ".new-item")
# May return stale elements or miss new ones

The Core Problem: Mixing Implicit and Explicit Waits

The most dangerous mistake in Selenium is setting both:

# ❌ Never do this
driver.implicitly_wait(10)  # Global 10-second wait
wait = WebDriverWait(driver, 5)  # Explicit 5-second wait

# What actually happens?
element = wait.until(EC.visibility_of_element_located((By.ID, "element")))
# Behavior is UNDEFINED — waits can compound, overlap, or interact
# You might wait 10s + 5s = 15s, or 5s, or something else

From the Selenium documentation:

"Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times."

The WebDriver spec marks this as a known issue. Different browsers implement the interaction differently, making cross-browser tests even more unpredictable.

Why Explicit Wait is Better

Explicit wait gives you condition-specific, per-element control:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# Disable implicit wait
driver.implicitly_wait(0)

wait = WebDriverWait(driver, 10)

# Wait for element to EXIST (in DOM, may be hidden)
element = wait.until(EC.presence_of_element_located((By.ID, "element")))

# Wait for element to be VISIBLE
element = wait.until(EC.visibility_of_element_located((By.ID, "element")))

# Wait for element to be CLICKABLE (visible + enabled)
element = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))

# Wait for specific TEXT to appear
wait.until(EC.text_to_be_present_in_element((By.ID, "status"), "Done"))

# Wait for element to DISAPPEAR
wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".spinner")))

Each wait is precise. You know exactly what you're waiting for. When a test fails, you know exactly why.

When Implicit Wait Seems Acceptable

There are narrow cases where implicit wait appears useful:

Simple Scripted Tests

# Quick script, not a test suite
driver.implicitly_wait(5)
driver.get("https://example.com")
driver.find_element(By.ID, "login").click()
driver.find_element(By.ID, "username").send_keys("user")
# etc.

For one-off automation scripts (not maintained test suites), implicit wait reduces boilerplate. But even here, explicit waits are more reliable.

Legacy Codebases

If you're inheriting a codebase that uses implicit waits throughout, ripping them all out at once is risky. In this case:

  1. Keep driver.implicitly_wait() as-is
  2. Never add WebDriverWait alongside it
  3. Gradually refactor to explicit waits module by module

Correct Pattern: Explicit Waits Only

Here's the production-ready pattern:

import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@pytest.fixture
def driver():
    driver = webdriver.Chrome()
    driver.implicitly_wait(0)  # Explicitly disabled
    yield driver
    driver.quit()


def test_login(driver):
    wait = WebDriverWait(driver, 10)

    driver.get("https://example.com/login")

    # Each wait is specific to what we need
    username = wait.until(EC.visibility_of_element_located((By.ID, "username")))
    username.send_keys("testuser@example.com")

    password = driver.find_element(By.ID, "password")  # After first element loads, others are present
    password.send_keys("password123")

    submit = wait.until(EC.element_to_be_clickable((By.ID, "submit-btn")))
    submit.click()

    # Wait for navigation
    wait.until(EC.url_contains("/dashboard"))

    # Verify dashboard loaded
    welcome = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".welcome-message")))
    assert "testuser" in welcome.text.lower()

Checking if Implicit Wait is Set

There's no direct getter in Selenium Python for the current implicit wait value. Track it yourself:

class BrowserDriver:
    def __init__(self):
        self._driver = webdriver.Chrome()
        self._implicit_wait = 0
        self._driver.implicitly_wait(self._implicit_wait)

    def set_implicit_wait(self, seconds: int):
        self._implicit_wait = seconds
        self._driver.implicitly_wait(seconds)

    def disable_implicit_wait(self):
        self.set_implicit_wait(0)

Implicit Wait in Selenium Java

The same rules apply in Java:

// Set implicit wait
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

// Disable implicit wait
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(0));

// ❌ Never mix with explicit wait
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
// Unpredictable behavior when both are set

Implicit Wait in Selenium JavaScript (WebDriverJS)

// Set implicit wait
await driver.manage().setTimeouts({ implicit: 10000 }); // milliseconds

// Disable
await driver.manage().setTimeouts({ implicit: 0 });

// ✅ Use explicit wait instead
const { until, By } = require('selenium-webdriver');
await driver.wait(until.elementLocated(By.id('element')), 10000);
await driver.wait(until.elementIsVisible(element), 10000);

Migration: From Implicit to Explicit Waits

If you're refactoring away from implicit waits:

Before (implicit wait):

driver.implicitly_wait(10)

driver.get("https://example.com/products")
product = driver.find_element(By.CSS_SELECTOR, ".product-card")
product.click()
add_to_cart = driver.find_element(By.ID, "add-to-cart")
add_to_cart.click()
cart_count = driver.find_element(By.ID, "cart-count")
assert cart_count.text == "1"

After (explicit wait):

driver.implicitly_wait(0)
wait = WebDriverWait(driver, 10)

driver.get("https://example.com/products")
product = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".product-card")))
product.click()

add_to_cart = wait.until(EC.element_to_be_clickable((By.ID, "add-to-cart")))
add_to_cart.click()

cart_count = wait.until(EC.text_to_be_present_in_element((By.ID, "cart-count"), "1"))

The explicit version catches more failures (hidden elements, disabled buttons) and gives clearer error messages when things go wrong.

The Alternative: AI Handles All Waits

Selenium requires you to choose between implicit and explicit waits — both have trade-offs. HelpMeTest eliminates the choice entirely:

Go to https://example.com/login
Type "testuser@example.com" in the email field
Type "password123" in the password field
Click the "Sign In" button
Verify the dashboard page loads

The AI waits for each element to be ready before interacting — no implicitly_wait, no WebDriverWait, no time.sleep. It behaves like a human: it sees the page and waits until elements are actually interactable.

Implicit/explicit waits matter when:

  • Maintaining existing Selenium test suites
  • Working in teams with mixed testing backgrounds
  • Migrating from legacy test infrastructure

When to reconsider:

  • New test projects without legacy constraints
  • Non-technical team members need to write tests
  • Test maintenance is consuming more time than feature development

Summary

Implicit wait in Selenium:

# Set (applies globally to all find_element calls)
driver.implicitly_wait(10)

# Disable (required before using explicit waits)
driver.implicitly_wait(0)

Rules:

  1. Never mix implicit and explicit waits — behavior is undefined
  2. Implicit wait only handles NoSuchElementException, not visibility/clickability
  3. Use WebDriverWait + expected_conditions for reliable, precise waits
  4. Set driver.implicitly_wait(0) in your test fixture if using explicit waits
  5. time.sleep() is always wrong — never use fixed sleeps in tests

Read more