URL 编码与解码

全球通用工具

百分号编码让 URL 能携带那些原本会被当作结构的字符:空格、开启下一个参数的 `&`、开启片段的 `#`。这个页面把纯文本编码成这种形式,也能把转义文本解回来;自动模式会判断该往哪个方向走,并把判断结果说出来。

自动模式会编码纯文本,并解码已经含有 `%` 转义的字符串,同时说明走了哪个方向。

一个设置讲清 encodeURI 与 encodeURIComponent 的区别,也解释了链接里的加号为什么有时会变成空格。

粘贴一整条 URL、一个查询值,或一段已经含百分号转义的字符串。

留空则使用 “encoded.txt”。

边输入边更新。所有计算都在你的浏览器里完成,数据不会离开本机。

文本已为 URL 编码

18 个额外字符

按查询字符串里的一个值编码。18 个字符是为了转义那些否则会被 URL 解析器当作结构的字符而增加的。

输入
46 个字符
输出
64 个字符

编码后的 URL

https%3A%2F%2Fdanfio.app%2Ftools%3Fq%3Dhello%20world%26lang%3Den

可以复制,也可以下载成文件。放进链接、iframe 的 src 或 <form> 字段值的就是它。

这些数字没有说明的事

  • 百分号编码有三种常见口径,它们对空格的处理并不一致:查询值里是 %20,表单数据里是 +,路径里也是 %20。上面选择的范围就是本次应用的口径,所以输出只针对一种语境。
  • 只编码一次。对已经转义过的 URL 再编码,% 本身也会被转义,因为百分号就是一个普通字符 —— 查询字符串里 %26 反复出现,正是这件事意外发生的结果。
  • 编码不是加密:它存在是为了让 URL 能携带那些原本会破坏结构的字符,并不隐藏任何东西。
查询字符串里的一个值是在当前浏览器标签页里转义的:没有上传任何内容,也没有存储任何内容。

页面提供的是“范围”设置而不是一个按钮,因为百分号编码有三种不同的口径。查询值要转义 `&` 分隔符,整条 URL 要保留真正的 `&`,表单数据则把空格变成 `+`。页面会写明这次应用的是哪一种口径,因为大多数“我的 URL 为什么坏了”的问题,本质都是范围用错。

关于这个工具

把一个参数里含 `&` 的 URL 粘进来,或者粘一个带空格的搜索词,页面会显示百分号编码应该把它变成什么样。你可以编码纯文本或解码转义文本;自动模式会判断方向,并说明应用了三种口径中的哪一种。

三种口径正是重点:查询值会转义那个本会结束它的 `&`;整条 URL 会保留真正的 `&` 和 `/`;表单数据会把空格变成加号。页面会标明所用的范围,因为大多数关于“URL 坏了”的疑问,背后都是范围不匹配。所有处理都在客户端完成,所以带签名的链接不会被发送到任何地方。

双重编码是这个页面特意要让人看见的失败:对已经编码过的字符串再编码,`%20` 会变成 `%2520`,服务器随后会按字面读取。页面把输入和输出并排显示,而不是神秘地再做一遍。对任何调试回调 URL 的人来说,这份并排对照就是全部价值。

它是怎么工作的

三种口径与空格

在查询值内部,`encodeURIComponent` 风格的编码会转义 `&`、`=`、`/` 以及其他任何可能被误读的字符,空格变成 `%20`。对整条 URL 而言,只转义非转义不可的部分:分隔 URL 的 `&`、`/` 和 `:` 必须原样保留,否则链接就断了。表单数据里,空格变成 `+`,其余字符沿用组件规则。选择哪一种,取决于这段字符串最终落在 URL 的哪个位置。

