URL 结构与百分号编码速查

5 个速查板块 · 关联 5 款站内工具 · 数据最后核对 2026-10-05

一个 URL 拆开是七个部分、哪些字符必须转义、中文地址为什么变成一长串百分号,以及 URL 到底有没有长度限制。

URL 是互联网上最常被看见、却最少被完整理解的东西。它由若干有明确语义的部分拼成,每一部分各自有转义规则——这也是「同一个地址在浏览器、日志、后端框架里长得不一样」的原因。

理解它有一份很实在的收益:参数该放查询串还是路径、锚点为什么后端读不到、中文为什么变成 %E4%B8%AD、接口报「URL 过长」该怎么改,这些问题都能自己回答。下面先拆结构,再讲编码规则。

1URL 的七个组成部分

以 https://user:pw@www.example.com:8443/a/b?x=1&y=2#top 为例,各部分的名称与作用如下。

部分示例说明
协议 Schemehttps用什么协议访问。常见有 http、https、ftp、file、mailto
用户信息 Userinfouser:pw已废弃的写法,凭证放在 URL 里会留在日志中,不应再用
主机 Hostwww.example.com域名或 IP,是 URL 中唯一必需(在 http/https 下)的部分
端口 Port8443省略时用协议默认值:http 是 80,https 是 443
路径 Path/a/b资源在服务器上的位置,层级用 / 分隔
查询 Queryx=1&y=2以 ? 开始,& 分隔多个键值对。用于筛选、分页、搜索词
锚点 Fragmenttop以 # 开始。**只在浏览器内生效,不会发送给服务器**

锚点不发给服务器这一点很实用:如果用锚点传参数,后端永远拿不到;但反过来,用锚点做页面内定位或前端路由,就不会污染服务端的访问日志,也不会影响缓存命中。

2哪些字符必须转义

URL 里的字符分成三类:可以直接出现的、有特殊含义必须转义的、以及可以出现但不建议出现的。转义的写法是 % 加两位十六进制(即该字符 UTF-8 字节的十六进制值)。

分类字符处理方式
未保留字符(可直接用)A-Z a-z 0-9 与 - . _ ~无需转义,出现任何场合都安全
保留字符(有语法含义):/?#[]@ 与 !$&'()*+,;=作为分隔符使用时不转义;作为普通数据时必须转义
必须转义空格、中文、"、<、>、` `、\、^、{|}` 等统一转义,如空格转成 %20
不安全字符控制字符、换行、制表符一律转义,出现在 URL 中通常说明数据未做处理

3中文与空格:实际会变成什么

中文并不是被「翻译」了,而是先按 UTF-8 编码成字节,再把每个字节写成百分号形式。所以一个汉字通常对应三个 %XX。

原始内容转义结果说明
中%E4%B8%ADUTF-8 下「中」是 3 字节,所以有 3 个 %XX
中文%E4%B8%AD%E6%96%876 个字节,6 个 %XX
空格(路径中)%20标准写法
空格(查询串中)+ 或 %20+ 表示空格只适用于 form-urlencoded 场景,路径中必须用 %20
#%23不转义会被当成锚点起始符,导致后面的内容全被截断
&%26作为参数值出现时必须转义,否则会被切断成新参数
中文域名xn--fiq228c.cn国际化域名先转成 Punycode 再解析

「参数值里带 `&` 或 `=` 却忘了转义」是最常见的参数解析 bug:看起来是一个参数,服务端却读到了两三个。凡是把用户输入直接拼进 URL 的地方,都要先做一次编码。

4URL、URI、URN 的关系

三个词经常被混用。严格来说,URI 是最大的集合,URL 和 URN 都是它的子集:URL 负责定位(在哪),URN 负责命名(叫什么)。

URI
统一资源标识符,泛指「能标识一个资源的东西」,是 URL 与 URN 的统称
URL
统一资源定位符,指出了「怎么找到它」,日常说的网址就是 URL
URN
统一资源名称,只给资源一个持久名字,不说明怎么获取,实际应用很少
日常用法
写代码时字段名常叫 uri(含义更宽),实际内容基本是 URL。做技术文档区分时,严格写 URL 更准确
路径与查询的取舍
资源标识(谁)放路径 /users/123,筛选与排序(怎么取)放查询 ?page=2&sort=desc。这样缓存与日志分析都更清晰

5URL 有长度限制吗

规范本身没有规定 URL 的最大长度,限制来自具体的实现。所以「URL 太长」是一个工程问题,不是协议问题。

规范层面
RFC 3986 未规定长度上限,任何长度理论上都是合法的
浏览器层面
现代浏览器支持到数万字符;早年 IE 的 2083 字符限制已经成为历史,但仍常被引用
服务器层面
才是真正的瓶颈。Nginx 默认单个请求行与请求头缓冲区为 8KB 左右,超过会返回 414 或 431
CDN 与网关
多数 CDN 对请求行也有类似限制,且不同厂商数值不同,迁移时容易踩
应对方式
长参数改用 POST 请求体传递;批量 ID 改用逗号分隔而不是重复键;分页参数不要塞进路径;确实需要超长内容的场景改用服务端生成的短标识

关于「URL 结构与百分号编码速查」的常见问题

URL 里的锚点(#后面那段)后端能收到吗?

不能。按规范,锚点部分只在客户端(浏览器)内使用,发起请求时会被完全去掉,服务器端根本看不到。所以想用 # 传参数给后端是行不通的。反过来,如果某个信息只与前端展示有关(页面内定位、前端路由状态、滚动位置),放在锚点里反而是好选择——它不会污染服务端日志,也不会影响缓存键。

为什么中文参数在地址栏里变成了一串 %E4%B8%AD?

这是百分号编码(也叫 URL 编码)。URL 只允许出现一部分 ASCII 字符,其它字符必须先按 UTF-8 编码成字节,再把每个字节写成 % 加两位十六进制的形式。「中」在 UTF-8 下是 3 个字节(E4 B8 AD),所以编码后就是 %E4%B8%AD。这不是乱码,而是标准写法,属于同一套规则对空格(%20)、井号(%23)的处理方式。

URL 最大能有多长?

协议规范没有规定上限,限制来自实现。服务器端通常是真正的瓶颈:Nginx 默认的请求行与请求头缓冲区合计约 8KB,超出会返回 414(URI Too Long)或 431(请求头过大);各类 CDN 与网关也各有自己的限额。浏览器侧现代版本支持到数万字符,早年 IE 的 2083 限制已不适用。所以处理长参数应优先改用 POST 请求体,而不是试图把 URL 拉长。

把参数放在路径里还是查询串里?

一个简单的判断标准:这个信息是「资源的身份」还是「取资源的方式」。身份放路径,例如 /users/123、/articles/how-to-xxx;取法放查询串,例如 ?page=2&sort=desc&q=关键词。这样做的直接好处是缓存与日志分析都更清晰——同一资源的不同筛选条件可以被识别为同一类请求,而资源本身的地址保持稳定,页面改版也不会影响已收录的链接。

内容标识:本页内容由人工智能辅助生成,并经人工核对与编辑。详见 人工智能生成内容标识说明。
内容说明:本页速查数据由本站自行整理,事实性内容以对应官方规范与文档为准,未复制第三方速查表或百科的表述。数据最后核对日期:2026-10-05。若发现错误或已更新的标准,欢迎通过页脚反馈入口告知。