2025, Oct 21 12:00

Fixing the Pyright IDE warning for Selenium 4 relative locators in Python: find_elements with RelativeBy explained

Learn why Selenium 4 Python relative locators work with find_elements despite Pyright IDE warnings. See working example, the type-hint mismatch, and what to do.

Selenium 4 shipped relative locators in Python, but many developers see their IDE warning that driver.find_elements does not accept a RelativeBy. The official snippet looks right, yet the method signature suggests only a By and a value. Here is how to read that mismatch and why your code still runs fine on Selenium 4.33.0 and Python 3.13.5.

Minimal example that triggers the confusion

The following code mirrors the official pattern with locate_with and a relative constraint. The symbol names here are arbitrary, but the logic is identical.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
anchor_el = browser.find_element(By.ID, "below")
para_nodes = browser.find_elements(locate_with(By.CSS_SELECTOR, "p").above(anchor_el))

Many IDEs and Pyright-type tooling warn here because driver.find_elements is defined with a signature like find_elements(self, by=By.ID, value=None), which looks incompatible with a RelativeBy. That does not mean the call fails at runtime.

What is actually happening

driver.find_element and driver.find_elements in Selenium 4 account for a RelativeBy instance when passed as the by argument. The function definition does not enforce By as a strict type, even though the default value is By.ID. In practice, the warning you see is a static analysis false positive: Pyright guessed the type for by and assumed it had to be a By enum. Running the code proves the locator works. If the target element you reference does not exist in the DOM, you will of course get a normal failure unrelated to relative locators.

A working run with relative locators

The example below runs against https://books.toscrape.com. The page has no element with id="below", so the anchor uses the first button on the page by tag name. The rest is identical: locate all p tags above that anchor.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
import selenium
import sys
print("selenium:", selenium.__version__)
print("python:", sys.version)
app = webdriver.Chrome()
app.get("https://books.toscrape.com")
pivot_el = app.find_element(By.TAG_NAME, "button")
above_items = app.find_elements(locate_with(By.CSS_SELECTOR, "p").above(pivot_el))
print("\n--- above ---\n")
for idx, node in enumerate(above_items, 1):
    print(idx, ">", node.text)
all_items = app.find_elements(By.CSS_SELECTOR, "p")
print("\n--- all ---\n")
for idx, node in enumerate(all_items, 1):
    print(idx, ">", node.text)

On this page, relative lookup works. One observation from this run is that it returns p nodes only from the area above the first visible row of buttons and orders them differently than the full list.

It gives p only above the first row of buttons. It also shows p above button in a different order — from bottom to top — while the full list prints top to bottom.

The behavior above is simply what was observed on that page during the run. The key point is that the call pattern with locate_with(...).above(...) works in Selenium 4.

So what is the fix?

There is nothing to “fix” in Selenium for this usage. The relative locator API is valid. If your IDE or Pyright warns about the find_elements call, you can safely run the code anyway. If the HTML does not contain the element used as the anchor, you will get the expected failure, so make sure your reference locator actually exists. Selenium maintainers noted they may tweak type hints to satisfy strict type checkers; if you want to push that forward, open an issue at github.com/SeleniumHQ/selenium/issues with details about the false positive.

Why this matters

Static analysis is helpful, but it is not the ground truth for dynamic libraries like Selenium. Trust the documentation for the call pattern and validate by execution. When an IDE flags a seemingly official example as invalid, it is often a typing or inference limitation rather than a real runtime problem. Including the versions of Python and Selenium in your reports makes it easier for others to reproduce or confirm the behavior.

Takeaways

Relative locators in Selenium 4 do work in Python. When a type checker complains about passing a RelativeBy to find_elements, it is a warning you can ignore in this context. Verify the presence of the anchor element you relate to, run the code to confirm behavior on your page, and if the diagnostic still bothers you, share a reproducible case with versions at the Selenium issue tracker. That way you keep your tests moving while the ecosystem catches up on type hints.

The article is based on a question from StackOverflow by B1LLP4RK and an answer by furas.