deepseek 不提供 websocket 接口,仅支持 rest api;流式响应应使用 fetch + readablestream 解析 sse 风格数据,注意 json 转义字符二次解析及 cors 限制需后端代理。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

WebSocket 连接不上,DeepSeek 官方没提供 SDK 怎么办
DeepSeek 当前(截至 2024 年中)**不开放 WebSocket 接口**,所有公开文档和 API 列表里只有 /v1/chat/completions 这类 REST 接口。所谓“DeepSeek WebSocket 实时通信”是误传或混淆——你实际想做的,大概率是用 WebSocket 封装调用它的 REST API,或对接第三方中转服务。
常见错误现象:Connection refused、404 Not Found、405 Method Not Allowed 出现在尝试 ws://api.deepseek.com/... 或类似地址时;浏览器控制台报 Failed to construct 'WebSocket'。
- 别硬连
api.deepseek.com的 WebSocket 路径——它根本没开这个服务 - 官方只支持 HTTP/HTTPS,
ws://和wss://均无效 - 如果你看到某份“DeepSeek WebSocket 示例”,它要么是伪造的,要么背后跑的是自建代理/中转层
想实现流式响应(streaming),该用 fetch 还是 EventSource
DeepSeek 的 /v1/chat/completions 支持 stream=true 参数,返回的是 chunked transfer-encoding 的 SSE 风格文本流(每行以 data: 开头),不是 WebSocket 协议。所以优先选 fetch + ReadableStream,而不是 EventSource(后者对非标准 SSE 响应兼容性差,且无法带认证头)。
关键区别:
-
fetch可携带Authorization头,EventSource不行(除非用 CORS proxy,引入额外风险) -
fetch+response.body.getReader()能精确控制 chunk 解析,避免粘包或截断 - DeepSeek 返回的不是纯 SSE 格式:它混有空行、
data:前可能有空格、末尾无双换行,EventSource容易卡住或丢 chunk
示例要点:
fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer <your-key>'
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [{role: 'user', content: 'hello'}],
stream: true
})
})
.then(r => r.body.getReader())
.then(reader => {
const decoder = new TextDecoder();
function read() {
return reader.read().then(({done, value}) => {
if (done) return;
const text = decoder.decode(value);
// 手动按行 split,过滤空行,提取 data: 后内容
text.split('
').forEach(line => {
if (line.startsWith('data: ')) {
const json = line.slice(6).trim();
if (json && json !== '[DONE]') {
try {
const parsed = JSON.parse(json);
console.log(parsed.choices?.[0]?.delta?.content || '');
} catch {}
}
}
});
return read();
});
}
return read();
});
stream=true 下 response 乱码、中文变 uXXXX 怎么办
不是编码问题,是 DeepSeek 返回的 JSON chunk 里,content 字段本身是已转义的 Unicode 字符串(比如 "\u4f60\u597d"),而你直接 JSON.parse 后又没进一步解码。浏览器不会自动把 JSON 中的 u 序列还原成字符——它只是字符串字面量的一部分。
解决方法很简单:拿到 delta.content 后,用 JSON.parse('"' + str + '"') 再解析一次,或用 String.fromCodePoint() 手动转换(但前者更稳)。
- 错误写法:
console.log(chunk.choices[0].delta.content)→ 输出"\u4f60\u597d" - 正确写法:
const raw = chunk.choices[0].delta.content; const decoded = JSON.parse(`"${raw}"`); console.log(decoded); - 注意:必须加引号包裹再 parse,否则
JSON.parse(raw)会报错(raw是字符串,不是合法 JSON) - 如果
content为空或undefined,先判空再操作,否则JSON.parse('""')没问题,但JSON.parse(undefined)会炸
前端直连 DeepSeek API 有跨域(CORS)问题吗
有,而且无法绕过——DeepSeek 的 API 响应头里没有 Access-Control-Allow-Origin: *,浏览器会直接拦截请求。这不是你代码的问题,是服务端策略限制。
这意味着:你不能在纯前端页面(如本地 file:// 或任意域名 HTML)里直接 fetch DeepSeek API。必须走后端代理,或用支持 CORS 的网关(比如 Vercel Edge Function、Cloudflare Worker)中转。
- 开发阶段可用
localhost:3000启一个 Express/Nest 代理,把/api/deepseek转发到https://api.deepseek.com - 不要在前端硬写 API key:哪怕加了 CORS 代理,key 也会暴露在浏览器网络面板里,等同于公开
- 真正安全的做法是:前端只传 prompt 给你自己的后端,后端用服务端 key 请求 DeepSeek,再把结果流式转发回前端(用
res.write()或TransformStream)
最常被忽略的一点:很多人以为“只要开了代理就万事大吉”,却忘了 key 管理和流式透传的 buffer 控制——后端不及时 write,前端就会卡住,用户体验和真实 WebSocket 几乎没差别,但底层完全是 HTTP。











