查看 2026-05-29 8 分钟 进阶 5 步

订阅格式转换教程:Clash ↔ sing-box ↔ Surge ↔ 通用(2026)

客户端报'格式不支持'或导入后节点列表为空,根源通常是订阅格式与客户端不匹配。本文不逐个客户端讲导入,而是把三种转换方案(Sub-Store、subconverter、手动脚本)的适用场景、操作步骤和翻车点一次性讲完。补充入口位置、失败提示和回退动作,重点放在读者能马上检查的页面。

你从服务商拿到了订阅链接,粘贴到客户端里,弹出来一行红字:“不支持的格式”或”解析失败”。打开订阅链接一看——浏览器返回的是 Clash YAML,但你用的是 v2rayNG,它只认 base64 节点列表。或者反过来:sing-box 要 JSON,服务商只给 Clash YAML。

订阅格式不兼容是导入失败最常被忽略的原因。v2rayNG 不吃 Clash YAML,sing-box 不吃 base64 节点列表,Surge 只认自己的 .conf 格式。解决方案有三种:Sub-Store(Cloudflare Workers 免费部署,有 Web UI)、subconverter(自建或公共实例)、手动脚本(适合少量节点快速改)。 新手选 Sub-Store,老手选 self-hosted subconverter。

你的客户端到底要什么格式

在选转换方案之前,先搞清楚两件事:源订阅是什么格式,目标客户端接受什么格式。下表覆盖了 2026 年主流客户端的订阅格式兼容情况。

客户端支持的订阅格式不接受的格式
Clash Verge Rev / Mihomo PartyClash YAML(.yaml)sing-box JSON、base64 节点列表、Surge .conf
sing-box(iOS / Android / 桌面)sing-box JSON;部分支持 Clash YAML(需 clash_api 模块)base64 节点列表、Surge .conf
Surge(iOS / macOS)Surge .conf(INI 风格配置文件)Clash YAML、sing-box JSON、base64
Shadowrocket(iOS)base64 编码的节点列表、SS / SSR / V2Ray 链接Clash YAML、sing-box JSON
Quantumult X(iOS).conf 格式、base64 节点列表完整 Clash YAML、sing-box JSON
Stash(iOS / macOS)Clash YAMLsing-box JSON、Surge .conf
v2rayNG(Android)base64 节点列表、V2Ray 订阅链接Clash YAML、sing-box JSON、Surge .conf
NekoBox(Android)订阅链接(自定义格式)、手动粘贴完整 Clash YAML、Surge .conf
Hiddify(跨平台)sing-box JSON、V2Ray 订阅链接Surge .conf

用表格对一下你的情况:服务商给了 Clash YAML,但你在 iPhone 上用 Shadowrocket——直接导入必然失败。需要把 Clash YAML 转成 base64 节点列表。如果格式本身就匹配,不需要走转换,直接导入即可。

订阅链接打开后,一眼能判断是什么格式吗

