DevToolBox免费
博客

URL 编码特殊字符:完整参考表与示例

6 分钟阅读作者 DevToolBox

URL 编码(也叫百分号编码)将特殊字符转换为可以在 URL 中安全传输的格式。每个开发者都会遇到 URL 编码问题——链接损坏、参数乱码、或因未编码字符导致的 API 错误。本完整 URL 编码参考指南为你提供所有特殊字符及其编码形式的权威对照表,以及各主流编程语言的实用示例。

使用我们的 URL 编码/解码工具即时编码或解码任何 URL →

什么是 URL 编码(百分号编码)?

URL 编码用 % 符号加上两个十六进制数字(代表字符的 ASCII/UTF-8 字节值)来替换不安全或保留字符。例如,空格变为 %20,& 符号变为 %26

这个机制在 RFC 3986(统一资源标识符:通用语法)中定义。URL 只能包含 US-ASCII 字符集中的有限字符集。任何超出此集合的字符——或任何在特殊含义之外使用的保留字符——都必须进行百分号编码。

通用格式为:%XX,其中 XX 是字节的十六进制值。对于多字节 UTF-8 字符(如中文或 emoji),每个字节分别编码。例如,汉字"中"(U+4E2D)编码为 %E4%B8%AD(UTF-8 中的三个字节)。

// URL encoding example
Original:  https://example.com/search?q=hello world&lang=en
Encoded:   https://example.com/search?q=hello%20world&lang=en

// The space in "hello world" becomes %20
// The & and = remain unencoded (they are structural)

完整 URL 编码参考表

以下是所有常见特殊字符及其百分号编码形式的完整对照表。收藏此页面以便快速查阅。

