HTTP 状态码

可检索的 HTTP 状态码速查表,包含标准原因短语与定义它的 RFC 章节,支持按 1xx 至 5xx 分类过滤。

这个响应码到底代表什么? 输入数字(如 429)或单词(如 gateway)过滤表格,也可以只看某一类。每行给出状态码、在链路上实际传输的原因短语,以及定义它的规范章节。

匹配的状态码
状态码 原因短语 定义出处

正确理解 HTTP 状态码

首位数字才是真正的契约

每个 HTTP 响应都以三位数字开头,而客户端必须理解的只有第一位。RFC 9110 写得很明确:收到无法识别的 499 时,客户端应当完全按 400 处理。类别决定语义,后两位只是细化。正是这条规则让协议可以持续扩展——2005 年写的代理今天仍能正确转发 451,哪怕它根本不知道什么是法律审查。

五个类别按"接下来谁负责"划分得很干净:1xx 是临时响应,真正的结果还在后面;2xx 表示成功,客户端可以收工;3xx 交回一个重定向,客户端应换个地址重试;4xx 归咎于请求本身,原样重发只会再次失败;5xx 归咎于服务端,同样的请求重试有可能成功。所以重试逻辑应该按类别而不是具体码来写:重试 503 合理,重试 403 是 bug。

最容易混淆的几组

301 与 308、302 与 307 的区别不是风格问题。旧的一组允许客户端在跟随重定向时把 POST 改写成 GET,浏览器历史上确实这么做。新的一组禁止改写,方法和请求体都会被保留。如果用 301 迁移一个表单端点,部分客户端会静默地把提交变成 GET 并丢掉负载。非幂等的请求请用 308 或 307。

401 和 403 同样常被混用。401 表示请求未通过认证,响应必须带上 WWW-Authenticate 挑战头,告诉客户端该怎样带凭据重试;403 表示服务端已经知道你是谁,但仍然拒绝。不带挑战头的 401 属于违反规范,而用户只是忘了登录却返回 403,会让排查变得困难得多。

4xx 里还有一组很有用的划分:400 与 422。400 表示请求根本无法解析,语法就是坏的;422 表示语法解析正常,但内容没通过校验。区分这两者能把一个含糊的失败变成可行动的提示。

原因短语只写给人看

状态码旁边的文字(如 Not FoundI'm a teapot)叫原因短语。HTTP/1.1 会在状态行里传输它,但 HTTP/2 和 HTTP/3 已彻底移除,所以现代连接上往往只有数字而没有短语。客户端代码绝不应该依据这个字符串分支判断——它存在的意义仅仅是让人在看日志或原始抓包时不用查表。

有些状态码的约束也比看上去更严格:204 和 304 不得携带消息体,中间件擅自添加就会产生非法响应;HEAD 响应无论什么码都不带消息体。这些成帧规则很重要,因为不该有消息体的地方出现消息体会破坏连接复用的同步,表现出来是跨请求的诡异串数据,而不是一个明确的报错。

开源说明:使用原生 JavaScript 实现,不依赖第三方库。

常见问题

HTTP 状态码一共有多少个?
IANA 注册的状态码在五个类别中略多于六十个,本表全部收录,另外还补充了若干广泛部署的 WebDAV 与扩展状态码。注册表是有意开放的,随时可能新增,这也正是客户端必须按首位数字兜底的原因。
永久重定向该用 301 还是 308?
除非你明确希望老客户端把 POST 转成 GET,否则用 308。两者都表示资源已永久迁移,但只有 308 保证方法和请求体在重定向后保持不变。普通页面搬迁两者都可以,301 的老旧兼容性稍好一些。
401 和 403 有什么区别?
401 表示尚未认证,响应必须带 WWW-Authenticate 头说明如何认证;403 表示认证已通过但仍无权限。用户只是需要登录就返回 401,账号确实缺少权限才返回 403。
418 I'm a teapot 是真的状态码吗?
从 RFC 2324 的角度说是真的,它定义于 1998 年的愚人节规范「超文本咖啡壶控制协议」。IANA 保留了 418,防止被其他用途占用。它不属于 HTTP 本体,但不少框架把它作为彩蛋实现了。
客户端应该自动重试哪些状态码?
可以重试 408、429 以及大多数 5xx,并且只要响应带了 Retry-After 就必须遵守。除 408 和 429 外的 4xx 不要重试,因为问题出在请求本身,原样重发结果完全相同。
为什么我的 HTTP/2 响应没有原因短语?
HTTP/2 和 HTTP/3 从线路格式中移除了原因短语,因为本来就没有客户端应该去解析它,链路上只传数字。工具为 HTTP/2 响应显示的短语,都是在本地用类似本表的数据查出来的。