How to Fix the "Element Not Interactable" Exception

element not interactable exception in selenium web automation

Try setting an implicit wait of maybe 10 seconds.

gmail.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Or set an explicit wait. An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. In your case, it is the visibility of the password input field. (Thanks to ainlolcat's comment)

WebDriver gmail= new ChromeDriver();
gmail.get("https://www.gmail.co.in");
gmail.findElement(By.id("Email")).sendKeys("abcd");
gmail.findElement(By.id("next")).click();
WebDriverWait wait = new WebDriverWait(gmail, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
gmail.findElement(By.id("Passwd")).sendKeys("xyz");

Explanation: The reason selenium can't find the element is because the id of the password input field is initially Passwd-hidden. After you click on the "Next" button, Google first verifies the email address entered and then shows the password input field (by changing the id from Passwd-hidden to Passwd). So, when the password field is still hidden (i.e. Google is still verifying the email id), your webdriver starts searching for the password input field with id Passwd which is still hidden. And hence, an exception is thrown.

Selenium Element not interactable exception- How to overcome this?

let me explain what you are doing wrong. The first problem is in the line browser.find_element_by_name('search-field').send_keys(product_name). If you check the html code, you will see that there are two inputs with name 'search-field', the first one is hidden, that is why you were getting the ElementNotInteractableException:

input_name

you can solve it easily by getting all elements and selecting the second one, just change to browser.find_elements_by_name('search-field')[1].send_keys(product_name)

When you made this fix, you will find a similar problem when trying to submit the search using the button. You can use browser.find_elements_by_xpath('//button[@type="submit"]')[1].click()

To get the prices, you don't need to use the BeautifulSoup, as you already have all the information you need in your browser object. Just get them with product_price_list = browser.find_elements_by_xpath('//strong[@class="price"]')

Here is a complete solution example:

def scrape_currys(product_name):
website_address = 'https://www.currys.co.uk/gbuk/index.html'
options = webdriver.ChromeOptions()
options.add_argument('start-maximized')
options.add_argument("window-size=1200x600")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)

browser = webdriver.Chrome(ChromeDriverManager().install(), options=options)

browser.get(website_address)
time.sleep(2)

# browser.implicitly_wait(30)
browser.find_element_by_id('onetrust-accept-btn-handler').click()
browser.find_elements_by_name('search-field')[1].send_keys(product_name)
browser.find_elements_by_xpath('//button[@type="submit"]')[1].click()

product_price_list = browser.find_elements_by_xpath('//strong[@class="price"]')
return [elem.text for elem in product_price_list]

if __name__ == '__main__':
product_name_list = ['Canon EF 24-105mm f/4L IS II USM Lens']
for product in product_name_list:
price_list = scrape_currys(product)
print(price_list_list)

output:

['£2,329.00', '£409.00', '£1,629.00', '£1,249.00', '£1,149.00', '£649.00', '£959.00', '£599.00', '£329.00', '£589.00', '£2,049.00', '£419.00', '£1,349.00', '£669.00', '£639.00']

Why is the element not interactable using selenium? selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable

The reason why your code did not work is cause, username, password id's are not unique.

Code :-

websites = ['https://www.spacresearch.com/symbol?s=live-deal§or=&geography=']
data = []
for live_deals in websites:
browser.maximize_window()
browser.implicitly_wait(30)
browser.get(live_deals)
#time.sleep(1)
wait = WebDriverWait(browser, 10)

wait.until(EC.element_to_be_clickable((By.XPATH, "(//input[@id='username'])[2]"))).send_keys("xyz@pqr.com")
wait.until(EC.element_to_be_clickable((By.XPATH, "(//input[@id='password'])[2]"))).send_keys("abc@123%$")
wait.until(EC.element_to_be_clickable((By.XPATH, "(//button[text()='Next'])[2]"))).click()

time.sleep(2)
#rest of the code

Imports :

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

2nd 'Element not interactable exception' when iterating on the loop, SELENIUM PYTHON

This is one way to achieve your goal:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import time as t

chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument('disable-notifications')

chrome_options.add_argument("window-size=1280,720")

webdriver_service = Service("chromedriver/chromedriver") ## path to where you saved chromedriver binary
browser = webdriver.Chrome(service=webdriver_service, options=chrome_options)
wait = WebDriverWait(browser, 20)
url = 'https://sprawozdaniaopp.niw.gov.pl/'
browser.get(url)
wait.until(EC.element_to_be_clickable((By.ID, "btnsearch"))).click()
links = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "a[class='dialog']")))
counter = 0
for link in links[:5]:
link.click()
print('clicked link', link.text)
### do your stuff ###
t.sleep(1)
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'span[class="ui-icon ui-icon-closethick"]')))[counter].click()
print('closed the popup')
counter = counter+1

This will print out in terminal:

clicked link STOWARZYSZENIE POMOCY DZIECIOM Z PORAŻENIEM MÓZGOWYM "JASNY CEL"
closed the popup
clicked link FUNDACJA NA RZECZ POMOCY DZIECIOM Z GRODZIEŃSZCZYZNY
closed the popup
clicked link FUNDACJA "ADAMA"
closed the popup
clicked link KUJAWSKO-POMORSKI ZWIĄZEK LEKKIEJ ATLETYKI
closed the popup
clicked link "RYBNICKI KLUB PIŁKARSKI - SZKÓŁKA PIŁKARSKA ROW W RYBNIKU"
closed the popup

Every time you click on a link, a new popup is created. When you close it, that popup will not disappear, but it will stay hidden. So when you click on a new link and then you want to close the new popup, you need to select the new (nth) close button. This should also apply to popup elements, so make sure you account for it. I stopped after the 5th link, of course you will need to remove the slicing to handle all links present in page.
Selenium setup above is chromedriver on linux - you just have to observe the imports, and the code after defining the browser(driver).

Selenium documentation can be found at https://www.selenium.dev/documentation/

ElementNotInteractableException: Message: element not interactable error sending text in search field using Selenium Python

This error message...

ElementNotInteractableException: Message: element not interactable

...implies that the WebElement with whom you are trying to interact isn't interactable (isn't in interactable state) at that point of time.

The two(2) main reasons for this error are:

  • Either you are trying to interact with a wrong/mistaken element.
  • Or you are invoking click() too early even before the element turns clickable / interactable.

To send a character sequence with in the search field you you have to induce WebDriverWait for the element_to_be_clickable() and you can use the following Locator Strategies:

Code Block:

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

options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get("https://thelubricantoracle.castrol.com/industrial/en-DE")
WebDriverWait(driver, 20).until(lambda driver: driver.execute_script('return document.readyState') == 'complete')
time.sleep(3)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='button primary' and contains(@id, 'termsPopup_lbConfirm')]"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@id='search-init']"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='search']"))).send_keys("Example")

Browser Snapshot:

castrol



Reference

You can find a couple of relevant detailed discussions in:

  • selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable when clicking on an element using Selenium Python


Related Topics



Leave a reply



Submit