解码则反过来,按你声明的来源口径还原。最值得注意的是加号:按组件数据解码时,`+` 仍然是 `+`;按表单数据解码时,`+` 才变成空格。页面在表单口径下的默认行为就是把加号还原成空格,因为表单编码当初正是这么写进去的。范围选错时,输出看起来“几乎对”,却会在某个参数上悄悄错位,这类问题通常比直接报错更难查。

只编码一次,以及双重编码是怎么发生的

百分号本身也是编码器认识的字符,所以对一条已经转义过的 URL 再编码,会把其中的 `%` 号再转义一次,`%20` 就变成了 `%2520`。这不是页面的缺陷,而是查询字符串里 `%26` 反复出现这一现象的同一套机制。页面把这一点说明白:编码一次,然后按字符串当初被编码的次数解码相应的次数。

实践中最常见的场景是回调地址:框架已经对参数做过一次编码,拼接时又整体编码了一次,服务端只解开一层,于是看到的是 `%252F` 之类的字面量。遇到这种链接,先把输入和输出并排看,确认到底叠加了几层,再决定解码几次;盲目多点几次解码,反而可能把本来正确的 `%` 也吃掉。

编码不是加密

这里没有任何东西在隐藏信息。百分号编码的存在是为了让 URL 能携带字符,解码后的形式只有一步之遥。页面把这一点讲明,是因为不少人会把编码过的字符串粘进来,期待它带来隐私保护——而一个用 `%` 转义的字符串,私密程度和 Base64 差不多,也就是说完全没有。

拿到字符串的人不需要密钥,任何解码器都能还原,这个页面也一样。因此,把令牌、密码或个人数据放进编码后的 URL,并不会让它们变得安全;真正需要保护的内容应该走 HTTPS、放在请求体或服务端会话里,而不是指望一层可逆的文本转换。页面负责转义与还原,不负责保密。

非 ASCII 文本会先变成 UTF-8 字节

非 ASCII 字符没有自己单独的一个百分号序列:页面先把它编码成 UTF-8 字节,再让每个字节变成一个 `%XX` 转义。`café` 会变成 `caf%C3%A9`,一个中日韩字符通常变成三个转义。这正是浏览器访问包含这些字节的 URL 时所做的处理。

也正因如此,同一个汉字在不同编码下会得到不同结果;如果服务端按 Latin-1 或 GBK 解读,就会出现乱码。这个页面统一按 UTF-8 处理,与浏览器的地址栏一致;域名那套把非 ASCII 变成 `xn--` 的 Punycode 是另一套方案,不属于百分号编码,这个页面不涉及。

编码在下游修不好什么

百分号编码只在 URL 内部是安全的,出了这个语境就不是。放进 HTML 属性时,分隔查询参数的 & 仍然要在标记里写成 &amp;;放进 JSON 正文时,% 号就是普通字符。编码回答的是「URL 解析器会不会把它当成结构」,不是「它在任何地方都安全」。

服务端也会解码,有些还解两次。拿到时 %20 已经变回空格,说明它在被你看到之前已经被解过一次;拿到的是 %2520,说明出去的路径上又被编码了一次。两者都是「口径与层」的问题,本页的范围设置存在的意义就是把这个问题露出来。

URL 的实际长度上限是页面无法强制的另一件事。浏览器能处理很长的 URL,但代理、邮件客户端与服务端配置常在 2,000 字符左右截断。编码后的内容接近这个量级时,链接里应该只带一个 id,数据放在链接背后。

示例

示例使用页面自带的默认输入,只改设置;下面的结果与你在页面上看到的完全一致。

带空格的搜索词

要做什么: 编码为百分号编码 · 百分号编码范围: 查询字符串里的单个值(转义 %26、%3D、%2F) · 输入: hello world · 下载文件名: —

已为 URL 编码

2 个额外字符

按查询字符串里的一个值编码。2 个字符是为了转义那些否则会被 URL 解析器当作结构的字符而增加的。

输入: 11 个字符 · 输出: 13 个字符

组件编码把空格变成 `%20`:`hello%20world`,正是查询值期望的形式。

