首页
/ cobalt API 完整技术指南:/api/json 处理端点、流式下载与请求规范解析

cobalt API 完整技术指南:/api/json 处理端点、流式下载与请求规范解析

2026-09-05 17:02:43作者:廉彬冶Miranda

cobalt 是一个无广告、无跟踪的媒体下载服务,其核心能力全部通过一套极简的 REST API 暴露。本文基于仓库中的 API 官方文档 及后端源码,完整讲解 cobalt 的三个端点(POST /api/jsonGET /api/streamGET /api/serverInfo)的请求体/响应体规范、参数默认值与校验规则、/api/stream 不透明参数的签名与时效机制,以及从请求进入到结果返回的完整处理链路。读完本文,你可以直接在自己的项目中集成 cobalt API,并理解每个参数在服务端真正如何生效。

一、API 总体结构:三个端点各司其职

src/core/api.js 的路由注册可以看出,cobalt 的 API 层只暴露三个面向外部的端点:

端点 方法 作用
/api/json POST 主处理端点:接收媒体链接与下载选项,返回直链、流式链接或选择器
/api/stream GET Live render(流式/实时渲染)端点:携带签名参数,由服务端代理并加工媒体内容
/api/serverInfo GET 返回服务器基本信息(版本、commit、分支、启动时间等)

官方文档 docs/api.md 开头明确声明:官方实例 api.cobalt.tools 可免费用于自己的项目。同时文档中有一条硬性要求:

⚠️ 每个 POST /api/json 请求必须包含 Accept 和 Content-Type 请求头:

Accept: application/json
Content-Type: application/json

这条要求在源码中是真实生效的校验。src/core/api.js 定义了校验正则 acceptRegex = /^application\/json(; charset=utf-8)?$/,并在 路由处理函数 中分别测试 AcceptContent-Type 两个头,任一不匹配即返回错误(分别对应本地化错误码 ErrorInvalidAcceptHeaderErrorInvalidContentType)。

二、POST /api/json:主处理端点

/api/json 是 cobalt 唯一的核心入口。请求体类型与响应体类型均为 application/json

2.1 请求体参数完整说明

以下是 docs/api.md 中请求体变量表的完整内容,并在“源码印证”列标注了每个参数在服务端被消费的位置:

参数 类型 可选值 默认值 说明
url string 作为 URI 编码的 URL null 每个请求必须包含
vCodec string h264 / av1 / vp9 h264 仅对 YouTube 下载生效;手机端推荐 h264
vQuality string 144 / ... / 2160 / max 720 手机端推荐 720 质量
aFormat string best / mp3 / ogg / wav / opus mp3 音频输出格式
filenamePattern string classic / pretty / basic / nerdy classic 改变文件命名方式,预览可在 web 应用中查看
isAudioOnly boolean true / false false 仅下载音频
isTTFullAudio boolean true / false false 启用下载 TikTok 视频中使用的原始声音
isAudioMuted boolean true / false false 在下载的视频中禁用音轨
dubLang boolean true / false false true 时,后端对 YouTube 视频音轨使用 Accept-Language 请求头(用于选择配音语言)
disableMetadata boolean true / false false true 时禁用文件元数据
twitterGif boolean true / false false 控制 Twitter 循环视频是否转换为 .gif
tiktokH265 boolean true / false false 控制是否优先选择 1080p H.265 视频

2.2 参数如何被服务端解析:白名单 + 默认值模板

文档中“默认值”一栏并非摆设。src/modules/processing/request.js 中的 normalizeRequest 函数展示了完整的解析逻辑:

  1. 固定模板兜底:每个请求先被填入一份模板,其中 vCodec: "h264"vQuality: "720"aFormat: "mp3"filenamePattern: "classic" 以及全部布尔项为 false——与文档中的默认值列完全一致;
  2. 键数量限制:请求体中的键数量不得超过模板键数 + 1(即 url 加上 11 个可选参数),多出的未知字段会让请求直接被拒绝(返回 ErrorCantProcess 错误);
  3. 枚举白名单vCodecvQualityaFormatfilenamePattern 的取值必须在 白名单 内才会被采纳(例如 vQuality 允许 max / 4320 / 2160 / 1440 / 1080 / 720 / 480 / 360 / 240 / 144),不在白名单内的值会被静默忽略并回落到默认值;
  4. 布尔归一化isAudioOnlyisTTFullAudioisAudioMuteddubLangdisableMetadatatwitterGiftiktokH265 这 7 个布尔参数(见 booleanOnly 列表)会被强制转换为布尔值;
  5. URL 预处理url 会先经过 decodeURIComponent 再由 normalizeURL 处理,src/modules/processing/url.js 会执行别名域名归一(youtu.beyoutube.com/watchpin.itpinterest.comclips.twitch.tvtwitch.tv/clip 等)并剥离无用的 query/端口/锚点。

另外一个容易被忽略的硬限制:src/core/api.js/api/json 挂载了 express.json({ limit: 1024 }),即 请求体最大 1024 字节,超限会收到 HTTP 400 与 invalid json body。这也解释了为什么该端点只设计为接收轻量级的“链接 + 选项”对象。

