Como é que a Cloudflare detecta navegadores sem cabeça?
A Cloudflare é uma empresa de tecnologia com uma rede gigante. Concentram-se em serviços como CDN, DNS e vários sistemas de segurança online. A sua Web Application Firewall é normalmente concebida para proteger contra ataques como DDoS ou cross site scripting. Nos últimos anos, a Cloudflare e outros fornecedores do sector introduziram sistemas de impressão digital, capazes de detetar navegadores sem cabeça. Como se pode imaginar, um dos primeiros afectados por estas técnicas é o Selenium. E como a indústria de scraping da Web depende muito desta tecnologia, os scrapers também são diretamente afectados.
Antes de avançar para as técnicas anti-bot, penso que é importante discutir como o cloudflare detecta o Selenium. Bem, o sistema pode ser muito complexo. Por exemplo, existem propriedades em um navegador que um web driver não possui. A interface `navigator` em um navegador tem até mesmo uma propriedade chamada `webdriver` que indica se um navegador é controlado por automação. E isso é uma indicação imediata. Se quiseres experimentar:
- Abra as ferramentas de desenvolvimento do seu navegador
- Navegar para a consola
- Digite o seguinte comando: `navigator.webdriver`
No seu caso, ele deve retornar `false`. Mas se você tentar com o Puppeteer ou Selenium, você obterá `true`. Se você está se perguntando como o Cloudflare aproveita isso para detetar bots, bem, é bem simples. Tudo o que eles precisam fazer é injetar um script como o abaixo no site de seu parceiro:
// detection-script.js
const webdriver = navigator.webdriver
// If webdriver returns true, display a reCaptcha
// In this example, I am transferring the user to a Cloudflare challenge page.
// But you get the idea
if ( webdriver ) location.replace('https://cloudflarechallenge.com')
Claro que, na vida real, há muitos mais níveis de deteção que estes fornecedores utilizam. Até o tamanho do ecrã, a disposição do teclado ou os plugins utilizados pelos browsers são utilizados para identificar especificamente um browser. Se estiver interessado em saber como funciona a deteção sem navegador, veja o meu teste simples de trabalhador de serviço. E isto apenas se nos cingirmos ao browser. Você também pode detetar a atividade de bots examinando o endereço IP de onde a solicitação se origina. Por exemplo, se você estiver usando IPs de datacenter, suas chances de ser bloqueado aumentam a cada solicitação. É por isso que se recomenda a utilização de proxies residenciais ou de ISP quando se está a construir um web scraper.
Como contornar o Cloudflare com o Selenium
Felizmente, a comunidade de raspagem da Web é muito ativa. E como existe uma grande procura para contornar o Cloudflare e outros fornecedores anti-bot, existem soluções de código aberto nessa área. É possível fazer grandes coisas quando as comunidades de programação trabalham em conjunto! Para avançar, sugiro que sigamos estes passos:
- Execute alguns testes para ver se o Selenium padrão pode contornar o Cloudflare
- Adicionar algumas evasões extra para tornar os nossos scripts mais discretos
Vamos então começar com o nosso primeiro passo:
#1: O Selenium padrão pode contornar o Cloudflare?
Não sou do género de fazer suposições. E isso deve-se sobretudo ao facto de não sabermos ao certo como funcionam os sistemas da Cloudflare. Eles usam todo tipo de ofuscação em seu código, o que dificulta a engenharia reversa. É por isso que, ao longo da minha experiência como desenvolvedor, aprendi que testar é a melhor maneira de entender como um sistema funciona. Então, vamos construir um scraper básico e ver como ele se comporta em um alvo real, protegido pelo Cloudflare.
1.1. Configurar o ambiente
Com Python, é melhor isolarmos os nossos projectos dentro de um único diretório. Por isso, vamos criar uma nova pasta, abrir uma janela de terminal e navegar até ela:
# Criar um novo ambiente virtual e ativá-lo
~ » python3 -m venv env && source env/bin/activate
# Instalar dependências
~ » python3 -m pip install selenium
# Criar um novo ficheiro .py e abrir o projeto no seu IDE
~ » touch app.py && code .
1.2. Construir um simples raspador da Web com o Selenium
Agora que já configurou o seu projeto com sucesso, está na hora de adicionar algum código. Não vamos criar nada de muito complexo aqui. Precisamos apenas deste script para fins de teste. Se quiser aprender sobre scraping avançado, consulte este [LINK](AQUI DEVE SER PUBLICADO O ARTIGOLUL) sobre o Pyppeteer.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Configurar o Chrome para abrir em modo headless
options = Options()
options.headless = True
# Criar uma nova instância do Chrome e aceder ao destino
driver = webdriver.Chrome(options=options)
driver.get('https://www.snipesusa.com/')
# Aguarde um pouco para que carregue
time.sleep(10)
# Capture uma imagem da página
driver.get_screenshot_as_file('screenshot.png')
# Feche o navegador
driver.quit()
Agora veja a captura de ecrã. Eis o que obtive:

