Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Selenium’s plural finder, then read the item at zero-based index 1. In Python:
from selenium.webdriver.common.by import By
matches = driver.find_elements(By.CLASS_NAME, "item")
if len(matches) > 1:
second = matches[1]
find_element (singular) always returns the first matching element. find_elements returns every match in document order, so the second match is index 1, not 2. Selenium documents this distinction in its element-finder guide.
The direct solution
When several elements have the same class token, do not call find_element and expect it to choose the second one. That method is intentionally limited to the first match. Call find_elements, verify that at least two elements were returned, and select position 1.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallfrom selenium.webdriver.common.by import By
matches = driver.find_elements(By.CLASS_NAME, "item")
if len(matches) < 2:
raise LookupError(f"Expected at least 2 .item elements, found {len(matches)}")
second = matches[1]
print(second.text)
second.click()
The returned list follows the page’s document order. A dynamic page can add, remove, or reorder nodes, so take the list after the page has reached the state you intend to test.
#1 Best Overall
Why find_element is not enough
Selenium’s singular finder returns a reference to the first element found. The plural finder returns all matching references and returns an empty list when there are no matches. This is why the following code cannot select the second item:
first = driver.find_element(By.CLASS_NAME, "item")
Use the plural form whenever your test needs to choose by position, count the matches, or assert that a page rendered the expected number of components. See Selenium’s Finding web elements documentation for the supported pattern.
Python: complete examples
Basic class-name lookup
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
try:
driver.get("https://example.com/products")
items = driver.find_elements(By.CLASS_NAME, "item")
if len(items) < 2:
raise AssertionError(f"Need two items, got {len(items)}")
second_item = items[1]
print(second_item.get_attribute("outerHTML"))
finally:
driver.quit()
Remove the accidental leading space before driver = if you paste this into a file; Python indentation must be consistent. The important operations are the plural finder, the length check, and index 1.
Recommended Free Tools
Waiting for the second match on an asynchronous page
If JavaScript inserts the elements after navigation, an immediate lookup may return zero or one result. Wait until the collection contains at least two elements:
Rank #2
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, 15)
def at_least_two(d):
elements = d.find_elements(By.CLASS_NAME, "item")
return elements if len(elements) >= 2 else False
items = wait.until(at_least_two)
second_item = items[1]
The wait function returns the current list once the condition is true. If the condition never becomes true, Selenium raises a timeout rather than an index error.
Restricting the search to a container
Class names are often reused in headers, sidebars, cards, and dialogs. Locate the intended parent first, then search within it:
from selenium.webdriver.common.by import By
catalog = driver.find_element(By.ID, "catalog")
items = catalog.find_elements(By.CLASS_NAME, "item")
if len(items) < 2:
raise AssertionError("The catalog has fewer than two items")
second_item = items[1]
Searching from a parent prevents unrelated .item elements elsewhere in the document from changing which element is considered second. Selenium supports finding descendants from an already located element.
Use CSS selectors for multiple class tokens
By.CLASS_NAME accepts one class token. If the target must have both item and active, use a CSS selector with adjacent class selectors:
Rank #3
matches = driver.find_elements(By.CSS_SELECTOR, ".item.active")
if len(matches) < 2:
raise LookupError("Fewer than two active items")
second = matches[1]
Do not pass a space-separated string to By.CLASS_NAME:
# Wrong: this is two class tokens, not one
matches = driver.find_elements(By.CLASS_NAME, "item active")
Selenium’s locator strategies identify CSS selector as the option for selector expressions. The Java By API likewise says that className is for one class and directs multi-class matching to cssSelector.
CSS positional selectors versus list indexing
You can express a position in CSS, but CSS position has different semantics depending on the selector. For example, .item:nth-of-type(2) means an .item that is the second element of its tag type among siblings; it does not necessarily mean the second .item anywhere on the page. Fetching all matches and using index 1 is usually clearer when your requirement is “the second result returned by this locator.”
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Java: selecting the second match
Java’s findElements returns a List<WebElement>. Lists are also zero-based, so call get(1) after checking the size:
Rank #4
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com/products");
List<WebElement> matches = driver.findElements(By.className("item"));
if (matches.size() < 2) {
throw new IllegalStateException("Expected at least two .item elements");
}
WebElement second = matches.get(1);
System.out.println(second.getText());
} finally {
driver.quit();
}
For two class tokens, replace the locator with By.cssSelector(".item.active"). The same size check protects get(1) from IndexOutOfBoundsException.
Choosing a robust locator
| Requirement | Locator | Example |
|---|---|---|
| One class token | By.CLASS_NAME |
find_elements(By.CLASS_NAME, "item") |
| Several class tokens | By.CSS_SELECTOR |
find_elements(By.CSS_SELECTOR, ".item.active") |
| Only items in a component | Find parent, then descendants | panel.find_elements(By.CLASS_NAME, "item") |
| Stable semantic hook | Use a dedicated attribute when available | [data-testid='product'] |
Position is inherently less stable than a unique identifier. If the application can provide a reliable id, data-testid, or other component-specific attribute, prefer that. If the requirement genuinely is “second card,” retain the positional selection but scope it to the correct container.
Handling stale and changing elements
StaleElementReferenceException
A framework re-render can replace the nodes after you collected them. The old references then become stale. Re-locate the list immediately before interacting, and avoid keeping WebElement objects across a known refresh:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesdriver.find_element(By.ID, "refresh").click()
wait.until(lambda d: len(d.find_elements(By.CLASS_NAME, "item")) >= 2)
second = driver.find_elements(By.CLASS_NAME, "item")[1]
second.click()
Unexpected ordering
Check the text or an identifying attribute before clicking. This catches hidden placeholders, ads, pinned cards, and responsive rearrangements:
Best Value
items = driver.find_elements(By.CSS_SELECTOR, "#catalog .item")
for i, item in enumerate(items):
print(i, item.text, item.get_attribute("data-id"))
Hidden or duplicate nodes
find_elements returns matching DOM elements, including elements that may not be visible. If visibility matters, filter with is_displayed() or use an explicit wait for visibility. Be careful: filtering changes the meaning of “second”—it becomes the second visible match, not the second DOM match.
Common errors and fixes
- Only the first element is returned: replace
find_elementwithfind_elements. - IndexError or IndexOutOfBoundsException: fewer than two matches existed; check length or wait for the intended state.
- InvalidSelectorException with a class locator: a space-separated class string was supplied; use one token or a CSS selector such as
.item.active. - The wrong second element is clicked: scope the search to a parent container and inspect the returned order and attributes.
- Timeout while waiting: verify the class spelling, iframe context, authentication state, and whether the page actually creates two matching nodes.
- No matches inside an iframe: switch into the correct frame before locating descendants, then switch back when finished.
- Element is present but not clickable: wait for visibility or clickability, scroll it into view, and check for an overlay or consent dialog.
Testing and maintenance checklist
- Confirm the locator matches the intended component, not every use of a generic class.
- Use
find_elementsand index1only after asserting there are at least two results. - Wait for asynchronous rendering when the list is populated after navigation.
- Log text or stable attributes while diagnosing ordering failures.
- Re-find elements after a page update that can replace DOM nodes.
- Prefer stable test attributes over styling classes when your team controls the markup.
Or skip the browser setup
If your goal is to capture a page image rather than interact with the second element, ScreenshotNeo makes a screenshot with one HTTP request. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for all options, including full-page and element capture, device presets, custom CSS and JavaScript, waits, request blocking, cookies, headers, geolocation, PDF output, caching, signed links, asynchronous jobs, bulk capture, and usage reporting.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account.
Frequently Asked Questions
Is the second Selenium element index 1 or 2?
Index 1. Python lists and Java lists are zero-based, so index 0 is the first result and index 1 is the second.
Can I use XPath to select the second class match?
Yes, but use a carefully scoped XPath and still verify the result. For most class-based cases, Selenium’s plural finder plus index 1 is easier to read and maintain.
What happens when there is only one matching element?
The plural finder returns a one-item list. Accessing index 1 or Java get(1) then fails, so check the collection length or wait for a second match.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

