Creating virtual click (click as human) functions with Selenium

In this tutorial part, I will create a virtual click function, which we'll use that no one could track our click, in simple words, we'll be clicking as humans

When we create automated bots to do stuff for us on the internet, we are usually doing this for a reason. The reason may be to get some cash, data, or something like that. Usually, these sites may have protection from automated programs. If we would use the click() default Selenium function, we would click virtually on the center of an object. It's easy to track or protect from such clicks. But if we would create a function that could click as a human, no one could say that we are using the bot. So in this short tutorial, I will create a virtual click function.

Continuing from the last tutorial, I modified two functions. At first, where we are starting a new Browser, I added an option to open a Chrome browser when we use "2" as an option. "1" is Firefox as before and "3" is no for custom browsers:

def StartBrowser(browser=1, browser_location='', driver_path=''):
    if browser == 1:
        driver = webdriver.Firefox()
    if browser == 2:
        driver = webdriver.Chrome()        
    if browser == 3:
        options = webdriver.ChromeOptions()
        options.binary_location = browser_location
        driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
    #driver.implicitly_wait(30)
    #driver.set_window_size(1920,1080)
    #driver.maximize_window()
    return driver

Our 3rd tutorial part had a quite simple function for opening new tabs, so I added more functionality for more advanced users. This new function can choose to what window we will switch after the new tab opens. There is protection not to hang if our new tab opens only a blank page (possible when the link doesn't work). And you can add functionality if our function opens a wrong link or opened link redirects you somewhere else:

def NewTab(driver, Link, default_page=0, custom=0):
    window_count = len(driver.window_handles)
    driver.execute_script('''window.open("'''+Link+'''","_blank");''')
    while len(driver.window_handles) != window_count+1:
        time.sleep(0.5)
    if custom == 0:
        driver.switch_to.window(driver.window_handles[-1])
    if custom != 0:
        driver.switch_to.window(driver.window_handles[custom])    
    time.sleep(2)
    if driver.current_url == Link:
        current_window = driver.current_window_handle
        return current_window
    if driver.current_url == "about:blank":
        time.sleep(2)
        DriverClose()
        driver.switch_to.window(driver.window_handles[default_page])
        print("current window was about:blank we closed it, trying again in 10s")
        time.sleep(10)
        NewTab(driver, Link, default_page, custom)
    if driver.current_url != Link:
        pass

Here comes the final VirtualClick function we are creating. At first, let's import random library along with other imports. In the next tutorial, I will not explain exceptions. I am doing this in the video tutorial. We can choose we will use random object coordinates click in this function, or we'll always click in the center.

Here is the simplified function version, but if you use it, you will face errors quite soon(not recommended to use):

def VirtualClick(driver, click_object):
    size = click_object.size
    height_rand = random.randint(1,int(sizeList[0])-1)
    width_rand = random.randint(1,int(sizeList[1])-1)
    action = webdriver.common.action_chains.ActionChains(driver)
    action.move_to_element_with_offset(click_object, width_rand, height_rand)
    action.click()
    action.perform()
    return True

So our original function does the same as the simplified version above. But we integrated exceptions to protect from errors. If we would try to find out what our code does above, so at the first line, it gets x and y size of HTML object. In the next two lines, it picks random height_rand and width_rand coordinates. It's random coordinates which are between 1-x and 1-y axis. In the next line, we are using the standard ActionChains function to do everything like a human. Then we are moving our mouse to our chosen random coordinates and performing the virtual click() function. At the last line of code, we return True if everything is fine there.

So bellow is the same code we'll use in our further coding, where we handle exceptions:

def VirtualClick(driver, click_object, UseRandom=True):
    try:
        size = click_object.size
    except StaleElementReferenceException:
        print("StaleElementReferenceException")
        return False
    sizeList = list(size.values())
    height = int(sizeList[0])-1
    width = int(sizeList[1])-1
    if UseRandom == True:
        try:
            height_rand = random.randint(1,height)
        except ValueError:
            height_rand = 1
        try:
            width_rand = random.randint(1,width)
        except ValueError:
            width_rand = 1
    if UseRandom == False:
        height_rand = height
        width_rand = width
    action = webdriver.common.action_chains.ActionChains(driver)
    try:
        action.move_to_element_with_offset(click_object, width_rand, height_rand)
    except StaleElementReferenceException:
        return False
    action.click()
    try:
        action.perform()
    except MoveTargetOutOfBoundsException:
        print("MoveTargetOutOfBoundsException with action.perform()")
        return False
    except StaleElementReferenceException:
        print("StaleElementReferenceException with action.perform()")
        return False
    return True

And here comes the final up to date code:

from selenium import webdriver
import time
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoSuchFrameException
from selenium.common.exceptions import NoSuchWindowException
from selenium.common.exceptions import ElementNotInteractableException
from selenium.common.exceptions import StaleElementReferenceException
from selenium.common.exceptions import MoveTargetOutOfBoundsException
from selenium.common.exceptions import UnexpectedAlertPresentException
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import JavascriptException
import random

def CheckExistsById(driver, CheckId):
    try:
        DriverId = driver.find_element_by_id(CheckId)
    except NoSuchWindowException:
        return False
    return DriverId

def CheckExistsByName(driver, CheckName):
    try:
        DriverName = driver.find_element_by_name(CheckName)
    except NoSuchWindowException:
        return False
    return DriverName

def CheckExistsByXpath(driver, xpath):
    try:
        path = driver.find_element_by_xpath(xpath)
    except NoSuchWindowException:
        return False
    except WebDriverException:
        return False
    except StaleElementReferenceException:
        return False
    return path

def CheckExistsArrayByXpath(driver, xpath):
    try:
        path = driver.find_elements_by_xpath(xpath)
    except NoSuchWindowException:
        return False
    except WebDriverException:
        return False
    except StaleElementReferenceException:
        return False
    return path

def MinimizeWindow(driver):
    try:
        driver.minimize_window()
    except UnexpectedAlertPresentException:
        return False
    return True

def DriverClose(driver):
    try:
        driver.close()
    except NoSuchWindowException:
        print("NoSuchWindowException in driver.close()")
        return False
    return True

def SimpleClick(driver, ObjectToClick):
    try:
        ObjectToClick.click()
    except ElementNotInteractableException:
        return False
    except ElementClickInterceptedException:
        return False
    except TypeError:
        return False
    return True

def StartBrowser(browser=1, browser_location='', driver_path=''):
    if browser == 1:
        driver = webdriver.Firefox()
    if browser == 2:
        driver = webdriver.Chrome()        
    if browser == 3:
        options = webdriver.ChromeOptions()
        options.binary_location = browser_location
        driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
    #driver.implicitly_wait(30)
    #driver.set_window_size(1920,1080)
    #driver.maximize_window()
    return driver

def NewTab(driver, Link, default_page=0, custom=0):
    window_count = len(driver.window_handles)
    driver.execute_script('''window.open("'''+Link+'''","_blank");''')
    while len(driver.window_handles) != window_count+1:
        time.sleep(0.5)
    if custom == 0:
        driver.switch_to.window(driver.window_handles[-1])
    if custom != 0:
        driver.switch_to.window(driver.window_handles[custom])    
    time.sleep(2)
    if driver.current_url == Link:
        current_window = driver.current_window_handle
        return current_window
    if driver.current_url == "about:blank":
        time.sleep(2)
        DriverClose()
        driver.switch_to.window(driver.window_handles[default_page])
        print("current window was about:blank we closed it, trying again in 10s")
        time.sleep(10)
        NewTab(driver, Link, default_page, custom)
    if driver.current_url != Link:
        pass

def VirtualClick(driver, click_object, UseRandom=True):
    try:
        size = click_object.size
    except StaleElementReferenceException:
        print("StaleElementReferenceException")
        return False
    sizeList = list(size.values())
    height = int(sizeList[0])-1
    width = int(sizeList[1])-1
    if UseRandom == True:
        try:
            height_rand = random.randint(1,height)
        except ValueError:
            height_rand = 1
        try:
            width_rand = random.randint(1,width)
        except ValueError:
            width_rand = 1
    if UseRandom == False:
        height_rand = height
        width_rand = width
    action = webdriver.common.action_chains.ActionChains(driver)
    try:
        action.move_to_element_with_offset(click_object, width_rand, height_rand)
    except StaleElementReferenceException:
        return False
    action.click()
    try:
        action.perform()
    except MoveTargetOutOfBoundsException:
        print("MoveTargetOutOfBoundsException with action.perform()")
        return False
    except StaleElementReferenceException:
        print("StaleElementReferenceException with action.perform()")
        return False
    return True

browser_location = "C:/Users/HOME/Desktop/chrome-win/chrome.exe"
driver_path = "C:/Users/HOME/Desktop/chrome-win/chromedriver.exe"
driver = StartBrowser(1, browser_location, driver_path)
time.sleep(1)
driver.get("https://www.google.com")
time.sleep(1)
NewTab(driver, "https://www.google.com/gmail/about/new/")
signin = CheckExistsByXpath(driver, "//a[starts-with(.,'Sign In')]")
VirtualClick(driver, signin)
time.sleep(0.5)
driver.switch_to.window(driver.window_handles[-1])
time.sleep(2)
email = CheckExistsByXpath(driver, "//input[@type='email']")
email.send_keys("email")
next = CheckExistsByXpath(driver, "//span[@class='RveJvd snByac']")
VirtualClick(driver, next)

 

So now we have quite a nice function pack to use in our coding. You can use them for your own purposes or test this code. I wrote a simple example, which may be used to log in to a Gmail account. But this code not always works because Gmail usually changes his login page HTML code, so if it doesn't work, you'll need to adapt it. Another way you can continue on this tutorial series where you will find more interesting stuff on selenium.