'Can't login to Target.com with Selenium

I'm working on a online purchase bot for target.com and I've run into a blocker. Upon providing correct username and password combination on the login page and clicking "login", I get the following error message on the target login page: "Sorry, something went wrong. Please try again.". This only occurs when running through browser automation. Just wondering if there's a workaround for this issue. Here is my code thus far:

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

PATH="C:\Program Files (x86)\chromedriver.exe"

driver = webdriver.Chrome(PATH)

btn_sign_in_nav = "//span[text()='Sign in']"
btn_sign_in_drop_down = "//div[@id='accountMenu']//div[text()='Sign in']"
input_username_login = "//input[@id='username']"
input_password_login = "//input[@id='password']"
btn_submit_login = "//button[@id='login']"


def xpath_explicit_wait(xpath_val, time_sec):
    if type(time_sec) != int or type(xpath_val) != str:
        print("NUMERICAL VALUES ONLY!")
        driver.quit()
    try:
        element = WebDriverWait(driver, time_sec).until(
           EC.presence_of_element_located((By.XPATH, xpath_val))
        )
    except NoSuchElementException:
        driver.quit()


def login_user(url, username, password):
    driver.get(url)
    driver.implicitly_wait(3)
    driver.find_element_by_xpath(btn_sign_in_nav).click()
    xpath_explicit_wait(btn_sign_in_drop_down, 5)
    driver.find_element_by_xpath(btn_sign_in_drop_down).click()
    driver.implicitly_wait(3)
    driver.find_element_by_xpath(input_username_login).send_keys(username)
    driver.find_element_by_xpath(input_password_login).send_keys(password)
    xpath_explicit_wait(btn_submit_login, 5)
    driver.find_element_by_xpath(btn_submit_login).click()



Solution 1:[1]

There are detection mechanisms on sites like target that detect when you're using selenium and prevent the site from working.

More details can be found in the answer here: Can a website detect when you are using Selenium with chromedriver?

PhoenixBot implements a mechanism that changes the contents of the driver so that it's undetectable. Use this same mechanism and your problems will vanish, as mine did! :-D

https://github.com/Strip3s/PhoenixBot/blob/554441b3b6888a9be46b8aed6d364dc33da92e87/utils/selenium_utils.py#L150-L173

Solution 2:[2]

There is a bot Phoenixbot, I can't speak for the functionality 100% but the auto login portion definitely works and is python. https://github.com/Strip3s/PhoenixBot/blob/master/sites/target.py

I've been attempting to figure out how exactly it's accomplishing that but no success replicating successfully in my own code. Maybe take a look.... If you figure it out I'd love to know.

Solution 3:[3]

IF you have the ability to use Safari webdriver, then see the below code.

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

driver = webdriver.Safari(executable_path='/usr/bin/safaridriver')
driver.get('https://www.target.com/')
action = ActionChains(driver)
driver.find_element(By.XPATH, '//*[@id="account"]').click()
WebDriverWait(driver, 30).until(ec.presence_of_element_located((By.XPATH, '//*[@id="accountNav-signIn"]')))
action.send_keys(Keys.ENTER)
action.perform()
WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.XPATH, '//h2[@class="sc-hMqMXs sc-esjQYD eXTUDl"]')))
driver.find_element(By.ID, 'username').click()
driver.find_element(By.ID, 'username').send_keys('foo')
time.sleep(5)
driver.find_element(By.ID, 'password').click()
driver.find_element(By.ID, 'password').send_keys('bar')
time.sleep(5)
driver.find_element(By.XPATH, "//button[@id=\'login\']").send_keys(Keys.ENTER)
time.sleep(10)
driver.quit()

As @Decian Shanaghy mentioned, Target seems to be bot protected, but Safari webdriver still works.

The time.waits are not needed, you can remove them if you would like.

Solution 4:[4]

For anyone still seeking a solution to this, see this answer at Can a website detect when you are using Selenium with chromedriver?. I did a search through the chromedriver binary executable (MacOS in my case) and changed instances of $cdc_ to $abc_.

I originally suspected Target employs a JavaScript solution to hunting selenium users. I confirmed this suspicion by using selenium to open a browser at https://www.target.com without any automation. I attempted to manually login and obtained a 401 response with the well known "Sorry, something went wrong. Please try again." That didn't rule out a UI-based bot hunting solution but it pointed to a JavaScript hunter.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Declan Shanaghy
Solution 2 John Barnes
Solution 3 Ryan Burch
Solution 4 Dr.Ransom