📝 博客 · 2026-07-29 · ⏱ 9 分钟

URL编码是什么?%20和+是什么意思?

讲清楚 URL 编码的原理,%20 和 + 的区别,以及 encodeURI 和 encodeURIComponent 的不同。

一、URL 为什么需要编码

URL(统一资源定位符)的设计初衷是用于"指代互联网上的资源",它最早只支持 ASCII 字符集里的一部分可打印字符。具体来说,URL 里只能安全地出现:

但现实世界里我们要传的数据远远不止这些。中文、空格、emoji、特殊符号(&=?#)——这些都不能直接放进 URL 里。原因有两点:

  1. ASCII 范围之外的字符(比如中文)无法用单字节表示
  2. 某些字符在 URL 里有特殊含义,比如 ? 表示查询参数开始,& 表示参数分隔,如果数据里直接出现这些字符,解析器会搞混。

所以 URL 编码(也叫百分号编码,Percent-Encoding)出现了:把不安全的字符用一个 % 加两位十六进制数表示

二、百分号编码的原理

规则很简单:

举几个例子:

原始字符UTF-8 字节URL 编码
空格0x20%20
0xE4 0xB8 0xAD%E4%B8%AD
0xE6 0x96 0x87%E6%96%87
&0x26%26
=0x3D%3D
+0x2B%2B

所以 URL https://example.com/搜索?q=hello world 编码后可能变成:

https://example.com/%E6%90%9C%E7%B4%A2?q=hello%20world

可以看到,一个中文字符在 URL 里会变成 9 个字符(3 个字节,每个 %XX 3 个字符),这就是为什么带中文的链接看起来特别长。

三、%20 和 + 的区别

这是最容易让人困惑的一个点:空格在 URL 里既可以编码成 %20,也可以编码成 +,两者有什么区别?

答案在于上下文不同

编码方式出现的位置标准
%20URL 的任何部分(路径、查询、片段)RFC 3986(通用 URL 标准)
+仅查询字符串里HTML 表单提交规范

具体来说,当你用

提交表单时,浏览器会按 application/x-www-form-urlencoded 格式编码数据,这个格式规定空格编码成 +。这个规范比 RFC 3986 早,所以保留了下来。

举个例子:

原始数据在查询字符串里在路径里
hello worldhello+worldhello%20world
a=b ca=b+ca%3Db%20c

实际开发中要注意:

  • 后端解析查询字符串时,通常会把 + 自动还原成空格(比如 PHP 的 $_GET、Node.js 的 querystring.parse
  • 但解析路径时+ 不会被还原成空格,要手动处理

为了避免歧义,建议统一用 %20,它在任何位置都表示空格,不会出错。

四、encodeURI vs encodeURIComponent

JavaScript 提供了两个编码函数,很多人分不清它们的区别。

encodeURI

用于编码完整的 URL,它不会编码 URL 里本身就有的特殊字符:

encodeURI("https://example.com/search?q=hello world&lang=zh")
// 结果:https://example.com/search?q=hello%20world&lang=zh

可以看到 :/?=& 这些保留字符都没被编码,只有空格被编码了。这是因为这些保留字符是 URL 结构的一部分,编码后 URL 就坏了。

encodeURIComponent

用于编码 URL 里的单个参数值,它会编码所有非字母数字字符(除了 - _ . ! ~ * ' ( )):

encodeURIComponent("hello world&foo=bar")
// 结果:hello%20world%26foo%3Dbar

这里 &= 都被编码了。如果你用 encodeURI 编码这个字符串,&= 不会被编码,传到服务器就会被错误地解析成两个参数。

对比表

字符encodeURI 是否编码encodeURIComponent 是否编码
空格
/
?
&
=
#
:

口诀

  • 编码整个 URL → 用 encodeURI
  • 编码某个参数值 → 用 encodeURIComponent

五、常见 URL 编码表

字符编码字符编码
空格%20#%23
!%21$%24
&%26'%27
(%28)%29
*%2A+%2B
,%2C/%2F
:%3A;%3B
=%3D?%3F
@%40[%5B
]%5D%E4%B8%AD

六、实战例子

假设你要构造一个搜索 URL,参数 keyword 的值是 Python & Java 教程

错误做法(直接拼接):

https://example.com/search?q=Python & Java 教程

服务器会以为 q=Python 是一个参数,后面的 Java 教程 是另一个参数,解析直接乱掉。

正确做法(用 encodeURIComponent):

const keyword = "Python & Java 教程";
const url = "https://example.com/search?q=" + encodeURIComponent(keyword);
// 结果:https://example.com/search?q=Python%20%26%20Java%20%E6%95%99%E7%A8%8B

这样服务器才能正确还原出 Python & Java 教程

七、容易踩的坑

  1. 编码两次:有些框架会自动编码一次,如果你又手动编码一次,就会出现 %2520 这种双重编码。解码时也要相应地解码两次。
  2. 大小写%20%20 等价,但有些系统对大小写敏感,建议统一用大写。
  3. 保留字符的歧义/ 在路径里是分隔符,在参数值里是普通字符。如果参数值里包含 /,要用 encodeURIComponent 编码成 %2F
  4. URL 里出现中文:虽然现代浏览器地址栏里能看到中文,但实际传输时已经被编码了。复制链接时编码可能会丢失,导致分享出去的链接打不开。

八、实践推荐

日常开发中 URL 编码解码的场景非常多——构造 API 请求、解析 query 参数、处理前端路由等等。手写 JS 代码调试太麻烦,直接用在线工具最方便:

支持 encodeURIencodeURIComponent、UTF-8/GBK 等多种编码切换,实时预览结果,还能一键解码乱码 URL,是前后端联调时的必备工具。