如何解码 URL
- 把编码后的文本粘贴到 已编码的 URL 或文本。
- 处理查询字符串和表单数据时保持 将 + 视为空格 开启;处理路径或 Base64 值时关闭它。
- 如果结果中仍有
%XX序列,状态栏会提示:勾选 多次解码。 - 对于日志文件或一列值,勾选 逐行处理,让每一行单独解码。
- 如果源数据不是 UTF-8,选择对应的 字符集,然后点击 复制输出。
当输入是完整的 URL 时,输入输出框下方的表格会显示协议、主机、解码后的路径、每个查询参数(各占一行)以及片段。这是阅读冗长的跟踪链接或跳转链接最快的办法。
示例
| 编码后 | 解码后 | 说明 |
|---|---|---|
q=base64%20%26%20%22url-safe%22 | q=base64 & "url-safe" | %26 是 &,%22 是 " |
lang=%E6%97%A5%E6%9C%AC%E8%AA%9E | lang=日本語 | UTF-8 中每个字符 3 个字节 |
%F0%9F%98%80 | 😀 | emoji 占 4 个字节 |
q=a+b%2Bc | q=a b+c | 开启 将 + 视为空格 时 |
next=%252Fhome%253Ftab%253D1 | next=/home?tab=1 | 双重编码,两轮 |
caf%E9 | café | Windows-1252 或 ISO-8859-1,不是 UTF-8 |
双重编码
已经编码的字符串每被再编码一次,每个 % 就会变成 %25。于是 / 先变成 %2F,再变成 %252F,然后是 %25252F。当跳转 URL 经过多个服务传递,或者框架对代码已经编码过的值又编码一次时,就会出现这种情况。
要读取这样的字符串,就一直解码到没有转义为止;多次解码 正是这样做的,并会报告轮数。要从根源上解决,需要找到多编码了一次的那一层。合理的嵌套 URL,比如包含另一个 URL 的 next= 或 url= 参数,只需要恰好多一层编码,不能更多。
邮件安全网关是这种嵌套的常见来源。Microsoft Defender 安全链接(Safe Links)的 URL 形如 https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fexample.com%2Freset%3Fid%3D42&data=…;把它粘贴进来,参数表格就会显示真正的目标地址 https://example.com/reset?id=42,不需要你点击任何链接。
格式错误的转义和传统字符集
% 后面必须正好跟两位十六进制数字。100%、%zz 或在转义中途被截断的 URL 都是错误,解码器会报告 位置 N 处的转义序列有误。在同样的情况下,JavaScript 的 decodeURIComponent 会抛出 URIError: URI malformed,而 Python 的 unquote 会保留该序列原样不动。
另一个错误来源是字符集。百分号转义表示的是字节,而单独的 %E9 不是有效的 UTF-8。Python 会把它解码成替换字符,JavaScript 会抛出异常。把 字符集 设为 Windows-1252 或 ISO-8859-1,它就会解码为 é。Shift_JIS、GBK、EUC-KR、KOI8-R 等传统字符集也在同一个列表中。
在代码中进行 URL 解码
decodeURIComponent("a%20b%26c") // "a b&c"
new URLSearchParams("q=a+b%2Bc").get("q") // "a b+c"
from urllib.parse import unquote, unquote_plus, parse_qs
unquote("caf%C3%A9") # 'café'
unquote("caf%E9", encoding="latin-1") # 'café'
unquote_plus("q=a+b%2Bc") # 'q=a b+c'
parse_qs("q=a+b%2Bc&tag=x&tag=y") # {'q': ['a b+c'], 'tag': ['x', 'y']}
decodeURIComponent 不会把 + 变成空格;URLSearchParams 和 unquote_plus 会。请根据字符串的生成方式选择对应的函数。编码请看 URL 编码器;对于通过 URL 传来的 Base64,请看 Base64URL 解码器。
常见问题
如何解码 URL 编码的字符串?
粘贴到上面,解码后的文本会随输入实时显示。在 JavaScript 中用 decodeURIComponent(s),在 Python 中用 urllib.parse.unquote(s);如果 + 代表空格,则用 unquote_plus(s)。
为什么解码后的 URL 里还有 %20 或 %3A?
它被编码了两次。解码一轮会把 %2520 变成 %20,再解一轮才得到空格。勾选 多次解码,解码器会一直解到没有转义为止,最多五轮,并告诉你用了几轮。
为什么 decodeURIComponent 报 URI malformed 错误?
要么某个 % 后面没有跟两位十六进制数字(比如 100%),要么字节不是有效的 UTF-8(比如来自 Windows-1252 系统的 %E9)。这个解码器会指出确切位置,字符集 选项可以解码传统编码。
+ 应该解码成空格吗?
在查询字符串和表单正文中应该,所以 将 + 视为空格 默认是开启的。在 URL 路径以及可能包含 Base64 的值中,请取消勾选,因为那里的 + 就是加号本身。