就算是同类格式,不同客户端对字段名、缩进和编码的处理也不一样。在你动手转换之前,用浏览器打开原始订阅链接,看返回内容的开头几行:

  • proxies:mixed-port: 开头 → Clash YAML
  • { 开头,且内部有 "outbounds" 字段 → sing-box JSON
  • [General][Proxy] 段落 → Surge .conf
  • 一大段纯 base64 字符(没有 yaml/json 特征)→ base64 节点列表

如果浏览器打开后返回的是登录页面、404 或空白,说明订阅链接本身已失效——这时候不需要转换,需要重新从服务商获取订阅链接。

Sub-Store 部署一次就能永久用,具体怎么操作

Sub-Store 是目前最完善的跨客户端订阅转换与管理工具(GitHub 9K+ stars),技术栈是 Cloudflare Workers + KV。部署后你得到一个带 Web UI 的面板,把一条或多条订阅 URL 导入,勾选目标输出格式(Clash / sing-box / Surge / Quantumult X / Shadowrocket / Loon / Stash / Egern),它就生成一条目标格式的新订阅链接。

部署方式和完整操作我们已经单独写了一篇指南:

Sub-Store 订阅转换与节点管理工具指南

那篇覆盖了 Vercel / Cloudflare Workers / Docker 三种部署方式、Web UI 操作流程、订阅合并和节点过滤。Sub-Store 的转换核心用的是 subconverter 引擎,但多了一层图形化管理面板和 JS 脚本扩展能力。

什么时候选 Sub-Store:手里有多条订阅想合并成一条;经常在不同客户端之间切换,每次都要重新导出不同格式;不想碰命令行和 URL 参数拼接。

subconverter:老手的瑞士军刀

subconverter 是订阅格式转换领域的经典开源工具(GitHub 16K+ stars),支持 20+ 种输入和输出格式。它有两条使用路径:直接用社区维护的公共实例(零部署),或者 Docker 自建(一条命令)。

公共实例:3 分钟上手

公共实例的原理不复杂:把你的原始订阅 URL 和目标格式参数拼进 subconverter 的 HTTP API,浏览器打开这条拼接链接,返回的就是转换后的内容。

拼接格式:

https://<实例域名>/sub?target=<目标格式>&url=<原始订阅URL>&filename=<文件名>

三个核心参数:

  • target:目标格式。clash = Clash YAML;singbox = sing-box JSON;surge = Surge .conf;quanx = Quantumult X;v2ray = V2Ray base64;mixed = 混合格式
  • url:原始订阅链接,必须做 URL 编码。?%3F&%26=%3D
  • filename:输出标识名,部分客户端用这个名字在列表里显示

举个例子:你有一条 Clash 订阅 https://api.example.com/sub?token=abc123&flag=clash,要转成 sing-box JSON:

https://subconverter.example.com/sub?target=singbox&url=https%3A%2F%2Fapi.example.com%2Fsub%3Ftoken%3Dabc123%26flag%3Dclash&filename=mysub

浏览器访问这条拼接后的链接,返回的就是 sing-box JSON。这个拼接链接本身就是一条动态转换订阅——把它贴进 sing-box 客户端的订阅地址栏,每次客户端更新时它都会实时转换源订阅并返回最新内容。

自建:一条 Docker 命令

公共实例有隐私风险:第三方可以看到你的请求,包括订阅 URL 中的 token。主力订阅推荐自建:

docker run -d --restart=always -p 25500:25500 tindy2013/subconverter:latest

部署完成后把上面的公共实例域名换成 http://<你的服务器IP>:25500 就行。完整部署和高级参数(&emoji=true&udp=true&append_type=true&config=<规则集URL>)见我们的另一篇:

subconverter 订阅转换工具指南

什么时候选 subconverter:只需要做格式转换不需要 Web UI;写脚本做批量转换或 CI 自动化;自建后完全掌控转换过程。

什么时候值得到手动改?不动手写脚本怎么做

如果你只有 3-5 个节点要转,不想为这件事部署 Sub-Store 或 subconverter,手动改是最快的。

base64 节点列表 → Clash YAML

先用命令解码 base64:

echo '你的base64字符串' | base64 -d

解码后你会看到 URI 格式的节点行(ss://...vmess://...trojan://...)。把这些行放进 YAML 的 proxies: 数组下。然后在文件末尾补上 proxy-groupsrules 区块——没有这两块,客户端能显示节点但选不了,或者选了不走代理。最小可用结构如下:

proxies:
  - {name: "节点1", type: ss, server: 1.2.3.4, port: 8388, cipher: aes-256-gcm, password: "xxx"}
  - {name: "节点2", type: vmess, server: 5.6.7.8, port: 443, uuid: "xxx", alterId: 0, cipher: auto}

proxy-groups:
  - name: "Proxy"
    type: select
    proxies:
      - "节点1"
      - "节点2"
      - DIRECT

rules:
  - MATCH,Proxy

Clash YAML → base64 节点列表

提取 proxies: 下每个节点的 serverportpasswordcipher 字段,拼成 SS URI:

import yaml, base64

with open("clash_config.yaml") as f:
    config = yaml.safe_load(f)

for p in config.get("proxies", []):
    if p.get("type") == "ss":
        userinfo = base64.b64encode(f"{p['cipher']}:{p['password']}".encode()).decode()
        uri = f"ss://{userinfo}@{p['server']}:{p['port']}#{p['name']}"
        print(uri)

把输出的 URL 行拼在一起 base64 编码一次,贴进 v2rayNG 或 Shadowrocket 的”从粘贴板导入”。

手动转换的硬伤:规则和策略组会全部丢失。 这也是为什么 Sub-Store 和 subconverter 更推荐——它们能保留规则结构并自动生成 proxy-groups。

转换翻车清单

翻车现象原因怎么修
转换后节点名变成 %E9%A6%99%E6%B8%AF 之类的 URL 编码subconverter 默认对中文节点名做 URL 编码,部分客户端不解码直接显示subconverter URL 加 &emoji=true;Sub-Store 输出设置里 Node Name Encoding → Raw
转换后的配置里没有 rules 和 proxy-groups源订阅本身不含规则,或转换时选了 stripped / no-rules 模式Sub-Store 勾选「保留规则」;subconverter 确保 target 不是 clashr,且加 &config=<规则集URL>
sing-box 导入转换后的配置报 schema 错误target 设成了 clash,输出的是 Clash YAML 而非 sing-box JSONtarget 必须设成 singbox(不是 sing-box,没有横杠)
公共实例转换后节点延迟全部超时公共实例从它的网络出口测速,延迟不等于你的本地网络测速自建 subconverter 或用 Sub-Store(在本地浏览器完成转换请求)

三种方案怎么选

你的情况选哪个原因
手里多份订阅,想合并成一份Sub-StoreWeb UI 拖拽合并,不需手动拼 URL
只有一个客户端,偶尔换个格式subconverter 公共实例不用部署,拼接 URL 直接贴客户端
长期主力使用,在意隐私Sub-Store(CF Workers)或自建 subconverter数据不经过第三方
只要几个节点,临时应急手动改 YAML / 写 Python 脚本5 分钟搞定,零部署
写脚本做自动化批量转换subconverter HTTP API返回纯文本,天然适合管道操作

相关阅读

来源与时间

本文最后查看时间:2026-05-29。操作路径会随客户端版本变化,遇到按钮名称不一致时,优先按同义菜单和官方文档查看。

看更多教程:教程库 · 看客户端:客户端目录 · 看下载入口:下载中心