Penso que é seguro concluir que o teste falhou. O site visado é protegido pelo Cloudflare e, como você pode ver, estamos sendo bloqueados. Portanto, por padrão, o Selenium não é capaz de contornar o Cloudflare. Não vou me aprofundar e verificar com outros provedores de deteção de bots. Se quiser testar mais, aqui estão alguns alvos e seus fornecedores:

#2: O selénio furtivo pode contornar o Cloudflare?
Em primeiro lugar, deixe-me esclarecer os termos. Por Selenium furtivo quero dizer uma versão do Selenium que pode passar despercebida e contornar o Cloudflare. Não estou me referindo a nenhuma técnica específica de furtividade. Existem algumas maneiras de implementar técnicas de evasão no Selenium. Existem pacotes que lidam com isso, ou você pode usar o `execute_cdp_cmd` para interagir diretamente com a API do Chrome. Esta última opção permite-lhe mais controlo, mas requer mais trabalho. Aqui está um exemplo de como você poderia usá-lo para alterar o valor do agente do utilizador:
driver.execute_cdp_cmd('Emulation.setUserAgentOverride', {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win32; x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",
"platform": "Win32",
"acceptLanguage":"ro-RO"
})
Mas teria de passar pelo CDP e identificar as APIs que lhe permitem efetuar todas as alterações necessárias. Por isso, para já, vamos testar com alguns pacotes.
1.1. Selénio furtivo
Há pelo menos dois pacotes que você pode usar para tornar o Selenium furtivo. Até este ponto, porém, nenhum deles é garantido para contornar o Cloudflare. Mais uma vez, precisamos testar e ver se algum deles funciona. Primeiro de tudo, vamos dar uma olhada no `selenium-stealth`. Este pacote é um wrapper em torno do `puppeteer-extra-plugin-stealth`, tornando possível usar as evasões do Puppeteer com o Selenium do Python. Para usá-lo, é necessário instalá-lo primeiro. Abra uma janela de terminal e digite este comando:
# Instalar o selenium-stealth
~ » python3 -m pip install selenium-stealth
Já está tudo pronto. Podemos usá-lo para tornar o nosso raspador anterior mais furtivo:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium_stealth import stealth
import time
# Configurar o Chrome para abrir em modo headless
options = Options()
options.headless = True
# Criar uma nova instância do Chrome
driver = webdriver.Chrome(options=options)
# Aplicar stealth ao seu webdriver
stealth(driver,
languages=["en-US", "en"],
vendor="Google Inc.",
platform="Win32",
webgl_vendor="Intel Inc.",
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)
# Navegue até ao destino
driver.get('https://www.snipesusa.com/')
# Dê algum tempo para carregar
time.sleep(10)
# Tire uma captura de ecrã da página
driver.get_screenshot_as_file('stealth.png')
# Feche o navegador
driver.quit()
Desta vez, ao executar o script, obtive um resultado diferente, em comparação com as definições predefinidas do Selenium:

