2

I'm creating a basic script that picks a random code from your Discord 2FA backup code text file, and then puts that into the 2fa box and submits that during login. I've already completed getting the bot to enter your email and password and login initially, as well as pick a random code from that text file.

My current issue is that Selenium for some reason can not find the box to enter the 2fa code into: https://gyazo.com/52ca628569f351fec1306332da7e1045

The html for that is:

<input class="inputDefault-_djjkz input-cIJ7To" name="" type="text" placeholder="6-digit authentication code" aria-label="Enter Discord Auth Code" autocomplete="off" maxlength="10" spellcheck="false" value="">

So I'm using

codefill = browser.find_element_by_xpath("""//*[@id="app-mount"]/div[1]/div/div[2]/div/form/div/div[3]/div/div/input""")
codefill.clear()
codefill.send_keys(trycode)

To find the element, clear, then enter the code variable. I keep receiving the following error:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="app-mount"]/div[1]/div/div[2]/div/form/div/div[3]/div/div/input"}
  (Session info: chrome=79.0.3945.130)

Any idea how I can fix this or what I am doing wrong? Thanks :)

TTV jokzyz
  • 349
  • 1
  • 3
  • 13

1 Answers1

0

I'll have to see the full html to be 100% sure, but I'm 90% sure it's because the element you are trying to find is inside a frame element.

So let's say the frame element's name is "FRM", the html will look something like

<frame name ="FRM"><frame>
    ...
     ...
      ...
        <your element>

If the element is inside a frame, you need to switch the driver to the frame before accessing the element.

EC.frame_to_be_available_and_switch_to_it()

This is a great function because not only does it switch, but combined with WebDriverWait, the program waits for the frame to fully load before switching to it.

(+I think you can write the xpath for your element more efficiently)

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

WebDriverWait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"FRM")))
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, '//input[@class="inputDefault-_djjkz input-cIJ7To"]'))).send_keys(trycode)

Of course you can use the other attribute of the frame by using By.ID or By.CLASS_NAME instead.

Matt Yoon
  • 396
  • 4
  • 11