订阅格式转换教程: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 Party | Clash 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 YAML | sing-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),它就生成一条目标格式的新订阅链接。
部署方式和完整操作我们已经单独写了一篇指南:
那篇覆盖了 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:只需要做格式转换不需要 Web UI;写脚本做批量转换或 CI 自动化;自建后完全掌控转换过程。
什么时候值得到手动改?不动手写脚本怎么做
如果你只有 3-5 个节点要转,不想为这件事部署 Sub-Store 或 subconverter,手动改是最快的。
base64 节点列表 → Clash YAML
先用命令解码 base64:
echo '你的base64字符串' | base64 -d
解码后你会看到 URI 格式的节点行(ss://...、vmess://...、trojan://...)。把这些行放进 YAML 的 proxies: 数组下。然后在文件末尾补上 proxy-groups 和 rules 区块——没有这两块,客户端能显示节点但选不了,或者选了不走代理。最小可用结构如下:
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: 下每个节点的 server、port、password、cipher 字段,拼成 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 JSON | target 必须设成 singbox(不是 sing-box,没有横杠) |
| 公共实例转换后节点延迟全部超时 | 公共实例从它的网络出口测速,延迟不等于你的本地网络测速 | 自建 subconverter 或用 Sub-Store(在本地浏览器完成转换请求) |
三种方案怎么选
| 你的情况 | 选哪个 | 原因 |
|---|---|---|
| 手里多份订阅,想合并成一份 | Sub-Store | Web UI 拖拽合并,不需手动拼 URL |
| 只有一个客户端,偶尔换个格式 | subconverter 公共实例 | 不用部署,拼接 URL 直接贴客户端 |
| 长期主力使用,在意隐私 | Sub-Store(CF Workers)或自建 subconverter | 数据不经过第三方 |
| 只要几个节点,临时应急 | 手动改 YAML / 写 Python 脚本 | 5 分钟搞定,零部署 |
| 写脚本做自动化批量转换 | subconverter HTTP API | 返回纯文本,天然适合管道操作 |
相关阅读
来源与时间
本文最后查看时间:2026-05-29。操作路径会随客户端版本变化,遇到按钮名称不一致时,优先按同义菜单和官方文档查看。