你做網站時送出一個 request,畫面突然顯示「404」。換一個 API 又看到「401」,伺服器壞掉時可能變成「500」,Cloudflare 或反向代理出問題又冒出「502」。這些數字很容易被背成一張錯誤代碼表,但那樣其實少了最重要的東西:它們不是隨機編號,而是在描述這次 HTTP request 的結果屬於哪一類。
HTTP Status Code,可以先理解成伺服器放在 response 裡的一個標準化狀態訊號。它讓瀏覽器、App、前端程式、API client 或另一台伺服器,不必先讀完一大段文字,就能知道這次要求是成功了、需要重新導向、request 本身有問題,還是伺服器端沒辦法正常處理。
所以狀態碼和 response body 是兩回事。伺服器可以回 404,同時附上一段 JSON 說明找不到哪個資料;也可以回 200,再附上你真正要的內容。status code 比較像「這次 HTTP 互動的分類結果」,body 才是進一步的資料或錯誤細節。
先看第一個數字:1xx 到 5xx 在分什麼?
HTTP response status code 被分成五大類。第一位數字已經能提供很多資訊:1xx 是資訊性回應,2xx 表示 request 成功被處理,3xx 和重新導向有關,4xx 表示目前這個 request 無法被伺服器照預期完成,5xx 則表示伺服器端在處理一個看起來有效的 request 時出了問題。
這裡有一個很常見但不太準確的口訣:「4xx 是使用者的錯,5xx 是伺服器的錯。」它拿來快速記憶還可以,但實務上別把責任真的丟給某個人。404 可能只是前端用了舊網址;401 可能是 access token 過期;429 也可能是你的程式重試策略寫得太激進。status code 描述的是 HTTP 層的狀態,不是在判案。
200 不代表「所有事情都完美」
200 OK 是最常見的成功狀態之一,代表 request 已成功。除此之外,建立新 resource 時常會看到 201 Created;如果伺服器已接受工作,但真正處理會稍後完成,可能使用 202 Accepted;某個操作成功、但沒有 response body 要回時,也常見 204 No Content。
這也提醒了一件事:2xx 是一個家族,不是所有成功都只能回 200。如果你建立一篇文章,API 回 201,反而比什麼都用 200 更能表達發生了什麼。
另外,200 只代表 HTTP 層把這次要求視為成功。如果一個 API 每次都回 200,再把真正的錯誤塞進 { "ok": false },程式當然還是能跑,但 client 就失去了很多 HTTP 本身已經提供的語意。
401 和 403:一個是身分驗證,一個是拒絕處理
401 Unauthorized 的英文名稱很容易誤導。它主要表示 request 缺少有效的 authentication credentials,也就是系統還不能接受你目前提供的登入身分資訊。常見情況包括 token 沒帶、token 過期,或 authentication 資料無效。
403 Forbidden 則表示伺服器理解這個 request,但拒絕處理。最典型的情況是:你已經知道自己是誰,但這個帳號沒有做這件事的權限。例如學生成功登入成績系統,卻嘗試修改別人的成績,後端就可能回 403。
403 → request 看懂了,但伺服器拒絕做
這不是說所有網站一定只能照這個情境使用,實際安全設計也可能刻意隱藏資訊;但理解 authentication 和 authorization 的差異後,你會比死背「401 未授權、403 禁止」更容易讀懂 API。
404 和 410:找不到,不一定等於永遠消失
404 Not Found 表示伺服器找不到要求的 resource。它沒有保證這個東西以前不存在,也沒有保證未來不會出現,只是說目前這個 request 找不到它。
如果伺服器知道某個 resource 已經被永久移除,HTTP 還有更精確的 410 Gone。不過實務上很多系統仍大量使用 404,因為伺服器不一定知道資源消失是不是永久狀態,或不想對外透露更多資訊。
400 和 422:request 壞掉,和內容不合理,不完全一樣
400 Bad Request 常用在 request 本身有問題,例如語法不合法、message framing 錯誤,或伺服器根本無法把它當成正常 request 處理。
422 Unprocessable Content 則更像:「我知道你送的是什麼格式,也讀得懂,但照你給的內容做不下去。」例如 API 要求年齡必須是正整數,你送的 JSON 完全合法,但值是 -5;或者一個欄位格式合法,卻違反服務的資料規則。不同 API 會有自己的錯誤設計,不是所有 validation error 都一定要回 422,但這個差異能幫你理解為什麼兩種碼會同時存在。
429:不是伺服器壞掉,是你打得太快
429 Too Many Requests 表示 client 在一段時間內送出了太多 request,也就是碰到了 rate limit。做第三方 API、AI API 或爬取服務時很常遇到。這時候真正該做的通常不是無限快速重試,而是看服務端提供的限制資訊,搭配等待、backoff 或排程。
500、502、503:都在 5xx,但壞的位置不一樣
500 Internal Server Error 是很泛用的 server error。它大致表示伺服器碰到預期外的狀況,沒辦法正常完成 request,但沒有更精確的狀態適合回。程式丟出未處理例外、某段後端邏輯爆掉,都可能最後變成 500。
502 Bad Gateway 則常出現在系統中間還有 gateway、reverse proxy 或其他上游服務時。收到 request 的那台機器本身可能還活著,但它去問 upstream server 時拿到了無效的 response。所以你看到 502,不代表瀏覽器和第一層伺服器完全連不上;問題可能在更後面的服務鏈。
503 Service Unavailable 表示伺服器目前還沒準備好處理 request。維護、過載、暫時性服務不可用都可能出現 503。這和 500 那種「處理時撞到非預期錯誤」不太一樣,503 更常帶有暫時不可用的意味。
502 → gateway / proxy 從上游拿到無效回應
503 → 服務目前沒有準備好接這個 request
Status Code 不是錯誤訊息本身
如果 API 只回一個 422,你知道 request 的內容有問題,但還是不知道是哪個欄位。如果只看到 500,你知道問題在 server side,但不知道是 database timeout、程式例外,還是另一個依賴服務失敗。所以好的 API 通常還會在 response body 裡補上 machine-readable 的錯誤資訊,例如 error code、message、欄位或 trace id。
HTTP/1.1 422 Unprocessable Content
Content-Type: application/json
{
"error": "invalid_email",
"field": "email",
"message": "Email format is invalid"
}
這時 status code 負責大分類,body 負責具體原因。前端可以先用 status code 判斷大方向,再根據 API 定義的 error body 顯示正確訊息,而不是把伺服器所有錯誤一律翻成「發生未知錯誤」。
除錯時,先問「哪一層回了這個碼?」
這是 status code 真正好用的地方。看到 404,先確認 URL、route 和 resource;看到 401,檢查 authentication;看到 403,往 permission 和 policy 找;看到 429,查 rate limit;看到 500,開始看後端 log;看到 502,往 proxy 和 upstream dependency 追;看到 503,就檢查服務健康狀態、負載與維護情況。
它不會直接替你找出 bug,但會把搜尋範圍縮小。當系統從「一個網站」長成 frontend、API、reverse proxy、database、第三方服務好幾層之後,這種標準化訊號就非常重要。
所以別把 200、404、500 當成需要硬背的神祕數字。HTTP Status Code 是 response 對這次 request 結果的共同語言。先看它屬於哪一類,再看具體代碼和 response body,你通常就能知道下一步該往哪裡查。