字符编码形式ASCII 码说明
(space)%2032空格(也可用 + 表示)
!%2133感叹号
"%2234双引号
#%2335井号 / 片段标识符
$%2436美元符号
%%2537百分号(编码的转义字符本身)
&%2638与号 / 参数分隔符
'%2739单引号
(%2840左圆括号
)%2941右圆括号
*%2A42星号
+%2B43加号(表单中表示空格)
,%2C44逗号
/%2F47正斜杠 / 路径分隔符
:%3A58冒号(协议分隔符)
;%3B59分号
<%3C60小于号
=%3D61等号(键值分隔符)
>%3E62大于号
?%3F63问号(查询字符串起始符)
@%4064@ 符号(邮箱 / 用户信息分隔)
[%5B91左方括号
\%5C92反斜杠
]%5D93右方括号
^%5E94脱字符
`%6096反引号
{%7B123左花括号
|%7C124竖线
}%7D125右花括号
~%7E126波浪号(RFC 3986 中为非保留字符)
\n%0A10换行符(LF)
\r%0D13回车符(CR)
\t%099制表符(Tab)

保留字符与非保留字符(RFC 3986)

RFC 3986 定义了两类字符,决定何时需要编码:

保留字符

这些字符在 URL 中有特殊含义。如果你想按字面意思使用它们(而非其特殊用途),必须进行百分号编码。

: / ? # [ ] @ ! $ & ' ( ) * + , ; =

// Reserved characters in RFC 3986
gen-delims  = : / ? # [ ] @
sub-delims  = ! $ & ' ( ) * + , ; =

// Example: & is reserved (parameter separator)
// To use & literally in a value, encode it:
?search=Tom%26Jerry    // searching for "Tom&Jerry"
?search=Tom&Jerry      // WRONG: "Jerry" becomes a separate param

非保留字符

这些字符可以在 URL 中直接使用而无需编码,它们没有特殊含义:

字母:A-Z、a-z   数字:0-9   特殊:- _ . ~

// Unreserved characters (RFC 3986) — never need encoding
ALPHA  = A-Z / a-z
DIGIT  = 0-9
other  = - . _ ~

// These are always safe in any part of a URL:
https://example.com/my-file_name.v2~backup

其他所有字符——包括空格、非 ASCII 字符和控制字符——都必须进行百分号编码。

JavaScript 中的 encodeURI 与 encodeURIComponent

JavaScript 提供两个内置 URL 编码函数,使用错误的那个是最常见的错误之一:

encodeURI()

编码完整 URI。不会编码在 URL 中有特殊含义的字符:: / ? # [ ] @ ! $ & ' ( ) * + , ; =

// encodeURI() — for complete URLs
const url = 'https://example.com/path name/file?q=hello world';
encodeURI(url);
// → "https://example.com/path%20name/file?q=hello%20world"
// Note: :, /, ?, = are NOT encoded (URL structure preserved)

encodeURIComponent()

编码 URI 组件(如查询参数值)。会编码保留字符如 & = + / ——这正是处理参数值时所需要的。

// encodeURIComponent() — for parameter values
const query = 'price=100&currency=USD';
encodeURIComponent(query);
// → "price%3D100%26currency%3DUSD"
// Note: = and & ARE encoded (they're data, not structure)

// Correct usage: build URL piece by piece
const base = 'https://api.example.com/search';
const param = 'Tom & Jerry: The Movie';
const fullUrl = base + '?q=' + encodeURIComponent(param);
// → "https://api.example.com/search?q=Tom%20%26%20Jerry%3A%20The%20Movie"

经验法则:对查询参数值和路径段使用 encodeURIComponent()。仅在编码希望保留结构的完整 URL 时使用 encodeURI()

// Side-by-side comparison
const text = 'hello world & goodbye=fun';

encodeURI(text);
// → "hello%20world%20&%20goodbye=fun"
//    & and = are NOT encoded

encodeURIComponent(text);
// → "hello%20world%20%26%20goodbye%3Dfun"
//    & and = ARE encoded

// decodeURI() and decodeURIComponent() reverse the process
decodeURIComponent('%E4%B8%AD%E6%96%87'); // → "中文"

不同编程语言中的 URL 编码

Python

# Python 3 — urllib.parse
from urllib.parse import quote, quote_plus, unquote, urlencode

# Encode a path segment (spaces → %20)
quote('hello world/file name')
# → 'hello%20world/file%20name'   (/ is safe by default)

# Encode a path segment including /
quote('hello world/file name', safe='')
# → 'hello%20world%2Ffile%20name'

# Encode a query parameter value (spaces → +)
quote_plus('hello world&foo=bar')
# → 'hello+world%26foo%3Dbar'

# Build query string from dict
urlencode({'q': 'Tom & Jerry', 'page': '1'})
# → 'q=Tom+%26+Jerry&page=1'

# Decode
unquote('%E4%B8%AD%E6%96%87')  # → '中文'

Java

// Java — URLEncoder / URI
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// Encode a query parameter value (spaces → +)
String encoded = URLEncoder.encode(
    "hello world&foo=bar", StandardCharsets.UTF_8
);
// → "hello+world%26foo%3Dbar"

// Decode
String decoded = URLDecoder.decode(
    "hello+world%26foo%3Dbar", StandardCharsets.UTF_8
);
// → "hello world&foo=bar"

// For path segments, use URI class
import java.net.URI;
URI uri = new URI("https", "example.com", "/path with spaces", "q=hello world", null);
// → https://example.com/path%20with%20spaces?q=hello%20world

Go

// Go — net/url package
package main

import (
    "fmt"
    "net/url"
)

func main() {
    // Encode a query parameter value
    encoded := url.QueryEscape("hello world&foo=bar")
    // → "hello+world%26foo%3Dbar"

    // Encode a path segment
    pathEncoded := url.PathEscape("hello world/file")
    // → "hello%20world%2Ffile"

    // Build a complete URL safely
    u := &url.URL{
        Scheme: "https",
        Host:   "example.com",
        Path:   "/search",
    }
    q := u.Query()
    q.Set("q", "Tom & Jerry")
    q.Set("lang", "en")
    u.RawQuery = q.Encode()
    fmt.Println(u.String())
    // → "https://example.com/search?lang=en&q=Tom+%26+Jerry"
}

PHP

<?php
// PHP — urlencode / rawurlencode

// Query parameter encoding (spaces → +)
echo urlencode('hello world&foo=bar');
// → "hello+world%26foo%3Dbar"

// Path segment encoding (spaces → %20, RFC 3986)
echo rawurlencode('hello world&foo=bar');
// → "hello%20world%26foo%3Dbar"

// Build query string from array
echo http_build_query([
    'q' => 'Tom & Jerry',
    'page' => 1
]);
// → "q=Tom+%26+Jerry&page=1"

// Decode
echo urldecode('hello+world%26foo%3Dbar');
// → "hello world&foo=bar"

echo rawurldecode('hello%20world%26foo%3Dbar');
// → "hello world&foo=bar"
?>

C#

// C# — Uri.EscapeDataString / HttpUtility
using System;
using System.Web;

// Encode a URI component (RFC 3986)
string encoded = Uri.EscapeDataString("hello world&foo=bar");
// → "hello%20world%26foo%3Dbar"

// Encode for query string (spaces → +)
string queryEncoded = HttpUtility.UrlEncode("hello world&foo=bar");
// → "hello+world%26foo%3Dbar"

// Decode
string decoded = Uri.UnescapeDataString("hello%20world%26foo%3Dbar");
// → "hello world&foo=bar"

// Build query string
var query = HttpUtility.ParseQueryString(string.Empty);
query["q"] = "Tom & Jerry";
query["page"] = "1";
string queryString = query.ToString();
// → "q=Tom+%26+Jerry&page=1"

Ruby

# Ruby — URI / CGI
require 'uri'
require 'cgi'

# Encode a component (spaces → %20)
URI.encode_www_form_component('hello world&foo=bar')
# → "hello+world%26foo%3Dbar"

# Encode for path (spaces → %20)
URI::DEFAULT_PARSER.escape('hello world')
# → "hello%20world"

# Build query string
URI.encode_www_form('q' => 'Tom & Jerry', 'page' => '1')
# → "q=Tom+%26+Jerry&page=1"

# Decode
CGI.unescape('hello%20world%26foo%3Dbar')
# → "hello world&foo=bar"

常见 URL 编码错误

1. 重复编码(Double Encoding)

重复编码发生在对已编码的字符串再次编码时。例如,%20 变成 %2520% 被编码为 %25)。这是最常见且最难调试的 URL 问题之一。

// Double encoding example
const value = 'hello world';

// First encoding (correct)
const encoded = encodeURIComponent(value);
// → "hello%20world"

// Accidentally encoding again (BUG!)
const doubleEncoded = encodeURIComponent(encoded);
// → "hello%2520world"
//   %20 → %25 (the %) + 20 → %2520

// The server receives "hello%20world" instead of "hello world"
// Fix: only encode once, at the point where you build the URL

2. 编码整个 URL

永远不要将整个 URL 传给 encodeURIComponent()。它会编码 :///?= 字符,破坏 URL 结构。只编码单个参数值。

// WRONG: encoding the entire URL
const url = 'https://example.com/api?q=hello world';
encodeURIComponent(url);
// → "https%3A%2F%2Fexample.com%2Fapi%3Fq%3Dhello%20world"
// Completely broken URL!

// CORRECT: only encode the parameter value
const base = 'https://example.com/api';
const query = 'hello world';
const correctUrl = base + '?q=' + encodeURIComponent(query);
// → "https://example.com/api?q=hello%20world"

3. 忘记 + 与 %20 的区别

application/x-www-form-urlencoded 格式(HTML 表单)中,空格编码为 +。在标准百分号编码(RFC 3986)中,空格为 %20。大多数服务端框架两者都支持,但 API 可能较严格。不确定时使用 %20

// + vs %20 for spaces
// Form data (application/x-www-form-urlencoded):
// "hello world" → "hello+world"

// RFC 3986 (URI standard):
// "hello world" → "hello%20world"

// In JavaScript:
encodeURIComponent('hello world');  // → "hello%20world"
// To get + for form data, replace after:
encodeURIComponent('hello world').replace(/%20/g, '+');
// → "hello+world"

// URLSearchParams automatically uses + for spaces:
new URLSearchParams({ q: 'hello world' }).toString();
// → "q=hello+world"

4. 未编码非 ASCII 字符

如中文、日文、表情符号等字符必须先转换为 UTF-8 编码,然后对每个字节进行百分号编码。忘记这一步会导致 URL 中出现乱码。

// Non-ASCII characters must be UTF-8 encoded first
encodeURIComponent('café');
// → "caf%C3%A9"   (é = 2 UTF-8 bytes: C3 A9)

encodeURIComponent('中文');
// → "%E4%B8%AD%E6%96%87"  (中 = 3 bytes, 文 = 3 bytes)

encodeURIComponent('🚀');
// → "%F0%9F%9A%80"   (rocket emoji = 4 UTF-8 bytes)

5. 在服务端编码 Hash 片段

片段标识符(#section)不会发送到服务器——它仅在客户端使用。在服务端编码或处理它是无意义的。

6. 在 JavaScript 中使用已弃用的 escape()

escape() 函数已被弃用,且不能正确处理 UTF-8。请始终使用 encodeURI()encodeURIComponent()

// DEPRECATED — do NOT use
escape('hello world');   // → "hello%20world" (works for ASCII)
escape('café');          // → "caf%E9" (WRONG! not UTF-8)

// CORRECT alternatives
encodeURIComponent('café');  // → "caf%C3%A9" (correct UTF-8)

何时进行 URL 编码:查询参数、路径段、片段

URL 的不同部分有不同的编码规则:

// URL anatomy and encoding zones
https://user:pass@example.com:8080/path/to/page?key=value&k2=v2#section
|____| |_______| |__________| |__||____________||________________||______|
scheme  userinfo    host      port    path         query string   fragment

// Each part has different encoding rules:

查询参数

始终编码参数的键和值。这是最常需要编码的地方。

// Query parameters: ALWAYS encode keys and values
const params = new URLSearchParams();
params.set('search', 'C++ programming');    // auto-encodes
params.set('filter', 'price>100&sale=true'); // auto-encodes
params.toString();
// → "search=C%2B%2B+programming&filter=price%3E100%26sale%3Dtrue"

// Or manually:
'?q=' + encodeURIComponent('price > $100 & discount = 20%')
// → "?q=price%20%3E%20%24100%20%26%20discount%20%3D%2020%25"

路径段

分别编码每个路径段。作为 URL 结构的正斜杠(<code>/</code>)不应编码,但段值中的斜杠必须编码。

// Path segments: encode each segment individually
const fileName = 'my report (final).pdf';
const path = '/files/' + encodeURIComponent(fileName);
// → "/files/my%20report%20(final).pdf"

// DO NOT encode the structural slashes:
// WRONG: encodeURIComponent('/files/my report.pdf')
// → "%2Ffiles%2Fmy%20report.pdf" (broken path)

片段标识符

片段(<code>#</code> 之后的部分)遵循与查询字符串相同的编码规则。注意片段不会发送到服务器。

// Fragment: encode like query string values
const section = 'Q&A Section';
const url = '/page#' + encodeURIComponent(section);
// → "/page#Q%26A%20Section"

// Remember: browsers never send fragments to the server
// window.location.hash gives you the raw fragment

域名(主机名)

域名对国际化域名(IDN)使用 Punycode(而非百分号编码)。例如,带变音符的 münchen.de 变为 xn--mnchen-3ya.de

// International Domain Names use Punycode, NOT percent encoding
// münchen.de → xn--mnchen-3ya.de
// 中文.com    → xn--fiq228c.com
// 日本語.jp   → xn--wgv71a309e.jp

// In JavaScript:
const url = new URL('https://münchen.de/path');
url.hostname;  // → "xn--mnchen-3ya.de" (auto-converted)

常见问题

%20 和 + 表示空格有什么区别?

两者都表示空格,但来自不同标准。%20 由 RFC 3986(URI 标准)定义,用于路径段和现代 API。+application/x-www-form-urlencoded 格式(HTML 表单)定义。在查询字符串中,大多数服务器两者都接受。为了最大兼容性,使用 %20

应该编码 URL 路径中的正斜杠(/)吗?

仅当斜杠是数据值的一部分(而非路径分隔符)时才需编码。例如,如果文件名包含斜杠,必须在路径段中编码为 %2F。分隔路径段的结构性斜杠永远不应编码。

如何在 URL 中编码 Unicode 字符(如中文、阿拉伯文)?

先将字符转换为 UTF-8 字节序列,然后对每个字节进行百分号编码。例如,"café"→ UTF-8 字节 63 61 66 C3 A9 → é 变为 %C3%A9。现代编程语言的 URL 编码函数会自动处理这些。

URL 编码区分大小写吗?

百分号编码中的十六进制数字不区分大小写(%2f%2F 等价)。但 RFC 3986 建议使用大写字母(%2F)以保持一致性和规范化。

需要编码整个 URL 还是只编码部分?

永远不要一次性编码整个 URL。只编码各个组件——查询参数值、包含特殊字符的路径段和片段标识符。结构性字符(:///?=&)必须保持未编码以保留 URL 结构。

URL 编码是 Web 开发的基础技能。收藏此参考表以便快速查阅,并使用我们的工具实时编码和解码 URL。

使用我们的 URL 编码/解码工具编码和解码任何 URL →

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

%20URL Encoder/Decoder🔗URL Parser%%Percent Encoding Tool

相关文章

REST API 最佳实践:2026 完整指南

学习 REST API 设计最佳实践,包括命名规范、错误处理、认证、分页、版本控制和安全头。

URL 编码与解码完全指南:百分号编码详解

免费在线 URL 编码解码工具。详解百分号编码原理,支持 JavaScript、Python、Bash、PHP 代码示例。