**百分号编码**（英語：），又稱**URL编码**（）是特定上下文的统一资源定位符（URL）的编码机制，实际上也适用于统一资源标志符（URI）的编码。也用于为*application/x-www-form-urlencoded* MIME准备数据，因为它用于通过HTTP的请求操作（request）提交HTML表单数据。

URI的百分号编码
---------

### URI的字符类型

URI所允许的字符分作**保留**与**未保留**。**保留**字符是那些具有特殊含义的字符，例如：斜线字符用于URL（或URI）不同部分的分界符；**未保留**字符没有这些特殊含义。百分号编码把保留字符表示为特殊字符序列。上述情形随URI与URI的不同版本规格会有轻微的变化。

RFC 3986 section 2.2 *保留字符* （2005年1月）| `!` | `\*` | `'` | `(` | `)` | `;` | `:` | `@` | `&` | `=` | `+` | `$` | `,` | `/` | `?` | `#` | `[` | `]` |

RFC 3986 section 2.3 *未保留字符* （2005年1月）| `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` |
| `a` | `b` | `c` | `d` | `e` | `f` | `g` | `h` | `i` | `j` | `k` | `l` | `m` | `n` | `o` | `p` | `q` | `r` | `s` | `t` | `u` | `v` | `w` | `x` | `y` | `z` |
| `0` | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` | `-` | `\_` | `.` | `~` |  |

URI中的其它字符必须用百分号编码。

### 对保留字符的百分号编码

如果一个保留字符在特定上下文中具有特殊含义（称作"reserved purpose"） , 且URI中必须使用该字符用于其它目的，那么该字符必须百分号编码。百分号编码一个保留字符，首先需要把该字符的ASCII的值表示为两个16进制的数字，然后在其前面放置转义字符（"`%`"），置入URI中的相应位置。（对于非ASCII字符，需要转换为UTF-8字节序，然后每个字节按照上述方式表示。）

例如，"`/`"，如果用作URI的路径成份的分界符，则是具有特殊含义的保留字符。如果该字符需要出现在URI一个路径成分的**内部**，则三字符序列"`%2F`"或"`%2f`"就用于代替原本的"`/`"出现在该URI路径成分的内部.

保留字符的百分号编码| `!` | `#` | `$` | `&` | `'` | `(` | `)` | `\*` | `+` | `,` | `/` | `:` | `;` | `=` | `?` | `@` | `[` | `]` |
| `%21` | `%23` | `%24` | `%26` | `%27` | `%28` | `%29` | `%2A` | `%2B` | `%2C` | `%2F` | `%3A` | `%3B` | `%3D` | `%3F` | `%40` | `%5B` | `%5D` |

在特定上下文中没有特殊含义的保留字符也可以被百分号编码，在语义上与不百分号编码的该字符没有差别。

在URI的"查询"成分（?字符后的部分）中, 例如"`/`"仍然是保留字符但是没有特殊含义，除非一个特定的URI有其它规定。该`/`字符在没有特殊含义时不需要百分号编码。

如果保留字符具有特殊含义，那么该保留字符用百分号编码的URI与该保留字符仅用其自身表示的URI具有不同的语义。

### 对未保留字符的百分号编码

未保留字符不需要百分号编码。

两个URI的差别如果仅在于*未保留字符*是用百分号编码还是用字符自身表示，那么这两个URI具有等价的语义。但URI处理器实际上并不总是把二者视作等价[來源請求]。例如，URI的消费者不应该把"`%41`"与"`A`"，"`%7E`"与"`~`"视作不同，但是某些URI的消费者就是这么做了。为了最大的互操作性，URI的制造者不应该对*未保留字符*进行百分号编码。

### 对百分号字符的百分号编码

由于百分号字符（"%"）表示百分号编码字节流的存在，因此百分号字符应该被编码为3个字节的序列："%25"，用于URI内部。

### 对任意数据的百分号编码

大多数URI涉及表示任意数据，例如IP地址或文件系统路径作为URI的成分。

