百分号编码(Percent-Encoding)是什么?

把「为什么网址里要有 %20、%E4%BD%A0 这种东西」讲清楚的一页。这一页是概念讲解,不是工具。

这一页只讲概念,不含编解码工具。想实际编码/解码一段文字,请用 URL Encoder 工具页;想知道 JavaScript 里怎么调,请看 JavaScript 编码页。

百分号编码就是把一个「不能直接放进网址」的字节,写成 % 加上两位十六进制 的形式。 比如空格写成 %20,中文「你」写成 %E4%BD%A0。 它也常被称为 URL 编码(URL Encoding),正式名字在 RFC 3986 里叫 Percent-Encoding。

① 为什么需要有这个东西?

网址(URI)最初是为英文、纯 ASCII 设计的,而且里面有一批字符被赋予了结构含义。这带来三个问题:

  1. 字符集太小:URL 只能安全携带有限的 ASCII 字符。中文、emoji、带音调的字母都不在里面,必须换个写法。
  2. 有些字符是「骨架」,不能当内容:: / ? # & = @ 这些字符用来分隔协议、路径、查询串、锚点。如果内容里正好有一个 ?,不编码的话浏览器会把它当成「查询串开始」,网址结构就散了。
  3. 有些字符根本不允许出现:空格、< > " { }、控制字符等,在 URL 里是非法的。

百分号编码就是这三个问题的统一解法:凡是「不安全」或「想当内容用」的字符,一律写成 %XX。

② 编码规则:其实是「三步」

很多人以为「每个字符对应一个 %XX」,其实中间多了一层 UTF-8 字节。

第 1 步 · 拿到一个字符(比如「你」)。
第 2 步 · 先按 UTF-8 把它编成字节序列。「你」在 UTF-8 里是 3 个字节:E4 BD A0。
第 3 步 · 每个字节写成 % + 两位十六进制:E4→%E4,BD→%BD,A0→%A0,拼起来就是 %E4%BD%A0。
字符UTF-8 字节(十六进制)百分号编码结果
你E4 BD A0(3 字节)%E4%BD%A0
好E5 A5 BD(3 字节)%E5%A5%BD
空格20(1 字节)%20
A41(1 字节)A(不用编码)
&26(1 字节)%26

关键认知:百分号编码编的是「字节」,不是「字符」。所以一个中文通常变成 3 个 %XX,而英文字母保持原样。

③ 字符被分成三类

RFC 3986 把 ASCII 字符分成三类,决定了「能不能原样放进 URL」。

类别包含哪些要不要编码说明
未保留字符
unreserved
A-Z a-z 0-9 - _ . ~ 永远不用编码 到哪儿都安全,可以原样出现。
保留字符
reserved
:/?#[]@ !$&'()*+,;= 看场合 它们有结构含义。当结构用时保留原样;当普通内容用时必须编码。
其它 / 不安全 空格、" < > \ ^ ` { } |、控制字符、所有非 ASCII(中文等) 必须编码 在 URL 里非法,一律 %XX。

最重要的一句话:同一个字符在不同位置,处理方式不一样。比如 ? 出现在「参数开始」时是骨架,保留;但如果某个参数值里真的要写一个问号,就必须写成 %3F,否则会被误认为是查询串的开始。

④ URL 各部分:哪些字符能原样保留

这是理解百分号编码最容易卡住的地方 —— 规则不是「全 URL 统一」,而是按段的。

部分例子可以原样保留的字符
协议 schemehttps:字母 数字 + - .
主机 hostexample.com字母 数字 - . ~ % 及部分 sub-delims
路径 path/搜索/结果未保留字符 + :@ 及 /(作分隔)+ sub-delims
查询 query?q=你好&page=2未保留字符 + /?&=(作结构)+ sub-delims
锚点 fragment#第3节同 query,另加 # 本身

所以正确做法是「分段编码」:一条 URL 要编码时,应当把协议、主机、路径的每一段、参数名、参数值分别编码,再用结构符号拼起来 —— 而不是把整条 URL 一次性丢进编码器(那样 :// ? & 会被编掉,网址就坏了)。

⑤ 完整走一遍:一个真实例子

把 https://example.com/搜索?q=你好 world 变成合法 URL。

原始:https://example.com/搜索?q=你好 world

# 按段拆开、分别编码,结构符号保留:
协议   https:                    → 不变
主机   example.com               → 不变
路径   /搜索                     → /%E6%90%9C%E7%B4%A2
参数名 q                         → 不变
参数值 你好 world                → %E4%BD%A0%E5%A5%BD%20world

结果:https://example.com/%E6%90%9C%E7%B4%A2?q=%E4%BD%A0%E5%A5%BD%20world

注意:: // ? = 都保持原样,只有「内容」部分的中文和空格被编码了。

⑥ 四个常见误解

⑦ 接着看什么

→ URL Encoder 工具页(实际编码/解码) → JavaScript 编码用法与代码示例

本页为概念讲解,不含任何请求与上传 · 静态页面,打开即可读。