You've run into Cloudflare's waiting room, which is the Cloudflare JavaScript challenge **or the I Am Under Attack page.
Web application firewalls (WAFs), or anti-bot services like Cloudflare, use a variety of techniques to identify you as a bot. Your client faces a number of challenges when connecting to the website, such as detecting botnets, IP reputation, HTTP request headers, TLS fingerprinting, HTTP/2 fingerprinting, event tracking and environment API tracking. Cloudflare collects the data from all the mentioned methods as sensor data and validates it for inconsistencies on the server side. Know more about Cloudflare’s bot detection from here: How does Cloudflare detect bots?
There are two different approaches to bypassing a WAF:
- Trying to get ignored by the WAF
- Solving the challenges and captchas
And the most straightforward option is to try to be ignored by the WAF by replicating a real browser’s properties. When you're using browser-based automation tools like Selenium, you need to copy a real browser’s properties. When you use Selenium, the document.webdriver variable is set, which can be easily identified by WAF.
You can use undetected-chromedriver. It is an optimized Selenium Chromedriver patch that should not trigger anti-bot services.
import undetected_chromedriver as uc
from webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time
from fake_useragent import UserAgent
ua = UserAgent()
options = webdriver.ChromeOptions()
options.add_argument(f'user-agent={ua.random}')
chrome_path = ChromeDriverManager().install()
chrome_service = Service(chrome_path)
driver = uc.Chrome(headless = True, options=options, service=chrome_service, use_subprocess=True)
url = "https://etherdelta.com/"
driver.get(url)
time.sleep(5)
#do something
ss = driver.get_screenshot_as_png()
with open("bot-check.png", "wb") as f:
f.write(ss)
driver.quit()
Unfortunately, even after imitating the actual browser characteristics by changing user-agent and proxies, still got stuck in the waiting room. However, the above code works if you use the non-headless Chrome version. So if you are okay with implementing it with a non-headless chrome driver, make the following changes:
. . .
driver = uc.Chrome(options=options, service=chrome_service, use_subprocess=True)
. . .
You can also use JavaScript libraries such as Puppeteer & puppeteer-extra-plugin-stealth.
I tried the same approach with pyppeteer, but it didn’t work.
const puppeteer = require('puppeteer-extra');
const randUserAgent = require('rand-user-agent');
const StealthPlugin = require('puppeteer-extra-plugin-stealth')();
const agent = randUserAgent('desktop');
puppeteer.use(StealthPlugin);
puppeteer.launch({ headless: true }).then(async browser => {
const page = await browser.newPage();
await page.setUserAgent(agent);
await page.goto('https://etherdelta.com/');
await page.waitForSelector('.trading-cont');
await page.waitForTimeout(5_000);
await page.screenshot({ path: 'etherdelta.png', fullPage: true });
console.log(await page.content());
await browser.close();
});