#### 二进数据

1994年发布的RFC 1738规定， URI中的二进制数据应该表示为8位元组的序列，然后对每个8位元组按照上述方式百分号编码. 例如，字节值0F（十六进制）应表示为"`%0F`"，字节值41（十六进制）应表示为"`A`"或"`%41`". 优先使用未保留字符来表示这些字节值，因为这使得URL更短。

#### 字符数据

二进数据的百分号编码过程已经被外推到字符数据，甚至到不适合或未被完全规范的地步。在WWW初创阶段，仅仅处理ASCII字符是否编码问题，还没有什么问题。但随后发展到对非ASCII字符如何在URI中编码，缺少标准规范的情况下导致了歧义性的解释URI的错误。

例如， 基于RFC 1738与RFC 2396的协议规定，字符数据先要根据某种字符编码转换为字节流，然后再表示为URI。如果URI不提供是何种字符编码的提示信息，那么这个URI难以可靠的解析。

### 当前标准

2005年1月发布的RFC 3986，建议所有新的URI必须对未保留字符不加以百分号编码；其它字符建议先转换为UTF-8字节序列, 然后对其字节值使用百分号编码。此前的URI不受此标准的影响。

### 非标准的实现

有一些不符合标准的把Unicode字符在URI中表示为：`%u*xxxx*`, 其中*xxxx*是用4个十六进制数字表示的Unicode的码位值。任何RFC都没有这样的字符表示方法，并且已经被W3C拒绝 （页面存档备份，存于）。第三版的ECMA-262仍然包含函数`escape(string)`使用这种语法，但也有函数`encodeURI(uri)`转换字符到UTF-8字节序列并用百分号编码每个字节。

application/x-www-form-urlencoded类型
-----------------------------------

当HTML表单中的数据被提交时，表单的域名与值被编码并通过HTTP的GET或者POST方法甚至更古远的email把请求发送给服务器。这里的编码方法采用了一个非常早期的通用的URI百分号编码方法，并且有很多小的修改如換行规范化以及把空格符的编码"`%20`"替换为"`+`" 。按这套方法编码的数据的MIME类型是`application/x-www-form-urlencoded`，当前仍用于（虽然非常过时了）HTML与XForms规范中。此外，CGI规范包括了web服务器如何解码这类数据、利用这类数据的内容。

如果发送的是HTTP GET请求，`application/x-www-form-urlencoded`数据包含在所请求URI的查询成分中。如果发送的是HTTP POST请求或通过email，数据被放置在消息体中，媒体类型的名字被包含在消息的Content-Type头内部。

参见
--

* Quoted-printable

参考文献
----

1. ↑  RFC 1738 §2.2; RFC 2396 §2.4; RFC 3986 §1.2.1, 2.1, 2.5
2. ↑  User-agent support for email based HTML form submission, using a 'mailto' URL as the form action, was proposed in RFC 1867 section 5.6, during the HTML 3.2 era. Various web browsers implemented it by invoking a separate email program or using their own rudimentary SMTP capabilities. Although sometimes unreliable, it was briefly popular as a simple way to transmit form data without involving a web server or CGI scripts.

外部链接
----

* RFC 3986 / STD 66 (plus errata （页面存档备份，存于）), the current generic URI syntax specification.
* RFC 2396 (obsolete, plus errata （页面存档备份，存于）) and RFC 2732 (plus errata （页面存档备份，存于）) together comprised the previous version of the generic URI syntax specification.
* RFC 1738 (mostly obsolete) and RFC 1808 (obsolete), which define URLs.
* RFC 1630 (obsolete), the first generic URI syntax specification.
* W3C Guidelines on Naming and Addressing: URIs, URLs, ... （页面存档备份，存于）
* W3C explanation of UTF-8 in URIs （页面存档备份，存于）
* W3C HTML form content types （页面存档备份，存于）
* 在線URL解碼工具[永久]
* 在線URL編碼器[永久]