URL 的「编码」和「解码」是什么意思?
URL 编码 (「url encode」「urlencode」)把地址中每个不允许的字符——空格、重音字符、&、加号——转换成一个序列:百分号加上该字节的两位十六进制数字。 URL 解码 (「url decode」「decoder url」)反向读取这些序列:先还原字节,再按声明的编码(通常是 UTF-8)转换成字符。当人们搜索「encoder decoder url」或「percent encoding online」时,找的正是这样一对功能。
percent-encoding 既不是压缩也不是加密:带重音的词会变成两倍长,而且任何人都能一眼读懂。它唯一的作用是让任意字节都能进入 URL,而 URL 默认只接受 ASCII 的一个子集。反过来,Base64 用于在纯文本通道中传输字节——两者看起来相似,却不能互相替代。
如何用 percent-encoding 编码 URL
第 1 步:按所选字符集把文本转换成字节,默认是 UTF-8。第 2 步:逐个字节检查对应字符是否属于所选范围允许的字符列表。第 3 步:如果属于,就原样保留;否则变成 %XX,其中 XX 是该字节的两位十六进制数字。第 4 步:如果「空格转为 + 」选项已启用,字节 32 就会被替换成加号,而不是 %20.
具体示例:「 café & été 」在组件范围下的结果是 caf%C3%A9%20%26%20%C3%A9t%C3%A9。在编码器里输入这段文本:结果、输入大小、输出大小和开销在松开按键之前就已经出现了。
四种编码范围
这个 组件范围 只保留字母、数字和 - _ . ! ~ * ' ( ) :它对应单个参数值,等同于 encodeURIComponent。而 查询字符串 还额外保留 & 和 =,用来重建完整的 query string。而 路径片段 允许加入 / : @ & = + $ , ; ,以免破坏斜杠。而完整 URL 还会额外加入 ?, #, [ 和 ] :几乎什么都不转义,只有空格和非 ASCII 字符会变成 %XX.
如何解码已编码的 URL
解码从左到右扫描字符串:百分号加两位十六进制数字得到一个字节,其他字符按所选编码转换后原样保留。随后字节被分组转换成字符——「é」2 个字节,「日」3 个字节,一个 emoji 4 个字节。「解码」标签页会列出每条检测到的序列、它在字符串中的位置、对应的字节以及还原出的文本。
如果百分号后面没有两位有效数字,错误会明确给出原因:序列不完整或十六进制字符无效。「修正 %」按钮会把孤立的百分号变成 %25,这样字符串就能被解码且不丢失任何信息——处理部分转义的 URL 时,这是最稳妥的做法。
空格:%20 还是 + —— 表单的规则
%20 是严格的 percent-encoding 空格:路径、查询、片段和请求头中都能用。而符号 +,则只在格式 application/x-www-form-urlencoded ,即 HTML 表单以及历来 query string 使用的格式。在其他地方它仍是字面的加号——由于极易混淆,只要对值进行编码,就必须把它转义成 %2B ,只要对值进行编码。
实际用法:要填充表单字段,或复现某个 <form>,请勾选「空格转为 + 」。对于重定向 URL、canonical 或分享链接,请始终选择 %20。解码器则把 + 默认视为空格,你也可以一键关闭这个行为。
RFC 3986:unreserved、sub-delims 与 gen-delims
RFC 3986 把 ASCII 字符分成三类。 非保留字符 ——字母、数字、 - _ . ~ ——始终原样保留。而 次级分隔符 ! $ & ' ( ) * + , ; = 以及 通用分隔符 : / ? # [ ] @ 具有结构含义:它们分隔权威、路径、查询和片段。其余一切——空格、引号、尖括号、花括号、百分号——都必须编码。
这些类别正是「RFC 3986 & 参考」标签页逐字符列出的内容:点击任意方块,即可查看它的十六进制编码、所属类别,以及保留它的编码范围。要回答「这个字符需要转义吗?」,这是最快的参考。
重音字符、emoji 与 UTF-8
URL 只传输安全的 ASCII 字节,因此任何超过 U+007F 的字符都必须编码。在 UTF-8 中,「é」的值是 C3 A9 ,会变成 %C3%A9,「日」占 3 个字节,会产生 3 条序列;一个 emoji 占 4 个字节,编码后是 8 个字符。如果结果看起来很长,那不是 bug:这就是兼容所有协议的代价。最后还要留意原始字符集——把 Latin-1 编码的字符串按 UTF-8 解码会得到乱码,这正是「解码」标签页提供四种选项的原因。
为什么 encodeURIComponent 并不总是够用
encodeURIComponent 会编码除 A-Z a-z 0-9 - _ . ! ~ * ' ( )之外的一切,用在参数值上没问题,但会破坏完整 URL,因为它连斜杠、冒号和 & 也一并转义了。 encodeURI 则相反:它保留 URL 结构,却放行空格和重音字符,因此处理纯文本时会失败。这里两种用法都覆盖了——而且不止于此,因为「查询字符串」和「路径片段」两种范围正好弥补了两者之间的差距。
percent-encoding 与 Base64:两种不同的工具
percent-encoding 逐字节替换,保留原文的可读性,代价是长度大幅增加。Base64 每三个字节一组,重写成 64 个字符的字母表:紧凑却完全不可读,没有 URL-safe 变体就不能直接用在 URL 里。「交叉转换」标签页把两者放在同一屏对照,还额外给出十六进制字节、HTML 实体和转义后的 JSON 字符串——复制之前就能选对表示形式。
常见错误:双重编码与孤立的 %
最常见的错误是把同一个字符串转义两次:空格先变成 %20,再变成 %2520,于是服务器收到的字面内容是「%20」。第二个错误是漏掉了百分号本身,它应该变成 %25 ——否则解码器会把它当作序列的开头,导致崩溃或截断。最后,保留一个 + 而不转义地放进表单参数,就等于插入了一个你并没有要求的空格。解码器会标出格式错误的序列,「修正 %」按钮可以无损修复第二种情况。
编码后的 URL 藏在哪里
在 UTM 跟踪 query string 中,在 redirect_uri 和 OAuth 状态中,在 跟踪 query string 中,在 webhooks 中(其目标 URL 带有嵌套参数),在 回调 URL 中,在服务器日志中,在 sitemap 和 canonical 中,在 <a href> 中(客户端生成的),在 JWT 中(payload 使用 Base64URL),在 data: 以及 Location 请求头中,以及任何以 GET 提交的 HTML 表单里。花一秒钟就能完成编码和解码,省得为一个字符串专门打开终端。
性能与最佳实践
在浏览器中,编码和解码都是线性的,即使处理几兆字节也没有明显开销:每个字符只处理一次,既不递归也不逐字符分配内存。唯一的陷阱是双重编码——存储之前务必先做一次往返测试——以及几 KB 的 URL,代理通常会截断超过 2 000 个字符的 URL。请把所用范围标注在生成的字符串旁边:同一段文本,「组件」和「完整 URL」得到的结果并不相同。
推荐人群
前后端开发者(query string、重定向、OAuth)、集成与技术写作者(UTM 链接、canonical、跟踪)、管理员与 DevOps(webhook、签名 URL、日志)、测试与渗透测试人员(参数模糊测试、绕过过滤器)、学生(理解 UTF-8、ASCII 与 RFC 3986),以及任何需要 在线 URL 编码解码器 的人:快速、完整、私密——再搭配Base64 编码解码器 和 JSON 格式化器.