How to fix NotFoundException error in Selenium?
The NotFoundException exception in Selenium is one of the most common errors when writing automation scripts. Usually, it occurs when trying to find a particular element on the page using the find_element
method:
element = driver.find_element(By.ID, "button")
This error never occurs when using the find_elements
method, as it returns an empty []
list if no elements are found on the page.
Selenium WebDriver supports 8 ways to find an element on a page:
- by element ID (By.ID)
- by XPath (By.XPATH)
- by link text (By.LINK_TEXT)
- by partial link text (By.PARTIAL_LINK_TEXT)
- by NAME attribute element (By.NAME)
- by TAG_NAME tag (By.TAG_NAME)
- by CSS class or a combination (By.CLASS_NAME)
- by CSS selector (By.CSS_SELECTOR)
The combination of the search method and the string is called a locator. For example, the By.ID, "button"
locator will find the element <a href="..." id="button">Click me</a>
, and the By.NAME, "login"
locator will find the <input type="text" name="login">
element.
Why does NoSuchElementException occur? If you specify the locator incorrectly when looking for an element, or look for it on the wrong page or at the wrong time, a NoSuchElementException error can occur.
What the NoSuchElementException error message looks like in the console
Usually, in the console, such a message has three important fragments:
- exception class
selenium.common.exceptions.NoSuchElementException
- message
Message: no such element: Unable to locate element
- and what locator the element was searched for:
{"method":"css selector","selector":"[id="buton"]"}
(this fragment will be different in each case, in this example the locatorBy. ID, "button"
).
The full text of the message (the locator will be different in each case):
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="buton"]"}
Invalid locator
The very first step in fixing the NotFoundException error is to recheck the locator.
- You need to make sure that the correct way to find the element is used (By.ID, By.NAME, By.XPATH, and so on).
- Verify that the correct string is being passed along with the method.
The Google Chrome DevTools tool helps with this, which can show the HTML structure of the page and search by CSS selector or XPath selector.
You need to open the page under test and select the "Inspect" item in the context menu:
Then select the "Elements" tab, and press Ctrl + F (Cmd + F), then in the search bar enter the required CSS selector or Xpath and make sure that there is at least one element:
If the element is not found, then the locator is invalid. In the same window, you can try different ways to search for an element (different selectors) and choose a working option.
Sometimes it's hard to know exactly which find_element
statement throws a NoSuchElementException, especially if there are many such statements. This is where the PyCharm debugger can come in handy.
First you need to open the menu Run - View Breakpoints...
Then check the box next to Python Exception Breakpoint - Any Exception, as shown in the screenshot below:
Then you need to run the script again. The moment a NoSuchElementException occurs, the debugger will stop. We need to select the name of our script in the call stack and PyCharm will show the line of code in which the exception occurs:
Wrong page
If you double-checked the locator and made sure that it is correct: the correct way to search and the element is actually present on the page, then you need to make sure that the required page is open at the time of searching for find_element
. After all, if we are on the wrong page, then of course we will not find anything. It is very difficult to look for a black cat in a dark room, especially if it is not there.
To diagnose such a problem, I recommend setting a breakpoint on that find_element
statement (as shown in the screenshot below) that results in a NoSuchElementException and restarting the script. At the moment of stopping, pay attention to which page is open in the browser, whether the element you are looking for is present there. This can be verified through Google Chrome DevTools (see previous point).
If some wrong page is currently displayed in the browser, then you need to double-check the previous steps of the script and figure out why these steps do not open the desired page.
The element has not yet appeared at the time of the search
If in the previous steps you made sure that the locator is correct and that at the time of the search you are on the required page, then it is likely that you need to wait for the element you are looking for to appear in the page code.
Python scripts are very fast and the internet is relatively slow. Consider the example below, in which we do two actions: click on the "Login" button and immediately after the login, click on the "Profile" link:
# Find the login button and log in.
driver.find_element(By.ID, "login").click()
# Open profile.
driver.find_element(By.LINK_TEXT, "Profile").click()
From user's point of view, everything looks logical: two consecutive actions: log in, click on the profile.
Here you need to know one important fact: the automation script process and the web application process work in parallel, and are not synchronized with each other in any way. Therefore, the automation script after login immediately proceeds to the next instruction: click on the profile. But all web servers have a slight delay between actions, so at the time of clicking on the profile, this page has not yet fully loaded.
Typical symptoms of such a NoSuchElementException error are the fact that even under the debugger the correct page is displayed and that the element you are looking for is on the page.
The solution to this problem is to wait for the presence of an element on the page using the WebDriverWait class. Note that the presence of an element on the page refers to the presence of the element in question in the HTML DOM, not visual presence on the page.
A solution in which the automation script will wait for a link with the text Profile to appear on the page:
from selenium.webdriver.support import expected_conditions as EC
# Find the login button and log in.
driver.find_element(By.ID, "login").click()
# Wait for the link to appear on the page.
WebDriverWait(driver, timeout=10).until(
EC.presence_of_element_located((By.LINK_TEXT, "Profile"))
)
# Open profile.
driver.find_element(By.LINK_TEXT, "Profile").click()
In this case, the automation script, before clicking on the link, will wait until it appears on the page.
Conclusions
If you encounter the NoSuchElementException error, then the check algorithm is as follows:
- Check with Google Chrome DevTools that the element with this locator exists on the page.
- Make sure that when searching for an element, the script reaches the required page.
- Add an explicit wait for the element you are looking for using WebDriverWait.