同样的文本作为表单数据

要做什么: 编码为百分号编码 · 百分号编码范围: 表单数据,空格变成 + · 输入: hello world · 下载文件名: —

已为 URL 编码

没有需要转义的字符

按表单数据编码。每个字符本来就已经是 URL 安全的,所以输出与输入相同 —— 这个性质值得验证,而不该假定。

输入: 11 个字符 · 输出: 11 个字符

表单编码把空格变成 `+`:`hello+world`,这是表单提交实际发送的口径。

解码一整条 URL

要做什么: 把百分号编码解码为纯文本 · 百分号编码范围: 整条 URL(保留 &、/ 和 :) · 输入: https://danfio.app/tools?q=hello%20world · 下载文件名: —

已解码为纯文本

纯文本

按整条 URL解码。

输入: 40 个字符 · 输出: 38 个字符(38 字节)

整条 URL 解码会保留 URL 自身的 `&` 和斜杠,只把查询值里的 `%20` 还原成空格。

非 ASCII 文本,按字节编码

要做什么: 编码为百分号编码 · 百分号编码范围: 查询字符串里的单个值(转义 %26、%3D、%2F) · 输入: café · 下载文件名: —

已为 URL 编码

5 个额外字符

按查询字符串里的一个值编码。5 个字符是为了转义那些否则会被 URL 解析器当作结构的字符而增加的。

输入: 4 个字符 · 输出: 9 个字符

重音 e 不是一个字节,所以会变成两个转义 `C3 A9`:`caf%C3%A9` 就是该词的 UTF-8 字节经过百分号编码的结果,和浏览器地址栏里放的完全一致。

常见问题

%20 和 URL 里的 + 有什么区别?

`%20` 是 URL 和查询值里使用的百分号编码空格;`+` 是表单编码数据里的空格。它们是同一件事的两种口径,所以“加号变成了空格”或“`%20` 解开后还是 `%20`”,都是经典的范围不匹配症状。

为什么解码后的 URL 里还留着 %20?

几乎总是因为它被编码了两次:第一遍把空格变成 `%20`,第二遍把 `%` 变成 `%25`,于是留下 `%2520`。再解码一次,它就会恢复干净。

百分号编码能隐藏我的数据吗?

不能。编码是为了让结构能穿过 URL,而不是提供保护:任何解码器,包括这个页面,都能一步还原,不需要密钥。放在编码后 URL 里的令牌或密码,暴露程度和放在 Base64 里差不多——也就是说,可读——因此不应被当作私密内容。

非 ASCII 字符在编码后的 URL 里是怎么处理的?

非 ASCII 字符会按其 UTF-8 字节做百分号转义:`café` 里的重音 e 变成 `%C3%A9`,而不是单个转义。这与浏览器产生的形式一致,所以把浏览器转义过的 URL 粘到这里,能还原出同样的文本。Punycode——非 ASCII 域名使用的 `xn--` 形式——是另一套方案,不属于百分号编码。

把 URL 放进链接之前需要预先编码吗?

不需要:完整链接用整条 URL 范围编码一次,单个值用组件范围编码一次即可。对已经转义过的 URL 再编码,会把百分号本身也转义掉,也就是 `%26` 反复出现的那种情况,这几乎总是“链接看起来被编码了两遍”背后的缺陷。让页面按目标语境期望的方式,精确编码一次。

资料来源与统计口径

  • 百分号编码遵循 RFC 3986:使用 `%XX` 转义,各范围会保留本身带结构含义的保留字符。
  • 页面提供三种范围,对应 URL 的三种用途:查询字符串里的值、整条网址,以及空格写成 `+` 的表单数据。
  • 编码在你的浏览器里完成,不会上传任何内容。

最近复核于 2026-09-26.

本页在您的浏览器本地运行,请保留原文件备份;不涉及财务建议。 阅读完整免责声明。