You called driver.find_elements(By.CSS_SELECTOR, ".price")[0].text and Python crashed with IndexError because the page hadn’t finished loading or the selector matched zero elements. Selenium’s find_elements (plural) returns an empty list when nothing matches, vs find_element (singular) which raises NoSuchElementException.
![Selenium IndexError on find_elements[0] Fix (2026)](https://itsourcecode.com/wp-content/uploads/2026/06/Selenium-IndexError-on-find_elements0-Fix-2026-1024x576.png)
📌 Quick answer: Use WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".price"))) to wait until the element appears (up to 10 sec). For “first match” use find_element (singular). Never index into find_elements without checking the list is non-empty.
Cause 1: Element not loaded yet
JavaScript-rendered pages need time. find_elements runs immediately and gets nothing.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# ❌ Element not yet on page
price = driver.find_elements(By.CSS_SELECTOR, ".price")[0].text
# ✓ Wait up to 10 sec
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".price"))
)
price = driver.find_element(By.CSS_SELECTOR, ".price").textCause 2: Wrong selector or A/B test variant
Selector matches in your test environment but not in production due to CSS class change or A/B test.
# Use multiple fallback selectors
selectors = [".price", ".product-price", "[data-test='price']"]
for sel in selectors:
els = driver.find_elements(By.CSS_SELECTOR, sel)
if els:
price = els[0].text
break
else:
price = NoneCause 3: find_element vs find_elements confusion
find_element raises NoSuchElementException on no match. find_elements returns empty list.
from selenium.common.exceptions import NoSuchElementException
try:
price = driver.find_element(By.CSS_SELECTOR, ".price").text
except NoSuchElementException:
price = None
# Or just use find_elements and check
els = driver.find_elements(By.CSS_SELECTOR, ".price")
price = els[0].text if els else NonePrevention
- Default to WebDriverWait + presence_of_element_located for any JS-rendered content
- Use find_element (singular) when you expect exactly one match
- Use find_elements (plural) + iterate when zero or more matches are acceptable
- Catch NoSuchElementException on find_element instead of bare except
Related Guides
- List index out of range (full guide)
- String index out of range
- All IndexError fixes
- Python Tutorial hub
Quick step-by-step summary (click to expand)
- Check the results list before indexing. Use if elements: first_element = elements[0] after calling driver.find_elements.
- Wait for elements before searching. Use WebDriverWait with expected_conditions.presence_of_all_elements_located to ensure elements are loaded before find_elements returns.
- Verify your CSS or XPath selector matches. Copy the selector and paste into browser DevTools console with document.querySelectorAll to preview matches.
- Handle timing issues with explicit retry. For flaky pages, wrap find_elements in a retry loop with a short sleep between attempts.
Frequently Asked Questions
Why IndexError happens
List index out of range means you accessed my_list[i] beyond the list’s actual length. Python lists are indexed from 0 to len(list)-1.
Common triggers
- Off-by-one.
my_list[len(my_list)]fails — uselen(my_list) - 1. - Empty container.
my_list[0]fails when the list is empty. - Wrong data source. CSV had fewer columns than expected.
- Loop range wrong.
for i in range(len(my_list) + 1)— off-by-one. - API returned empty result. Unhandled empty response.
Diagnostic pattern
# BAD — accessing first element without check
def get_first(items):
return items[0] # IndexError if items is empty
# GOOD — guard for empty
def get_first(items):
if not items:
return None
return items[0]
# BETTER — use Optional and let caller handle
from typing import Optional, Sequence, TypeVar
T = TypeVar("T")
def get_first(items: Sequence[T]) -> Optional[T]:
return items[0] if items else None
# For pandas, use .iloc with .empty check
import pandas as pd
def first_row(df: pd.DataFrame) -> Optional[dict]:
if df.empty:
return None
return df.iloc[0].to_dict()
# For enumerate-based loops, this is safe
for i, item in enumerate(items):
print(i, item) # never IndexError
# Never write: for i in range(len(items) + 1)
Best practices
- Prefer enumerate over range(len()). Never off-by-one.
- Guard empty containers. Return None or default before accessing.
- Use slicing.
items[:5]is safe even if items has fewer than 5 elements. - Use type hints with Optional. Communicates that the value may not exist.
- Use pytest with edge cases. Test empty lists, single-element lists, off-by-one boundaries.
Official documentation
What’s the difference between find_element and find_elements in Selenium?
find_element (singular) returns the first match or raises NoSuchElementException. find_elements (plural) returns a list of all matches (possibly empty). For one element use find_element; for multiple use find_elements with iteration.
How do I wait for an element to appear before accessing it?
Use WebDriverWait: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, ‘.price’))). It polls every 500ms for up to 10 seconds and raises TimeoutException if the element doesn’t appear.
What’s the difference between presence_of_element_located and visibility_of_element_located?
presence_of: the element exists in the DOM (may be hidden). visibility_of: the element exists AND has non-zero size AND display is not ‘none’. Use visibility when you intend to click/read; presence when DOM existence is enough.
How do I handle Selenium A/B test variants with different selectors?
Try each selector in a loop with a list of fallbacks. for sel in [primary, fallback1, fallback2]: els = driver.find_elements(…); if els: break. Don’t rely on a single selector in production scrapers.
Why does my Selenium test work locally but fail in CI?
Usually timing: CI environments are slower, so explicit waits become critical. Replace any time.sleep() with WebDriverWait. Also check headless mode differences and screen resolution affecting visibility checks.
![Selenium IndexError on find_elements[0] Fix (2026)](https://itsourcecode.com/wp-content/uploads/2026/06/Selenium-IndexError-on-find_elements0-Fix-2026.png)