2.3 请求处理链路与 URL 校验

参数归一化之后,POST 处理函数 的执行顺序是:

  1. 校验 Accept / Content-Type 头(不合法 → 400 + error);
  2. 校验 url 字段存在(缺失 → 400 + ErrorNoLink);
  3. normalizeRequest 归一化(失败 → 400 + ErrorCantProcess);
  4. extract 解析 URL 得到 hostpatternMatchurl.js 中的 extract:基于 psl 解析公共后缀、按 servicesConfig.json 中的 patterns 做 UrlPattern 匹配;host 不在配置中或服务已禁用则返回 null → 400 + ErrorUnsupported);
  5. 调用 match 分发到具体服务实现(youtubetiktoktwittervimeo 等 20 个服务模块),最终由 matchActionDecider 决定返回 redirect(直链跳转)、stream(流式链接)还是 picker(多文件选择器);
  6. 任何环节抛异常统一兜底为 500 + ErrorSomethingWentWrong

以 YouTube 为例,match.js 展示了 vCodecvQualityisAudioOnlyisAudioMuteddubLang 如何被打包传入 youtube 服务函数;若 URL 来自 music.youtube.com 或显式 isAudioOnly,服务端会强制 quality: "max"format: "vp9" 的音频优先策略。

2.4 响应体字段

根据 docs/api.mdcreateResponse 实现,响应体字段及含义如下:

字段 类型 说明
status string error / redirect / stream / success / rate-limit / picker
text string 各种文本,主要用于错误信息
url string 文件直链,或指向 cobalt live render(/api/stream)的链接
pickerType string various / images
picker array picker 条目数组
audio string 文件直链,或指向 cobalt live render 的链接

status 对应的实际行为(来自 createResponse 的 switch 分支):

  • error:HTTP 400,body 为 { status: "error", text: "..." }text 是经过本地化的错误消息(错误文案集中定义在 src/localization/languages/en.json,如 ErrorNoLinkErrorUnsupportedErrorBrokenLinkErrorLengthLimit 等,可直接对照排查失败原因);
  • success / rate-limitsuccess 携带 textrate-limit 对应 HTTP 429,text 中包含可重试的等待秒数;
  • redirect:HTTP 200,body 为 { status: "redirect", url: "..." }——服务端确认了目标文件的直链(如 Facebook、Instagram、Pinterest、Twitch 等多数视频/图片直接走此路径,见 matchActionDecider.js);
  • stream:HTTP 200,url 是带签名参数的 /api/stream 链接,适用于需要服务端转码、静音、GIF 转换或 HLS 处理的场景(见下文第三节);
  • picker:多媒体的帖子(Twitter 图文、Instagram、TikTok 等)返回条目数组供客户端让用户选择。

2.5 picker 条目字段

picker 中每个条目是一个 object

字段 类型 说明
type string video / photo / gif,仅在 pickerTypevarious 时使用
url string 文件直链,或指向 cobalt live render 的链接
thumb string 条目缩略图,用于 picker 展示;videogif 类型使用

一个特殊的实现细节:createResponse 中 picker 分支 显示,当服务是 tiktokpickerType 固定为 images,且响应会额外携带 audio 字段——它本身就是一个已签名的 /api/stream 音频流链接(由 matchActionDecider 的 tiktok picker 分支 直接调用 createStream 生成),供客户端单独下载原声。

2.6 实际调用示例

结合上述规范,一个最简集成(curl)如下:

curl -X POST "https://<your-api-host>/api/json" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://youtube.com/watch?v=dQw4w9WgXcQ","vQuality":"1080","vCodec":"av1"}'

成功时(需要服务端加工的媒体)返回形如:

{
  "status": "stream",
  "url": "https://<your-api-host>/api/stream?id=...&exp=...&sig=...&sec=...&iv=..."
}

随后用 GET 请求该 url 即可拿到文件本体。若返回 redirect,则 url 已是直链,客户端可直接跟随下载。

三、GET /api/stream:不透明参数背后的签名与时效机制

docs/api.md/api/stream 的原文表述是:通常你会在成功调用 /api/json 后收到指向该端点的 URL;它接收的参数从 API 客户端视角是**不透明(opaque)且不可修改(unmodifiable)**的,并且可能随版本变化,客户端不需要关心其含义。

源码印证了这个承诺,同时揭示了它“不透明”的原因。src/modules/stream/manage.js 中的 createStreamL27-L68)为每次流式下载生成 5 个 query 参数:

参数 长度 生成方式
id 21 nanoid() 随机流标识
exp 13 Date.now() + streamLifespan * 1000 的毫秒时间戳
sig 43 id,exp,iv,sec 计算的 HMAC(盐为启动时 64 字节随机数)
sec 43 16 字节随机数的 base64url(加密密钥)
iv 22 12 字节随机数的 base64url(AES IV)

