URL 编码 / 解码

在线对 URL 和查询字符串进行百分号编码与解码。支持组件、完整 URI、表单三种模式,输入即时双向转换。

把文本转成 URL 可用的百分号编码,或还原回来。 在任意一侧输入,另一侧会立即更新。请按照值的实际用途选择模式:单个查询参数、完整 URL,还是 HTML 表单提交。

把百分号编码讲清楚

URL 为什么需要编码

URL 不是自由文本。?#&/= 这些字符是保留字符,它们承担结构含义:标明路径在哪里结束、查询从哪里开始、参数之间如何分隔。如果你要传输的值本身含有这些字符,接收端的解析器就会误读整条 URL。百分号编码的做法是把这个字节替换成 % 加上两位十六进制值,于是值里的 &%26 的形式传输,绝不会被当成分隔符。

未保留、保留,以及其他

RFC 3986 把字符空间分成三类。

  • 未保留字符A-Z a-z 0-9 - . _ ~。这些永远不需要编码,也不该编码。强行编码虽然合法,但会让 URL 更难看,还可能破坏简单的字符串比较。
  • 保留字符: / ? # [ ] @ ! $ & ' ( ) * + , ; =。只有在充当结构分隔符时才可以保持原样,出现在值里面就必须编码。
  • 其余字符 — 空格、控制字符,以及所有非 ASCII 文本,一律需要编码。

非 ASCII 与 UTF-8

百分号编码作用于字节而非字符,所以要先把文本转成字节。现代答案永远是 UTF-8。 在 UTF-8 里是三个字节(E2 82 AC),因此编码结果是 %E2%82%AC。早期系统有时按页面自身的字符集编码,这就是你偶尔还会遇到 Latin-1 或 GBK 编码乱码 URL 的原因。本工具全程使用 UTF-8,与浏览器和当前所有服务端框架的预期一致。

三种模式,以及各自的误用场景

encodeURIComponent 是安全默认值,会转义全部保留字符。只要是把一个值塞进 URL,就用它。encodeURI 刻意保留了保留字符以维持完整 URL 的结构 —— 只应该用来整理已经拼好的整条 URL,绝不要用在单个参数上,因为它会原样留下值里的 &,直接毁掉查询字符串。

表单模式是个异类。application/x-www-form-urlencoded 这套序列化方式早于现代 URL 规范,它把空格编码成 + 而不是 %20。两种写法在查询字符串里都正确,服务器也都能接受,但如果你在手工构造 POST 请求体,就应当遵循表单约定。

+ 的歧义

正因为表单编码赋予了 + 特殊含义,表单值里的字面加号必须自己编码成 %2B。这是现实中最常见的编码 bug:一段 base64 字符串或一个国际格式电话号码被原样传递,接收端把每个 + 都变成了空格。如果你的数据可能含加号,要么显式编码,要么别用表单模式。

双重编码

对已经编码过的字符串再编码一次,每个 % 都会变成 %25,于是 %20 变成 %2520。这通常是 bug —— 往往是应用代码编码了一次,框架或代理又编码了一次。如果你在 URL 里看到并非本意的 %25,那多半就是双重编码。解码两次可以还原,但真正的修复是去掉其中一层编码。

开源说明:使用标准 JavaScript 的 encodeURIComponentencodeURIdecodeURIComponentdecodeURI 实现,未使用第三方库。

常见问题

空格该用 %20 还是 +?
查询字符串里两者都可以。如果你想要一种到处都合法的写法,用 %20,因为在路径片段里 + 表示字面加号。只有在生成 application/x-www-form-urlencoded 数据时才用 +。
为什么我的加号变成了空格?
链路上有环节把这个值当作表单数据解析了,而表单编码里 + 就代表空格。发送前把字面加号编码成 %2B 即可。
斜杠需要编码吗?
只有当斜杠是值的一部分、而不是路径分隔符时才需要。含斜杠的文件名必须写成 %2F,否则服务器会把它当成多了一层目录。注意有些服务器出于目录穿越防护,默认会拒绝路径中的 %2F。
编码区分大小写吗?
十六进制位大小写都可以,解码结果完全一致,但 RFC 3986 建议优先使用大写。%2F 和 %2f 是同一个字符,%2F 是规范写法。
为什么我的字符串解码失败?
百分号后面必须恰好跟两位十六进制数字。单独一个 % 或者 %zz 这样的写法是非法的,解码器会抛错。如果你的文本里确实有百分号,它本应被编码成 %25。
数据会被上传吗?
不会。编码和解码都在你的浏览器里用内置 URI 函数完成,不上传任何内容。