A segunda opção que pode ser utilizada é o `undetected_chromedriver`. Este é descrito como um 'chromedriver Selenium otimizado'. Vamos testá-lo:
# Instalar o undetected_chromedriver
~ » python3 -m pip install undetected_chromedriver
O código é muito semelhante ao nosso script predefinido. A principal diferença está no nome do pacote. Aqui está um scraper básico com `undetected_chromedriver` e vamos ver se ele consegue contornar o Cloudflare:
import undetected_chromedriver as uc
import time
# Configurar o Chrome para abrir no modo headless
options = uc.ChromeOptions()
options.headless = True
# Criar uma nova instância do Chrome e maximizar a janela
driver = uc.Chrome(options=options, executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')
driver.maximize_window()
# Navegar até ao destino
driver.get('https://www.snipesusa.com/')
# Aguardar algum tempo para carregar
time.sleep(10)
# Capturar imagem da página
driver.get_screenshot_as_file('stealth-uc.png')
# Fechar o navegador
driver.quit()
Mais uma vez, a execução do script resultou bem para mim. Parece que pelo menos estes dois pacotes conseguem contornar com sucesso a proteção do Cloudflare. Pelo menos a curto prazo. Verdade seja dita, as chances são de que, se você usar esses scripts extensivamente, o Cloudflare vai pegar o seu endereço IP e bloqueá-lo.
Por isso, deixem-me apresentar-vos uma terceira opção: Web Scraping API.
1.2. Selenium com API de raspagem da Web
A API de raspagem da Web tem um recurso incrível chamado Modo Proxy. Você pode ler mais sobre ele aqui. Mas o que eu quero notar aqui é que nosso Modo Proxy pode ser integrado com sucesso ao Selenium. Desta forma, tem acesso a todas as funcionalidades de evasão que implementámos. E deixe-me dizer-lhe que temos uma equipa dedicada a trabalhar em técnicas de evasão personalizadas. Em termos técnicos, estamos a lidar com rotações de IP, estamos a utilizar vários proxies, estamos a resolver captchas e estamos a utilizar a API do Chrome para alterar continuamente a nossa impressão digital. Em termos não técnicos, isto traduz-se em menos trabalho da sua parte e numa maior taxa de sucesso. Basicamente, obtém-se a versão mais furtiva do Selenium que existe. E aqui está como isso é feito:
# Instalar o selenium-wire
~ » python3 -m pip install selenium-wire
Estamos a utilizar o `selenium-wire` para utilizar o Selenium com um proxy. Agora aqui está o script:
from seleniumwire import webdriver
import time
# Method to encode parameters
def get_params(object):
params = ''
for key,value in object.items():
if list(object).index(key) < len(object) - 1:
params += f"{key}={value}."
else:
params += f"{key}={value}"
return params
# Your WSA API key
API_KEY = '<YOUR_API_KEY>'
# Default proxy mode parameters
PARAMETERS = {
"proxy_type":"datacenter",
"device":"desktop",
"render_js":1
}
# Set Selenium to use a proxy
options = {
'proxy': {
"http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",
}
}
# Create a new Chrome instance
driver = webdriver.Chrome(seleniumwire_options=options)
# Navigate to target
driver.get('https://www.httpbin.org/get')
# Retrieve the HTML documeent from the page
html = driver.page_source
print(html)
# Close browser
driver.quit()
Se executar este script algumas vezes, verá como o endereço IP muda de cada vez. Este é o nosso sistema de rotação de IP. Em segundo plano, ele também adiciona técnicas de evasão. Nem sequer precisa de se preocupar com elas. Nós tratamos da parte de contornar o Cloudflare para que se possa concentrar mais na análise dos dados.
Conclusões
Se quiser construir um scraper que possa contornar o Cloudflare, precisa de ter em conta uma série de coisas. Uma equipa dedicada pode trabalhar 24 horas por dia, 7 dias por semana, mas mesmo assim não há garantia de que as evasões funcionem sempre. Isso porque, a cada versão do navegador, há uma chance de novos recursos serem adicionados à API. E algumas dessas funcionalidades podem ser utilizadas para identificar e detetar bots.
Diria mesmo que o melhor browser para contornar o Cloudflare e outros fornecedores é aquele que você mesmo constrói. E nós construímos um na Web Scraping API. Agora estamos a partilhá-lo consigo. Por isso, divirtam-se a fazer scraping!




