Node.js爬取Cloudflare保护的WebSocket失败求解决方案
解决DexScreener WebSocket 403错误的可行方案
先修正代码里的基础错误
你的代码里有几个不符合WebSocket标准的参数,这大概率是触发403的直接原因:
- Sec-WebSocket-Version 必须设为
13,这是当前WebSocket协议的唯一标准版本,你写的1会被服务器直接拒绝 - Origin 应该是
https://dexscreener.com(网页的源地址),而非WebSocket的wss://io.dexscreener.com - 没必要手动打乱TLS cipher顺序,这种操作反而容易被Cloudflare识别为异常请求
修正后的基础请求头示例:
const header = { 'Sec-WebSocket-Key': this.generateWebSocketKey(), 'Sec-WebSocket-Version': '13', // 修正为标准版本 'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits', 'Origin': 'https://dexscreener.com', // 修正为网页源 'User-Agent': UserAgent.random().toString(), };
核心问题:绕开Cloudflare的会话验证
Cloudflare对WebSocket连接的验证依赖前置HTTP会话的CF验证状态——你必须先通过Cloudflare的人机验证(哪怕是隐形的),拿到有效的cf_clearance Cookie和相关请求头,才能建立合法的WebSocket连接。
方案1:用无头浏览器自动处理CF验证(最可靠)
直接用Puppeteer或Playwright打开目标页面,让浏览器自动完成Cloudflare的验证流程,然后监听页面内的WebSocket消息。这种方法完全模拟真实用户行为,不需要手动处理任何CF参数:
示例代码(Puppeteer):
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: 'new' }); const page = await browser.newPage(); // 监听页面内的所有WebSocket消息 page.on('websocket', (ws) => { console.log('WebSocket连接建立'); ws.on('message', (data) => { console.log('收到消息:', data.toString()); }); ws.on('close', () => { console.log('WebSocket连接关闭'); }); }); // 打开目标页面,浏览器自动处理CF验证 await page.goto('https://dexscreener.com/new-pairs'); // 等待页面加载完成,确保WebSocket连接建立 await page.waitForTimeout(5000); // 保持运行,直到手动终止 // await browser.close(); })();
方案2:手动获取CF验证会话(适合无浏览器场景)
如果必须用纯Node.js的WebSocket客户端,需要先通过HTTP请求完成CF验证:
- 发送GET请求到
https://dexscreener.com/new-pairs,带上真实的User-Agent - 检查响应是否包含Cloudflare的Turnstile验证页面(状态码503或页面有cf-turnstile元素)
- 完成Turnstile验证(可使用专门的库或第三方验证服务)
- 提取验证后的
cf_clearanceCookie和CF-RAY头 - 在WebSocket连接时,将这些Cookie和头加入请求头
示例代码框架:
const WebSocket = require('ws'); const axios = require('axios'); const crypto = require('crypto'); const UserAgent = require('user-agents'); async function getCFCredentials() { const userAgent = new UserAgent().toString(); const response = await axios.get('https://dexscreener.com/new-pairs', { headers: { 'User-Agent': userAgent }, maxRedirects: 5, withCredentials: true }); // 此处需补充Turnstile验证逻辑,获取有效cf_clearance const cfClearance = response.headers['set-cookie']?.find(c => c.startsWith('cf_clearance'))?.split(';')[0]; const cfRay = response.headers['cf-ray']; return { userAgent, cfClearance, cfRay }; } async function connectWebSocket() { const { userAgent, cfClearance, cfRay } = await getCFCredentials(); if (!cfClearance) { console.error('未获取到有效的CF验证Cookie'); return; } const ws = new WebSocket('wss://io.dexscreener.com/dex/screener/pairs/h24/1?rankBy[key]=trendingScoreH6&rankBy[order]=desc&filters[pairAge][max]=24&filters[liquidity][min]=1000', { headers: { 'User-Agent': userAgent, 'Cookie': cfClearance, 'CF-RAY': cfRay, 'Origin': 'https://dexscreener.com', 'Sec-WebSocket-Version': '13', 'Sec-WebSocket-Key': crypto.randomBytes(16).toString('base64') } }); ws.on('open', () => console.log('连接成功')); ws.on('message', (data) => console.log(data.toString())); ws.on('error', (err) => console.error('错误:', err)); } connectWebSocket();
注意:手动处理Turnstile验证稳定性极低,Cloudflare的验证机制会持续更新,这种方法仅适合临时测试。
额外提示
- 不要频繁更换User-Agent或请求参数,模拟真实用户的稳定行为
- 如果使用代理,确保代理IP未被Cloudflare拉黑
- 尽量保持WebSocket连接的生命周期与真实用户一致,避免频繁建立/断开连接
内容的提问来源于stack exchange,提问作者emmab
相关产品推荐
相关产品推荐

