Handling captchas (Completely Automated Public Turing test to tell Computers and Humans Apart) with Selenium is a problem where some testers struggle to find a solution for.
If you are wondering how to handle reCaptcha with Selenium or any other captcha with Selenium, this guide will help with a couple of possible solutions.
We will discuss possible solutions to run automated tests with Captcha enabled websites.
Table of Contents
- What is a Captcha?
- How to disable captchas in your staging environment?
- How to click the reCaptcha checkbox with Selenium WebDriver?
- How to manually solve a captcha during your automated tests?
- How to handle Captcha's with Headless Puppeteer & Playwright?
- How to handle invisible reCaptcha with automated tests?
What is a Captcha?
A Captcha is a task, asked to the user of the website or application.
The task usually involves entering text from an image, performing a simple calculation or matching certain images from a group of mixed images.
The Captcha is similar to a puzzle, used to differentiate humans from automated bots.
The presented captcha is dynamically generated, it's built to be easy to solve by humans and hard to solve by aritificial intelligence (AI) bots.
The most popular captchas are recaptchas (built by Google).
ReCaptcha is popular because it's easy to integrate by webdevelopers and offers accessibility features such as screen-readers and voice-overs (audio challenge).
How to disable captchas in your staging environment?
The easiest and most foolproof way to handle captchas, is to disable the need for captchas during your test. By disabling the captcha, your automated tests do not need to be modified and are not required to enter the captcha response.
The disadvantage of this is approach is that you are testing something which is different from your production environment. Ideally, you want your automated tests to test your product on an environment most closely resembling to your production environment.
If you want to run automated tests using reCaptcha, you can choose to use separate test keys (Site key
and Secret key
).
The reCaptcha will show a big red warning to the user (automated test), warning that the captcha is disabled and should not be used in production.
It is recommended to safeguard your code and credentials in such a way that the test credentials can never be used in production mode.
While in reCaptcha test mode, reCaptcha will accept any answer to the captcha challenge.
Your automated test can click or input any answer, the captcha will always allow the request.
How to click the reCaptcha checkbox with Selenium WebDriver?
During your automated test, you'll want to click the captcha to complete the action.
Once of the mechanisms that reCaptcha uses is checking how long it took for the captcha to complete.
Humans will take a bit longer to complete a captcha task as compared to robots.
Before clicking the captcha, you will want to add a delay (for example using WebDriverWait
) to mimic human behavior.
Please see the example below, where our automated test will detect the captcha, wait a couple of seconds and proceed to complete the captcha.
driver.get("https://testingbot.com/");
new WebDriverWait(driver, 10).until(
ExpectedConditions.frameToBeAvailableAndSwitchToIt(
By.xpath("//iframe[starts-with(@name, 'a-') and starts-with(@src, 'https://www.google.com/recaptcha')]")
)
);
// wait a couple of seconds before clicking the Captcha
new WebDriverWait(driver, 20).until(
ExpectedConditions.elementToBeClickable(
By.cssSelector("div.recaptcha-checkbox-checkmark")
)
).click();
How to manually solve a captcha during your automated tests?
We do not recommend this option, as it requires manual intervention during an automated test, which means your automated tests are not really automated anymore.
With this method, your test will detect the captcha and wait for a specific amount of time, allowing you to enter the correct captcha answer.
While waiting for the captcha answer, you will need to manually look at the captcha question, solve the captcha and pass the answer to the (automated) test.
require "rubygems"
require "selenium-webdriver"
require "selenium/client"
caps = {
:browserName => "internet explorer",
:version => "8",
:platform => "WINDOWS"
}
urlhub = "https://hub.testingbot.com/wd/hub"
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 120
@webdriver = Selenium::WebDriver.for :remote, :url => urlhub, :desired_capabilities => caps, :http_client => client
@webdriver.navigate.to "https://testingbot.com"
captcha = @webdriver.find_element(:name => "captcha")
sleep 50
answer = gets #get user input
captcha.send_keys(answer)
@webdriver.quit
How to handle Captcha's with Headless Puppeteer & Playwright?
If you are using Puppeteer or Playwright instead of Selenium, chances are you are also looking for a way to click a captcha.
With Puppeteer and Playwright you can open an URL containing the captcha, find the specific captcha DOM element and click the captcha:
const puppeteer = require('puppeteer')
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://cloud.testingbot.com?key=key&secret=secret&browserName=chrome&browserVersion=latest'
})
const page = await browser.newPage()
await page.goto('https://testingbot.com')
const captchaElement = await page.$('div.recaptcha-checkbox-checkmark')
await captchaElement.click()
browser.close()
Another solution is to use puppeteer-extra-plugin-recaptcha, which is a Puppeteer plugin to solve captchas (reCAPTCHAs and hCaptchas).
How to handle invisible reCaptcha with automated tests?
reCAPTCHA v2 offers an invisible captcha, which does not require the user to perform any interaction with the captcha.
The invisible captcha will try to block web traffic that appears to come from a bot, so in order to avoid this, we can:
- Change the user-agent of our test script.
- Add random waits to mimic user behavior.
Change the user-agent
Selenium, Puppeteer and Playwright allow you to change your user-agent.
For example, while using Python with Selenium, you can use a Firefox profile and override the general.useragent
flag:
profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "Mozilla/5.0 (Windows NT x.y; rv:10.0) Gecko/20100101 Firefox/52.0")
driver = webdriver.Firefox(profile)
Add random waits
Adding random waits to your automated tests, between various steps of your test, is easy to accomplish:
require "rubygems"
require "selenium-webdriver"
require "selenium/client"
caps = {
:browserName => "internet explorer",
:version => "8",
:platform => "WINDOWS"
}
urlhub = "https://hub.testingbot.com/wd/hub"
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 120
@webdriver = Selenium::WebDriver.for :remote, :url => urlhub, :desired_capabilities => caps, :http_client => client
@webdriver.navigate.to "https://testingbot.com"
# ... perform action
sleep rand(5..10) # wait randomly for 5 up to 10 seconds
# ... perform another action
@webdriver.quit