而服务端 路由侧 在放行前会做三层前置校验:参数齐全性(5 个参数缺一不可)、基础长度(id 必须 21 位、exp 必须 13 位)、签名长度(sig/sec 43 位、iv 22 位),随后 verifyStream 再执行:

  1. HMAC 复核:用同一盐值重算 generateHmac(id, exp, iv, sec),与 sig 不一致返回 401——这保证链接无法被篡改或伪造;
  2. 缓存查找:流数据加密后存于内存缓存(NodeCache),查不到返回 404;
  3. 解密:用 iv + sec 解出真实的下游 URL、请求头、文件名等元数据(客户端永远接触不到加密密钥,服务端也保存的是密文);
  4. 时效校验exp 早于当前时间则 404。

关于时效:src/modules/config.jsstreamLifespan 固定为 90 秒,缓存的 stdTTL 也取该值并开启过期自动删除。因此 /api/stream 链接是短时效的一次性凭证——客户端拿到后应尽快使用,过期后需重新调用 /api/json。官方隐私说明(见 en.json 的 PrivacyPolicy 文案)也与此一致:需要渲染的内容数据仅加密保存在服务器 RAM 中 90 秒。

此外,/api/stream 支持一个速率限制探测参数:带 p 参数时会返回 200 与 { "status": "continue" }api.js L161-L166),文档注释标注该行为在 8.0 之后将不再返回 JSON——集成时不建议依赖它。

四、GET /api/serverInfo:服务器信息

该端点返回当前服务器的基本状态,响应体类型为 application/json,字段如下(与 docs/api.md 的表格一致):

字段 类型 说明
version string cobalt 版本
commit string git commit
branch string git 分支
name string 服务器名称
url string 服务器 URL
cors number CORS 状态(0/1,对应 CORS_WILDCARD
startTime string 服务器启动时间(毫秒时间戳字符串)

serverInfo 对象构造 可见,各字段分别取自 package.jsonversion(当前仓库为 7.15)、启动时传入的 gitCommit/gitBranch、以及环境变量 API_NAMEconfig.js,默认 unknown)、API_URL 等。部署时可用它快速确认实例版本与 CORS 配置是否符合预期。

五、速率限制与运行时约束

文档没有专门展开限速章节,但 rate-limit 是响应 status 的合法值之一,集成时必须处理。源码给出的事实是:

  • /api/json/api/stream 各自挂载了基于 express-rate-limit 的限流器,键是请求 IP 的 HMAC(IPv6 先截断为 /56 前缀以防遍历规避,见 getIP);
  • 触发限流后 /api/json 返回 HTTP 429{ "status": "rate-limit", "text": "...try again in N seconds!" }/api/stream 则直接返回 429;
  • 窗口与阈值由环境变量控制,默认值为 RATELIMIT_WINDOW=60 秒RATELIMIT_MAX=20 次。完整的 API 环境变量列表(含 API_PORTAPI_URLCORS_WILDCARDDURATION_LIMIT 等)参见 docs/run-an-instance.md
  • 响应头暴露了 Ratelimit-LimitRatelimit-PolicyRatelimit-RemainingRatelimit-ResetCORS 配置中 exposedHeaders),客户端可用它们实现平滑退避。

其他值得注意的运行约束:

  • 时长限制DURATION_LIMIT 默认 10800 秒(3 小时),超长视频会被拒绝(对应 ErrorLengthLimit 文案);
  • 服务支持范围:当前启用的服务与 URL 匹配模式集中在 servicesConfig.json(YouTube、TikTok、Twitter/X、Instagram、Bilibili、Vimeo、Twitch 等 20 个服务),每个服务的 enabledsubdomainstldpatterns 都在这里定义——排查“链接无效”类错误时,这是第一参照物;
  • 错误分级createResponse 的 critical 分支 表明部分内部错误(如依赖服务不可达)会返回 500 且带 critical: true 标记,与可重试的 400 错误在语义上不同。

六、集成要点清单

  1. 头必须齐AcceptContent-Type 都必须是 application/json(允许 ; charset=utf-8 后缀),否则 400;
  2. body 要短:请求体上限 1024 字节,且不接受模板之外的多余键;
  3. 参数要合法:枚举参数取值须与白名单一致,否则静默回落默认值;
  4. 按 status 分支处理redirect 跟随 url 下载;stream 尽快(90 秒内)请求 urlpicker 遍历条目让用户选择,TikTok 场景注意 audio 字段是独立的音频流链接;
  5. 处理 429:解析 Ratelimit-* 响应头做退避;
  6. 不要解析 stream 参数/api/stream 的 query 参数是不透明签名凭证,只能原样使用,不能修改、拼接或长期保存。

以上规范在当前仓库(cobalt 7.15,API 入口 src/core/api.js、处理层 src/modules/processing/、流层 src/modules/stream/manage.js)中均有对应实现可查证;若自建实例,请同时参考 docs/run-an-instance.md 完成部署与环境变量配置。

登录后查看全文
热门项目推荐
相关项目推荐