如何绕过Cloudflare的503错误(需启用JavaScript)
解决Cloudflare 503拦截:绕过JS检测并模拟浏览器请求
问题背景
Cloudflare返回503并提示"请启用JavaScript并重载页面",拦截requests、curl等程序请求,但同一主机的Chrome(含无痕模式)可正常访问。已尝试cloudscraper、复制请求头、mechanize、requests_html执行JS等方法均无效,且Chrome存在三次302跳转流程:无Cookie请求触发带cookieSet=1的跳转并设Cookie → 带Cookie访问跳转URL后跳回原URL → 最终带Cookie访问原URL返回200,但curl无-L时直接返回503。
核心识别机制分析
Cloudflare能区分浏览器与程序请求,核心原因可能是以下几点:
- TLS指纹差异:浏览器与
requests/curl的TLS握手参数(如Cipher Suites、扩展字段顺序)不同,Cloudflare会通过该指纹识别非浏览器请求 - 请求行为细节:程序处理跳转的速度、请求头顺序、动态生成的浏览器特有请求头(如
sec-fetch-*)与真实浏览器不一致 - JS环境特征:模拟JS执行的库(如
requests_html)缺少真实浏览器的环境属性(如navigator对象的细节、Canvas指纹)
可行解决方案
1. 使用真实浏览器驱动(最可靠)
直接调用真实Chrome浏览器,完全模拟其TLS握手、跳转逻辑、JS执行环境,Cloudflare无法区分。推荐用Playwright或Selenium,示例代码(Playwright):
from playwright.sync_api import sync_playwright # 启动无头Chrome(headless=True可改为False查看窗口) with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() # 模拟Chrome无痕模式的请求行为 page.goto("目标URL") # 等待页面加载完成(可根据目标页面调整等待条件) page.wait_for_load_state("networkidle") # 获取页面内容 content = page.content() print(content) browser.close()
2. 匹配浏览器TLS指纹
使用支持自定义TLS指纹的请求库,模拟Chrome的TLS握手参数,绕过指纹检测。示例用tls-client库:
import tls_client # 初始化会话,指定Chrome版本的TLS指纹 session = tls_client.Session( client_identifier="chrome118", # 可根据目标Chrome版本调整 random_tls_extension_order=True # 模拟浏览器随机的TLS扩展顺序 ) # 发送请求,自动处理跳转和Cookie response = session.get("目标URL") print(response.status_code) print(response.text)
3. 手动复现完整跳转流程(适合轻量场景)
严格模拟Chrome的三次302跳转逻辑,注意每一步的请求头顺序、Cookie携带、微小延迟:
import requests import time headers = { # 完全复制Chrome无痕模式的请求头,包括sec-fetch-*、Accept等字段的顺序 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.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,application/signed-exchange;v=b3;q=0.9", "Accept-Language": "zh-CN,zh;q=0.9", "Accept-Encoding": "gzip, deflate, br", "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "none", "Sec-Fetch-User": "?1", "Upgrade-Insecure-Requests": "1", "Connection": "keep-alive" } session = requests.Session() session.headers.update(headers) # 第一步:无Cookie请求原URL,获取跳转地址和Cookie first_resp = session.get("目标URL", allow_redirects=False) if first_resp.status_code == 302: redirect_url = first_resp.headers["Location"] # 等待100ms,模拟浏览器跳转延迟 time.sleep(0.1) # 第二步:携带Cookie访问跳转URL second_resp = session.get(redirect_url, allow_redirects=False) if second_resp.status_code == 302: final_url = second_resp.headers["Location"] time.sleep(0.1) # 第三步:访问最终URL final_resp = session.get(final_url) print(final_resp.status_code) print(final_resp.text)
为什么之前的方法失效?
cloudscraper:版本迭代慢,模拟的TLS指纹和JS环境已被Cloudflare识别- 复制请求头:可能遗漏了动态生成的请求头,或未严格遵循浏览器的请求头顺序(Cloudflare会检查字段顺序)
requests_html:JS执行环境为简化版,缺少真实浏览器的环境特征(如Canvas指纹、特定API支持)
内容的提问来源于stack exchange,提问作者Cosmo
相关产品推荐
相关产品推荐

