How to avoid hCaptcha with Selenium WebDriver?
Prevent selenium driven automation from being detected
First of all, Captcha if was put there on purpose, automation scripts cannot go past it, as that’s what Captcha is designed for. In software testing, a typical approach to Captcha in test automation is to disable Captcha in the test server environment(s). This makes sense, it is internal testing. Do people install locks on every door inside their house?
However, when working with external websites, some activate hCaptcha (or reCaptcha) when accessed via automation scripts.
With message like below:
“One more step
Please complete the security check to access www.mysite.com.Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.
What can I do to prevent this in the future?
Another way to prevent getting this page in the future is to use Privacy Pass”
This sucks for automation. How to avoid it?
Option 1: Using a Chrome plugin to get over it.
I tried the “Privacy Pass” extension, suggested by the hCaptcha page, but no luck.
Maybe another extension will work. Anyway, for instructions on driving the Chrome extension in Selenium, refer to this article.
Option 2 (better): Hide the automation flag to browsers
This approach tries to fool the browser, and prevent automation (driven by Selenium WebDriver) from being detected.
Add an argument --disable-blink-features=AutomationControlled
to the ChromeDriver options.
the_chrome_options.add_argument("--disable-blink-features=AutomationControlled")
Demo Video (Animated GIF):
Run the test, getting the Captcha page
Uncomment the line (above)
Rerun the tests, Fine!
Full Script:
require "selenium-webdriver"
require "rspec"
describe "Hide automation flag to browser" do
before(:all) do
the_chrome_options = Selenium::WebDriver::Chrome::Options.new
the_chrome_options.add_option("detach", true)
the_chrome_options.add_argument("--disable-blink-features=AutomationControlled")
dbgport = rand(40000) + 10000
the_chrome_options.add_argument("--remote-debugging-port=#{dbgport}")
@driver = Selenium::WebDriver.for(:chrome, :capabilities => the_chrome_options, :listener => TestwiseListener.new)
@driver.manage().window().resize_to(1024, 576)
@driver.get("https://canva.com")
end
after(:all) do
@driver.quit unless debugging?
end
it "help search" do
@driver.find_element(:xpath, "//a[@aria-label='Help centre']").click
elem = @driver.find_elements(:xpath, "//input[@type='search']").last
elem.send_keys("DevOps")
sleep 0.5
elem.send_keys(:enter)
sleep 1
puts @driver.title
end
def debugging?
return ENV["RUN_IN_TESTWISE"].to_s == "true" && ENV["TESTWISE_RUNNING_AS"] == "test_case"
end
end
For more Selenium recipes like this, please check my book: Selenium WebDriver Recipes in Ruby.