URL 编解码

URL 组件或完整 URI 编解码

正在加载工具…

关于 URL 编码解码工具

URL 编解码工具提供两种范围的百分号编码:「URL 组件」用于查询参数、路径段这类单个值,「完整 URI」用于分隔符必须保留的整条地址。输入框会实时校验百分号序列,格式不对的值在你点击转换之前就会被标出来。

百分号编码把一个字节写成百分号加两位十六进制,真正要回答的问题只有一个:哪些字符算数据,哪些字符算结构。在完整 URI 里,斜杠、问号、& 和 # 属于结构,必须保持原样;而在单个值内部,同样这些字符属于数据,必须转义,否则它们会悄悄改变整条 URL 的形状。非 ASCII 字符会先按 UTF-8 编码,再逐字节做百分号转义——这就是为什么一个汉字会变成九个字符的转义序列。

如何使用这个开发者工具

  1. 先选择「编码」或「解码」。
  2. 再选择范围:单个值选「URL 组件」,处理整条地址时选「完整 URI」。
  3. 粘贴内容并留意状态提示;解码模式下它会立即告诉你百分号序列是否合法。
  4. 转换后重点检查结果里的保留字符,尤其是 &、=、?、/ 和 #。
  5. 最终的 URL 应该由「字面分隔符 + 组件编码后的值」拼出来,而不是对拼好的整串再编码一次。

实例:一个回跳参数

一条回调 URL 需要塞进另一条 URL 的查询串里。两种范围中只有一种能产出可用的链接。

待嵌入的值
https://example.com/cb?state=a b&next=/home
两种范围的输出
URL 组件  :https%3A%2F%2Fexample.com%2Fcb%3Fstate%3Da%20b%26next%3D%2Fhome
完整 URI :https://example.com/cb?state=a%20b&next=/home

只有组件形式能接在 redirect= 后面,拼出 https://sso.example.com/login?redirect=https%3A%2F%2Fexample.com%2Fcb%3Fstate%3Da%20b%26next%3D%2Fhome。完整 URI 形式保留了字面的 &,接收方服务器会把 next=/home 当成它自己登录地址上的参数,回调地址就这样丢了一半。

两种范围对各字符的处理

两种范围都会编码空格和所有非 ASCII 字节,区别只在于那些撑起 URL 结构的保留字符。

字符URL 组件完整 URI为什么要紧
空格%20%20URL 中不允许出现未编码的空格
&%26&分隔查询参数
=%3D=分隔参数名与参数值
?%3F?开启查询串
/%2F/分隔路径段
#%23#开启片段标识,而片段永远不会发给服务器
+%2B+表单解码器会把它读成空格
: 与 @%3A 与 %40: 与 @协议与 userinfo 的分隔符
%%25%25必须转义,否则解码失败
中%E4%B8%AD%E4%B8%AD按 UTF-8 编码,每个汉字三字节
- . _ ~ ! * ' ( )保持原样保持原样非保留字符与子分隔符,两种范围都不动

常见问题排查

参数传到服务端时,从第一个 & 起就被截断了。

成因 这个值是按「完整 URI」范围编码的,或者根本没编码,于是它自带的 & 被接收方当成了分隔符。

解决办法 每个值都按「URL 组件」范围编码,再自己拼接。写代码时交给 URLSearchParams 之类的接口来构造查询串,从根上避免这个问题。

空格变成了加号,或者加号变成了空格。

成因 这里同时有两套编码在起作用。百分号编码把空格写成 %20,而 application/x-www-form-urlencoded 把它写成 +。本工具解码时绝不会把 + 转成空格,因为在路径或片段里加号就是字面字符。

解决办法 处理表单编码的数据时,先把 + 换成 %20 再解码,或者直接用遵循表单规则的 URLSearchParams 解析。

解码时提示编码格式无效。

成因 某个百分号后面不是两位十六进制数字,或者多字节 UTF-8 序列不完整。常见于日志在转义序列中间截断,或者粘进了 Windows 路径、带百分号的数字。

解决办法 看字符串里最后一个百分号:如果它后面不足两位数字,说明值被截断了。文本中本来就含百分号时,请先把它转义成 %25 再编码。

值里出现了你从没写过的 %2520 或 %25 序列。

成因 它被编码了两次,通常是应用编了一次,网关或客户端库以为拿到的是原始值又编了一次。

解决办法 先解一次看看:结果里如果还有合法转义,就说明是双重编码。去修那个「对已编码的值再编一次」的环节,而不是在下游反复补偿。

带非 ASCII 字符的路径在浏览器里正常,到服务端就不行了。

成因 地址栏显示的是解码后的形态,实际发出的是百分号编码的 UTF-8。服务端若按别的字符集解码,这些字节就会变成乱码。

解决办法 把服务端日志里的原始请求行与这里编码出来的结果比对,并把服务端的 URL 解码字符集配置成 UTF-8——所有浏览器发的都是它。

适合用这个工具的场景

  • 构造需要承载一整条 URL 的回跳、回调或 state 参数。
  • 读懂日志行或报错信息里那串百分号编码的 URL。
  • 解释签名不一致的问题:签名方和发送方对同一个值采用了不同的编码方式。
  • 修好从聊天窗口复制出来、夹着空格或换行的链接。

应该换用别的工具的场景

  • 构造要求空格变加号的表单请求体,请用 URLSearchParams 或 HTTP 客户端自带的表单编码器。
  • 为网页文本做转义。标记需要的是实体转义,请用 HTML 实体编解码工具。
  • 判断 URL 是否可达或安全。本工具从不发起连接,可达性请交给网站检查工具。

隐私与数据处理

编解码使用浏览器自带的 URI 函数,在当前标签页内完成。工具从不访问这个地址,所以它无法告诉你链接是否可达、是否会跳转、是否安全;你粘贴的内容也不会被传输或保存。从浏览器复制的 URL 经常在查询串里带着会话标识和一次性令牌,分享之前请先抹掉。

相关开发者工具

常见问题

什么时候用组件范围,什么时候用完整 URI?

只要是单个值就用组件范围:查询参数、路径段、片段标识都算。只有当你手里已经是一条结构正确的完整地址、只想把其中的空格和非 ASCII 字符转义掉时,才用完整 URI。

为什么加号没有被解码成空格?

因为那条规则属于表单编码,不属于 URI。在路径、片段和一般查询值里,加号就是字面的加号,强行转换会破坏 Base64 载荷、电话号码之类的数据。

哪些字符永远不会被编码?

非保留字符集合,也就是字母、数字、连字符、句点、下划线和波浪号,再加上浏览器编码器不动的子分隔符 ! * ' ( )。其余字符要么两种范围都编码,要么只在组件范围编码。

汉字和 emoji 是怎么编码的?

先转成 UTF-8 字节,每个字节再写成一个百分号转义,所以一个汉字产出九个字符、一个 emoji 十二个。正因为膨胀得快,长的非 ASCII URL 很容易撞上长度上限。

百分号编码算一种安全措施吗?

不算。它保护的是结构,不做任何净化。解码后的 URL 依然可能指向恶意站点,而一个编码得当的值,在你的应用解释它之后同样可能有害。

放进链接之前要把整条 URL 编码一遍吗?

不要。对成品 URL 编码会把它自己的分隔符一并转义,直接破坏这条链接。正确做法是只编码各个值,再用字面分隔符把它们拼起来。