7种经过验证的方法,通过代理绕过Cloudflare检测
Cloudflare处理超过20%的网络流量,并使用多层次的机器人保护系统。通过代理服务器工作时,收到验证码或被阻止的可能性大大增加。在本指南中,我们将讨论检测的技术方面和在2024年有效的绕过方法。
Cloudflare如何识别代理和机器人
Cloudflare使用综合分析系统,检查每个请求的数十个参数。理解检测机制是成功绕过保护的第一步。
主要检测方法
TLS指纹识别: Cloudflare分析SSL/TLS握手的参数(密码套件、扩展、顺序)。每个HTTP客户端都有独特的“指纹”。例如,Python requests使用OpenSSL,具有易于与Chrome或Firefox区分的特定密码集。
在分析请求时,Cloudflare将TLS指纹与声明的用户代理进行匹配。如果您指定Chrome 120,但TLS参数与Python requests相符——这将立即检测到机器人。
| 检查参数 | 分析内容 | 检测风险 |
|---|---|---|
| TLS指纹 | 密码套件、扩展、TLS版本 | 高 |
| HTTP/2指纹 | 头部顺序、SETTINGS帧 | 高 |
| IP声誉 | IP历史、数据中心归属 | 中 |
| JavaScript挑战 | 执行JS、canvas指纹、WebGL | 高 |
| 行为分析 | 请求模式、时序、鼠标移动 | 中 |
自2023年以来,Cloudflare积极使用机器学习分析行为模式。系统不仅跟踪技术参数,还跟踪请求之间的时间间隔、用户的操作顺序、鼠标移动和页面滚动。
伪装TLS指纹
TLS指纹识别是检测机器人的最有效方法。标准的HTTP客户端(requests、curl、axios)生成的指纹与真实浏览器无法混淆。解决方案是使用模拟浏览器TLS行为的专用库。
使用curl-impersonate
curl-impersonate库是curl的修改版本,准确复制流行浏览器的TLS和HTTP/2指纹。支持Chrome、Firefox、Safari和Edge。
# 安装curl-impersonate
git clone https://github.com/lwthiker/curl-impersonate
cd curl-impersonate
make chrome-build
# 使用模拟Chrome 120
curl_chrome120 -x http://username:password@proxy.example.com:8080 \
-H "Accept-Language: en-US,en;q=0.9" \
https://example.com
Python:tls-client库
对于Python,有一个名为tls-client的包装,它在底层使用curl-impersonate,并提供类似requests的接口。
import tls_client
# 创建具有Chrome 120指纹的会话
session = tls_client.Session(
client_identifier="chrome_120",
random_tls_extension_order=True
)
# 配置代理
proxies = {
'http': 'http://username:password@proxy.example.com:8080',
'https': 'http://username:password@proxy.example.com:8080'
}
# 执行请求
response = session.get(
'https://example.com',
proxies=proxies,
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
)
print(response.status_code)
重要: 使用tls-client时,确保头部中的User-Agent与所选的client_identifier相匹配。否则将导致立即检测。
检查TLS指纹
在开始解析之前,建议检查您的TLS指纹。使用服务tls.peet.ws或ja3er.com进行分析。
# 检查指纹
response = session.get('https://tls.peet.ws/api/all')
print(response.json()['tls']['ja3'])
# 与真实Chrome的指纹进行比较:
# https://kawayiyi.com/tls-fingerprint-database/
正确配置HTTP头
即使TLS指纹正确,错误的HTTP头也会暴露机器人。Cloudflare不仅分析头部的存在,还分析它们的顺序、值的格式和逻辑一致性。
Chrome的必需头部
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Ch-Ua-Platform': '"Windows"',
'Cache-Control': 'max-age=0'
}
头部Sec-Ch-Ua-*在Chrome 89中引入,是Client Hints API的一部分。在使用现代用户代理时缺少它们是机器人的明显标志。
头部顺序很重要
在HTTP/2中,头部的顺序对于每个浏览器都是固定的。Python requests和其他标准客户端按字母顺序发送头部,这与浏览器的行为不同。使用支持自定义头部顺序的库。
建议: 使用浏览器的DevTools(网络选项卡→右键单击请求→复制→复制为cURL)获取真实浏览器头部的精确副本。然后根据您的代码进行调整。
动态生成User-Agent
对于所有请求使用相同的User-Agent会增加检测风险。创建一个最新的User-Agent池并进行轮换。
import random
# 最新User-Agent池(2024年12月)
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
]
def get_random_headers():
ua = random.choice(USER_AGENTS)
# 根据所选UA调整其他头部
if 'Chrome' in ua:
return {
'User-Agent': ua,
'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120"',
# ... 其他Chrome头部
}
elif 'Firefox' in ua:
return {
'User-Agent': ua,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# ... Firefox头部
}
# ... 处理其他浏览器
使用无头浏览器
当Cloudflare使用JavaScript挑战或高级检测时,唯一可靠的绕过方法是使用真实浏览器。无头浏览器自动处理JavaScript、cookies,并生成完全真实的指纹。
使用Playwright和反检测补丁
Playwright是Selenium的现代替代品,性能更好。然而,标准的Playwright容易通过navigator.webdriver和其他标记被检测到。使用playwright-stealth进行伪装。
from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync
def bypass_cloudflare(url, proxy):
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={
"server": f"http://{proxy['host']}:{proxy['port']}",
"username": proxy['username'],
"password": proxy['password']
},
args=[
'--disable-blink-features=AutomationControlled',
'--disable-dev-shm-usage',
'--no-sandbox'
]
)
context = browser.new_context(
viewport={'width': 1920, 'height': 1080},
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
locale='en-US',
timezone_id='America/New_York'
)
page = context.new_page()
stealth_sync(page) # 应用反检测补丁
# 转到页面
page.goto(url, wait_until='networkidle', timeout=30000)
# 等待通过Cloudflare挑战(通常5-10秒)
page.wait_for_timeout(8000)
# 检查是否成功绕过
if 'Just a moment' in page.content():
print('Cloudflare挑战未通过')
return None
# 提取cookies以供后续使用
cookies = context.cookies()
html = page.content()
browser.close()
return {'html': html, 'cookies': cookies}
# 使用
proxy_config = {
'host': 'proxy.example.com',
'port': 8080,
'username': 'user',
'password': 'pass'
}
result = bypass_cloudflare('https://example.com', proxy_config)
使用Puppeteer Extra和插件
对于Node.js生态系统,最佳解决方案是使用带有puppeteer-extra-plugin-stealth插件的puppeteer-extra。该插件应用超过30种不同的自动化伪装技术。
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
async function bypassCloudflare(url, proxyUrl) {
const browser = await puppeteer.launch({
headless: 'new',
args: [
`--proxy-server=${proxyUrl}`,
'--disable-blink-features=AutomationControlled',
'--window-size=1920,1080'
]
});
const page = await browser.newPage();
// 设置视口和用户代理
await page.setViewport({ width: 1920, height: 1080 });
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
// 重写navigator.webdriver
await page.evaluateOnNewDocument(() => {
delete Object.getPrototypeOf(navigator).webdriver;
});
// 转到页面
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
// 等待通过挑战
await page.waitForTimeout(8000);
// 获取内容和cookies
const content = await page.content();
const cookies = await page.cookies();
await browser.close();
return { content, cookies };
}
// 示例使用
bypassCloudflare('https://example.com', 'http://user:pass@proxy.example.com:8080')
.then(result => console.log('成功'))
.catch(err => console.error(err));
性能: 无头浏览器消耗的资源显著更多(每个实例200-500 MB RAM)。对于高负载任务,仅在获取cookies时使用它们,然后切换到带有这些cookies的HTTP客户端。
选择绕过Cloudflare的代理类型
代理类型对绕过的成功率至关重要。Cloudflare维护数据中心IP地址的数据库,并对其应用更严格的检查规则。
| 代理类型 | 绕过概率 | 速度 | 成本 | 推荐 |
|---|---|---|---|---|
| 数据中心 | 30-40% | 高 | 低 | 仅与无头浏览器一起使用 |
| 住宅 | 85-95% | 中等 | 高 | 最佳选择 |
| 移动 | 90-98% | 中等 | 非常高 | 用于关键任务 |
| ISP(静态住宅) | 80-90% | 高 | 中等 | 价格与质量的平衡 |
为什么住宅代理更有效
住宅代理使用真实设备的IP地址(家庭路由器、智能手机)。Cloudflare无法大规模阻止这些IP,因为这会阻止普通用户。统计数据显示,住宅IP收到验证码的频率比数据中心低15-20倍。
使用住宅代理时,地理位置至关重要。如果目标网站面向美国,使用来自亚洲的代理将增加可疑性。选择具有广泛地理覆盖和城市定向能力的提供商。
移动代理以确保最大可靠性
移动代理使用移动运营商的IP地址(4G/5G)。移动网络的特点是通过飞行模式动态更换IP,这提供了几乎无限数量的干净IP地址。移动IP被阻止的概率接近于零。
# 通过API轮换移动IP的示例
import requests
import time
def rotate_mobile_ip(proxy_api_url):
"""更换移动代理的IP"""
response = requests.get(f"{proxy_api_url}/rotate")
if response.status_code == 200:
print("IP成功更换")
time.sleep(5) # 等待更改生效
return True
return False
# 使用移动代理
mobile_proxy = "http://user:pass@mobile.proxy.com:8080"
for i in range(10):
# 执行请求
response = requests.get(
'https://example.com',
proxies={'http': mobile_proxy, 'https': mobile_proxy}
)
# 每次请求后轮换IP
rotate_mobile_ip('https://api.proxy.com/mobile')
管理cookies和会话
成功通过Cloudflare挑战后,服务器会设置cookies(cf_clearance、__cfduid等),以确认客户端的合法性。正确管理这些cookies可以避免重复检查。
提取和重用cf_clearance
cf_clearance cookie通常有效期为30-60分钟。在通过无头浏览器获取后,可以在常规HTTP请求中使用。
import requests
import pickle
from datetime import datetime, timedelta
class CloudflareCookieManager:
def __init__(self, cookie_file='cf_cookies.pkl'):
self.cookie_file = cookie_file
self.cookies = self.load_cookies()
def load_cookies(self):
"""加载保存的cookies"""
try:
with open(self.cookie_file, 'rb') as f:
data = pickle.load(f)
# 检查过期时间
if data['expires'] > datetime.now():
return data['cookies']
except FileNotFoundError:
pass
return None
def save_cookies(self, cookies, ttl_minutes=30):
"""保存带TTL的cookies"""
data = {
'cookies': cookies,
'expires': datetime.now() + timedelta(minutes=ttl_minutes)
}
with open(self.cookie_file, 'wb') as f:
pickle.dump(data, f)
def get_cf_clearance(self, url, proxy):
"""通过浏览器获取cf_clearance"""
if self.cookies:
return self.cookies
# 这里是启动浏览器的代码(来自前面的部分)
# ...
browser_cookies = bypass_cloudflare(url, proxy)['cookies']
# 转换为requests格式
cookies_dict = {c['name']: c['value'] for c in browser_cookies}
self.save_cookies(cookies_dict)
self.cookies = cookies_dict
return cookies_dict
def make_request(self, url, proxy):
"""自动管理cookies的请求"""
cookies = self.get_cf_clearance(url, proxy)
response = requests.get(
url,
cookies=cookies,
proxies={'http': proxy, 'https': proxy},
headers=get_random_headers()
)
# 如果再次收到挑战——更新cookies
if response.status_code == 403 or 'cf-browser-verification' in response.text:
print("Cookies过期,正在获取新的...")
self.cookies = None
return self.make_request(url, proxy)
return response
# 使用
manager = CloudflareCookieManager()
response = manager.make_request(
'https://example.com/api/data',
'http://user:pass@proxy.example.com:8080'
)
将cookies绑定到IP地址
Cloudflare将cf_clearance绑定到通过挑战的IP地址。在其他IP上使用此cookie将导致阻止。在使用轮换代理时,必须为每个IP存储单独的cookies集。
import hashlib
class IPBoundCookieManager:
def __init__(self):
self.cookies_by_ip = {}
def get_ip_hash(self, proxy_url):
"""为代理创建哈希以进行识别"""
return hashlib.md5(proxy_url.encode()).hexdigest()
def get_cookies_for_proxy(self, proxy_url, target_url):
"""获取特定代理的cookies"""
ip_hash = self.get_ip_hash(proxy_url)
if ip_hash in self.cookies_by_ip:
cookies_data = self.cookies_by_ip[ip_hash]
if cookies_data['expires'] > datetime.now():
return cookies_data['cookies']
# 通过浏览器获取新的cookies
new_cookies = self.fetch_cookies_with_browser(target_url, proxy_url)
self.cookies_by_ip[ip_hash] = {
'cookies': new_cookies,
'expires': datetime.now() + timedelta(minutes=30)
}
return new_cookies
代理轮换和请求频率控制
即使技术栈正确,从一个IP发出的请求频率过高也会触发速率限制。Cloudflare分析流量模式并识别异常活动。
代理轮换策略
轮换有三种主要方法:轮流(顺序)、随机和粘性会话(会话绑定)。对于绕过Cloudflare,最佳策略是粘性会话,并限制每个IP的请求。
import time
import random
from collections import defaultdict
from datetime import datetime, timedelta
class SmartProxyRotator:
def __init__(self, proxy_list, max_requests_per_ip=20, cooldown_minutes=10):
self.proxy_list = proxy_list
self.max_requests_per_ip = max_requests_per_ip
self.cooldown_minutes = cooldown_minutes
# 使用计数器
self.usage_count = defaultdict(int)
self.last_used = {}
self.cooldown_until = {}
def get_proxy(self):
"""获取下一个可用的代理"""
available_proxies = []
for proxy in self.proxy_list:
# 检查冷却时间
if proxy in self.cooldown_until:
if datetime.now() < self.cooldown_until[proxy]:
continue
else:
# 冷却时间结束后重置计数器
self.usage_count[proxy] = 0
del self.cooldown_until[proxy]
# 检查请求限制
if self.usage_count[proxy] < self.max_requests_per_ip:
available_proxies.append(proxy)
if not available_proxies:
# 如果所有代理都在冷却中——等待
wait_time = min(
(self.cooldown_until[p] - datetime.now()).total_seconds()
for p in self.cooldown_until
)
print(f"所有代理都在冷却中。等待{wait_time:.0f}秒...")
time.sleep(wait_time + 1)
return self.get_proxy()
# 选择使用最少的代理
proxy = min(available_proxies, key=lambda p: self.usage_count[p])
self.usage_count[proxy] += 1
self.last_used[proxy] = datetime.now()
# 达到限制时设置冷却时间
if self.usage_count[proxy] >= self.max_requests_per_ip:
self.cooldown_until[proxy] = datetime.now() + timedelta(
minutes=self.cooldown_minutes
)
print(f"代理{proxy}达到限制。冷却{self.cooldown_minutes}分钟。")
return proxy
def add_delay(self):
"""在请求之间添加随机延迟(模拟人类行为)"""
delay = random.uniform(2, 5) # 2-5秒
time.sleep(delay)
# 使用
proxy_pool = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
# ... 50-100个代理以确保稳定运行
]
rotator = SmartProxyRotator(
proxy_pool,
max_requests_per_ip=15, # 保守值
cooldown_minutes=15
)
# 执行请求
for i in range(1000):
proxy = rotator.get_proxy()
response = requests.get(
'https://example.com/page',
proxies={'http': proxy, 'https': proxy},
headers=get_random_headers()
)
print(f"请求 {i+1}: {response.status_code}")
rotator.add_delay()
自适应速率限制
更先进的方法是根据服务器的响应动态调整请求频率。如果开始出现429错误或验证码,则自动降低速度。
class AdaptiveRateLimiter:
def __init__(self, initial_delay=3.0):
self.delay = initial_delay
self.min_delay = 1.0
self.max_delay = 30.0
self.success_streak = 0
self.failure_streak = 0
def on_success(self):
"""成功请求——可以加速"""
self.success_streak += 1
self.failure_streak = 0
if self.success_streak >= 10:
# 将延迟减少10%
self.delay = max(self.min_delay, self.delay * 0.9)
self.success_streak = 0
def on_failure(self, status_code):
"""错误——减速"""
self.failure_streak += 1
self.success_streak = 0
if status_code == 429: # 速率限制
# 激进减速
self.delay = min(self.max_delay, self.delay * 2.0)
elif status_code == 403: # 可能被阻止
self.delay = min(self.max_delay, self.delay * 1.5)
print(f"延迟增加到 {self.delay:.2f}s")
def wait(self):
"""在下一个请求之前等待"""
# 添加±20%的随机性
actual_delay = self.delay * random.uniform(0.8, 1.2)
time.sleep(actual_delay)
绕过的现成工具和库
从零开始开发自己的解决方案需要时间和专业知识。现有的工具可以自动化绕过Cloudflare的过程。
cloudscraper(Python)
cloudscraper库是requests的一个扩展,能够自动解决JavaScript挑战。它适用于基本保护,但可能无法处理高级检查。
import cloudscraper
# 创建支持代理的scraper
scraper = cloudscraper.create_scraper(
browser={
'browser': 'chrome',
'platform': 'windows',
'desktop': True
}
)
# 配置代理
proxies = {
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
}
# 执行请求
response = scraper.get('https://example.com', proxies=proxies)
if response.status_code == 200:
print("成功绕过")
print(response.text)
else:
print(f"错误:{response.status_code}")
FlareSolverr(通用)
FlareSolverr是一个代理服务器,它启动无头浏览器来解决Cloudflare挑战。通过HTTP API工作,支持任何编程语言。
# 通过Docker启动FlareSolverr
docker run -d \
--name=flaresolverr \
-p 8191:8191 \
-e LOG_LEVEL=info \
ghcr.io/flaresolverr/flaresolverr:latest
# 从Python使用
import requests
def solve_cloudflare(url, proxy=None):
flaresolverr_url = "http://localhost:8191/v1"
payload = {
"cmd": "request.get",
"url": url,
"maxTimeout": 60000
}
if proxy:
payload["proxy"] = {
"url": proxy
}
response = requests.post(flaresolverr_url, json=payload)
result = response.json()
if result['status'] == 'ok':
return {
'html': result['solution']['response'],
'cookies': result['solution']['cookies'],
'user_agent': result['solution']['userAgent']
}
else:
raise Exception(f"FlareSolverr错误:{result['message']}")
# 示例使用
result = solve_cloudflare(
'https://example.com',
proxy='http://user:pass@proxy.example.com:8080'
)
print(result['html'])
undetected-chromedriver
修改版的Selenium ChromeDriver,自动应用多种反检测技术。使用起来比Playwright简单,但灵活性较差。
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def bypass_with_uc(url, proxy):
options = uc.ChromeOptions()
options.add_argument(f'--proxy-server={proxy}')
options.add_argument('--disable-blink-features=AutomationControlled')
driver = uc.Chrome(options=options, version_main=120)
try:
driver.get(url)
# 等待Cloudflare挑战消失
WebDriverWait(driver, 20).until_not(
EC.presence_of_element_located((By.ID, "cf-spinner-please-wait"))
)
# 为了可靠性额外等待
time.sleep(3)
# 获取结果
html = driver.page_source
cookies = driver.get_cookies()
return {'html': html, 'cookies': cookies}
finally:
driver.quit()
# 使用
result = bypass_with_uc(
'https://example.com',
'http://user:pass@proxy.example.com:8080'
)
组合方法: 最佳策略是仅在初始获取cookies时使用无头浏览器,然后切换到带有这些cookies的HTTP客户端(tls-client、cloudscraper)。这在可靠性和性能之间提供了平衡。
结论
通过代理绕过Cloudflare需要综合方法:正确的TLS指纹、真实的HTTP头、高质量的代理和合理的会话管理。关键建议:
- 使用住宅或移动代理而不是数据中心
- 使用具有正确TLS指纹的库(tls-client、curl-impersonate)
- 对于复杂情况,使用带有反检测补丁的无头浏览器
- 保存和重用cf_clearance cookies
- 根据速率限制轮换代理(每个IP不超过15-20个请求)
- 在请求之间添加随机延迟(2-5秒)
Cloudflare的保护机制不断演变,因此定期更新工具和调整策略非常重要。监控指纹技术的变化,并在最新版本的保护上测试解决方案。
为了稳定运行,建议使用具有广泛IP池和自动轮换的专业代理服务。