
เคยกดลิงก์แล้วเจอหน้าที่เขียนว่า 404 ไหมครับ หรือกดสั่งของในแอปแล้วขึ้นว่า 500 ตัวเลขพวกนี้ไม่ได้สุ่มขึ้นมา มันคือ HTTP Status Code รหัสสามหลักที่เซิร์ฟเวอร์แนบมากับคำตอบทุกครั้ง เพื่อบอกว่าคำขอของเราจบลงแบบไหน
ข่าวดีคือไม่ต้องท่องทุกเลข แค่ดูเลขตัวแรกก็รู้แล้วว่าปัญหาอยู่ฝั่งไหน บทความนี้จะพาไปเข้าใจหลักการ แล้วลองทำให้เกิด 200, 404 และ 500 ด้วยมือตัวเอง ทั้งในเบราว์เซอร์ ในคำสั่ง curl ใน Postman และในโค้ด JavaScript
จบบทความนี้คุณจะ:
- อธิบายได้ว่า Request, Response และ Status Code ทำงานด้วยกันยังไง
- แยก 5 กลุ่มของ Status Code ได้จากเลขตัวแรก
- เปิดดูเลขสถานะจริงได้ทั้งใน DevTools,
curlและ Postman - เขียน
fetchที่เช็กres.okได้ถูก และรู้ว่าทำไมfetchไม่ throw ตอนเจอ 404 - รู้ว่าเจอ 404, 401, 403, 500 หรือ 503 แล้วควรทำอะไรต่อ
ถ้าอยากเห็นภาพรวมก่อน ดูคลิปสั้นนี้ได้เลย ยาวแค่ 1 นาทีครับ
สั่งอาหาร แล้วพนักงานตอบกลับ
ทุกครั้งที่เปิดเว็บ จะมีสองฝ่ายคุยกัน ฝ่ายหนึ่งคือ Client (ไคลเอนต์) ผู้ขอ เช่น เบราว์เซอร์ แอปในมือถือ หรือโค้ดที่เราเขียน อีกฝ่ายคือ Server (เซิร์ฟเวอร์) ผู้ตอบ คือเครื่องที่เก็บหน้าเว็บหรือข้อมูลไว้
Client ส่ง Request (คำขอ) ไป แล้ว Server ตอบกลับด้วย Response (คำตอบ) และบรรทัดแรกสุดของคำตอบจะมีเลขสามหลักติดมาเสมอ นั่นคือ Status Code

เทียบกับร้านอาหารจะเห็นภาพง่ายขึ้น เราคือลูกค้า (Client) สั่งอาหารกับพนักงาน (Server) แล้วพนักงานตอบกลับได้หลายแบบ
| พนักงานตอบว่า | เทียบกับเลข |
|---|---|
| "ได้เลยครับ นี่อาหารของคุณ" | 200 สำเร็จ |
| "ร้านย้ายไปสาขาใหม่แล้ว เชิญทางนั้น" | 301 ย้ายถาวร |
| "เมนูนี้ไม่มีในร้านครับ" | 404 ไม่พบ |
| "ครัวมีปัญหา ทำให้ไม่ได้ตอนนี้" | 500 เซิร์ฟเวอร์ผิดพลาด |
| "ร้านเต็ม รอสักครู่นะครับ" | 503 ให้บริการไม่ได้ชั่วคราว |
สิ่งที่อยากให้จำคือ Status Code ไม่ได้แปลว่า error เสมอไป มันคือรายงานผล บอกว่าคำขอจบลงแบบไหน และคำขอส่วนใหญ่ที่ทำงานปกติก็ได้ 200 ครับ
ศัพท์ที่ต้องรู้
| คำ | เทียบกับ | หน้าที่ |
|---|---|---|
| HTTP | ภาษากลางของร้าน | กติกาการส่งคำขอและคำตอบบนเว็บ |
| Request | ใบสั่งอาหาร | บอกว่าขออะไร จากที่ไหน |
| Method | ชนิดของคำสั่ง | GET ขอดู POST ส่งข้อมูลไปสร้างของใหม่ |
| Response | อาหารพร้อมใบแจ้ง | คำตอบ มีเลขสถานะ Headers และ Body |
| Status Code | คำตอบของพนักงาน | เลขสามหลักบอกว่าคำขอจบแบบไหน |
| Headers | ข้อความบนใบแจ้ง | ข้อมูลประกอบ เช่น ชนิดของข้อมูลที่ส่งมา |
| Body | ตัวอาหาร | เนื้อหาจริง เช่น หน้า HTML หรือ JSON |
ดูเลขตัวแรกก็รู้เรื่อง
Status Code มีเยอะก็จริง แต่ทุกตัวแบ่งเป็นแค่ 5 กลุ่มตามเลขหลักร้อย

| กลุ่ม | ความหมาย | ตัวอย่าง |
|---|---|---|
| 1xx | รับเรื่องแล้ว กำลังทำต่อ | แทบไม่เห็นในงานทั่วไป |
| 2xx | สำเร็จ | 200, 201 |
| 3xx | ไปที่อื่น หรือใช้ของเดิม | 301, 304 |
| 4xx | คำขอฝั่ง Client มีปัญหา | 400, 401, 403, 404 |
| 5xx | ฝั่ง Server มีปัญหา | 500, 502, 503 |
ทริกจำ: ขึ้นต้นด้วย 4 ให้ส่องที่ตัวคำขอก่อน เช่น URL ผิดไหม ล็อกอินหรือยัง ขึ้นต้นด้วย 5 ให้ส่องที่เซิร์ฟเวอร์ เช่น โค้ดหลังบ้านพังหรือเปล่า แค่นี้ก็รู้แล้วว่าจะเริ่มหาปัญหาจากตรงไหน
4xx ไม่ได้แปลว่าผู้ใช้ทำผิดเสมอ "ฝั่ง Client" หมายถึงตัวคำขอมีปัญหา เช่น ในหน้าเว็บมีลิงก์ชี้ไปหน้าที่ถูกลบไปแล้ว ผู้ใช้แค่กดตามลิงก์ แต่คำขอที่ส่งไปคือหน้าที่ไม่มีอยู่จริง เซิร์ฟเวอร์จึงตอบ 404 คนที่ต้องแก้คือเจ้าของเว็บที่ต้องไปแก้ลิงก์นั้น
เตรียมเครื่อง
- เบราว์เซอร์ Chrome หรือ Edge (DevTools หน้าตาเหมือนกัน)
curlโปรแกรมส่งคำขอจาก Terminal ติดมากับ Mac, Linux และ Windows 10 รุ่นใหม่ๆ ขึ้นไปแล้ว- Postman (ไม่บังคับ) ถ้ายังไม่มี ดูวิธีติดตั้งใน Postman คืออะไร ยิง API ครั้งแรก
เช็กว่ามี curl ด้วยคำสั่งนี้ (บน Windows ให้พิมพ์ curl.exe --version ใน PowerShell)
curl --versioncurl 8.7.1 ...
Protocols: dict file ftp ftps gopher gophers http https ...เช็กว่าได้แล้ว: บรรทัดแรกขึ้นต้นด้วย curl ตามด้วยเลขเวอร์ชัน (เลขของคุณอาจไม่เหมือนนี้ ไม่เป็นไร) และในบรรทัด Protocols มี https
ดูเลขสถานะในเบราว์เซอร์
ทุกหน้าเว็บที่เราเปิด เบราว์เซอร์ส่ง Request ออกไปหลายครั้ง ทั้งตัวหน้า HTML ไฟล์ CSS JavaScript และรูป เราแอบดูทั้งหมดได้ในแท็บ Network ของ DevTools
- เปิดเว็บไหนก็ได้ เช่น
https://developer.mozilla.org - กด Ctrl+Shift+J (Mac ใช้ Cmd+Option+J) เพื่อเปิด DevTools หรือกด F12
- คลิกแท็บ Network
- กด F5 เพื่อโหลดหน้าใหม่
ที่ต้องกด F5 เพราะแท็บ Network จดเฉพาะคำขอที่เกิดขึ้น ตอนที่มันเปิดอยู่ ถ้าเปิดหลังหน้าโหลดเสร็จ ตารางจะว่างเปล่า
เช็กว่าได้แล้ว: ตารางมีหลายแถว แต่ละแถวคือไฟล์หนึ่งไฟล์ที่เบราว์เซอร์ขอ และในคอลัมน์ Status ส่วนใหญ่เป็น 200
ถ้าเห็น 304 ปนอยู่ ไม่ต้องตกใจครับ 304 (Not Modified) แปลว่าเบราว์เซอร์มีไฟล์นี้เก็บไว้แล้ว เลยถามเซิร์ฟเวอร์ว่าไฟล์เปลี่ยนไหม เซิร์ฟเวอร์ตอบว่าไม่เปลี่ยน ใช้ของเดิมได้เลย จึงไม่ต้องส่งไฟล์ซ้ำ ประหยัดทั้งเวลาและเน็ต
ลองคลิกที่แถวแรกสุด (ตัวหน้า HTML) แล้วดูแท็บ Headers ทางขวา ในหัวข้อ General จะมีบรรทัด Status Code บอกเลขพร้อมชื่อ เช่น 200 OK
ลองทำให้เกิด 404
เปิด DevTools ค้างไว้ที่แท็บ Network แล้วพิมพ์ URL ที่ไม่มีอยู่จริงลงในช่องที่อยู่
https://developer.mozilla.org/hello-devkubหน้าเว็บจะขึ้นว่า Page not found และแถวแรกในแท็บ Network จะเป็น 404 สังเกตว่าหน้าก็ยังแสดงผลได้ปกติ เพราะเซิร์ฟเวอร์ส่งหน้าแจ้งเตือนมาให้คนอ่าน และส่งเลข 404 มาให้เครื่องอ่าน สองอย่างนี้แยกกันครับ
เช็กว่าได้แล้ว: แถว hello-devkub ในคอลัมน์ Status ขึ้น 404 และเบราว์เซอร์ทำแถวนั้นเป็นสีแดง
ยิงด้วย curl ดูแค่หัวจดหมาย
ในเบราว์เซอร์มีคำขอปนกันเยอะ ถ้าอยากดูทีละคำขอแบบชัดๆ ใช้ curl ใน Terminal จะง่ายกว่า เราจะยิงไปที่ postman-echo.com ซึ่งเป็นบริการของ Postman ที่ทำไว้ให้ทดลองโดยเฉพาะ มี path /status/เลข ที่ตอบกลับด้วยเลขอะไรก็ได้ตามที่เราขอ
curl -I https://postman-echo.com/getHTTP/2 200
content-type: application/json; charset=utf-8
content-length: 184ตัวเลือก -I บอก curl ให้ขอแค่ Headers ไม่เอา Body ผลจึงสั้นและอ่านง่าย มาดูทีละบรรทัดกันครับ
HTTP/2 200คือเวอร์ชันของ HTTP ตามด้วยเลขสถานะ บางเครื่องอาจขึ้นHTTP/1.1 200 OKก็ความหมายเดียวกันcontent-typeบอกว่า Body เป็นข้อมูลแบบ JSONcontent-lengthขนาดของ Body เป็นไบต์
ทีนี้ลองขอ 404 กับ 500 ดู
curl -I https://postman-echo.com/status/404
curl -I https://postman-echo.com/status/500HTTP/2 404
HTTP/2 500เช็กว่าได้แล้ว: บรรทัดแรกเปลี่ยนเลขตามที่เราขอ ลองเปลี่ยนเป็น 401, 403 หรือ 503 ต่อได้เลย
ถ้าอยากเห็น Body ด้วย ให้ใช้ -i ตัวเล็กแทน จะได้ทั้ง Headers และ Body ซึ่ง echo จะตอบกลับมาสั้นๆ ว่า {"status":404}
curl -i https://postman-echo.com/status/404บน Windows ให้พิมพ์ curl.exe ใน Windows PowerShell ตัวที่ติดมากับเครื่อง คำว่า
curlเฉยๆ เป็นชื่อเล่นของคำสั่งInvoke-WebRequestซึ่งไม่รู้จัก-Iจึงขึ้น error เรื่อง parameter ให้พิมพ์curl.exe -I https://postman-echo.com/status/404แทน หรือใช้ Command Prompt ที่curlเป็นตัวจริงอยู่แล้ว
ลองใน Postman
ถ้าไม่ถนัดพิมพ์คำสั่ง Postman ทำแบบเดียวกันได้ผ่านหน้าจอ
- กดปุ่ม + เพื่อเปิดแท็บคำขอใหม่
- เลือก Method เป็น
GET - ใส่ URL
https://postman-echo.com/status/404แล้วกด Send
เลขสถานะจะขึ้นที่มุมขวาของส่วน Response เช่น 404 Not Found เป็นสีแดง ลองเปลี่ยนเป็น /get จะได้ 200 OK สีเขียว และ /status/500 จะได้ 500 Internal Server Error
Postman ยังเขียน Test ให้ตรวจเลขสถานะอัตโนมัติได้ด้วย ที่แท็บ Scripts > Post-response กด Snippets แล้วเลือก Status code: Code is 200 ลองกด Send กับ /status/404 ดู Test จะไม่ผ่านทันที วิธีใช้แบบละเอียดอยู่ในบทความ Postman คืออะไร? ยิง API ครั้งแรกโดยไม่ต้องเขียนโค้ด
เช็กเลขสถานะในโค้ดด้วย fetch
fetch คือคำสั่งของ JavaScript สำหรับส่ง Request จากโค้ด และมีเรื่องหนึ่งที่มือใหม่เข้าใจผิดกันบ่อยมาก คือคิดว่าถ้าเซิร์ฟเวอร์ตอบ 404 หรือ 500 แล้ว fetch จะ throw error ให้เอง ความจริงคือไม่ throw สำหรับ fetch แค่ได้คำตอบกลับมา ไม่ว่าเลขอะไรก็ถือว่าสำเร็จ หน้าที่เช็กเลขจึงเป็นของเรา
ลองกันใน Console ครับ แต่ต้องเปิดให้ถูกแท็บก่อน
- เปิดแท็บใหม่ไปที่
https://postman-echo.com/get - กด F12 แล้วเลือกแท็บ Console ในแท็บนั้น
- พิมพ์โค้ดนี้แล้วกด Enter
const res = await fetch('https://postman-echo.com/status/404');
console.log(res.status); // 404
console.log(res.ok); // false404
falseawaitแปลว่ารอให้คำตอบกลับมาก่อนค่อยไปบรรทัดถัดไป (Console ของ Chrome ใช้awaitนอกฟังก์ชันได้)res.statusคือเลขสถานะres.okเป็นtrueเฉพาะเลข 200 ถึง 299 นอกนั้นเป็นfalse
ทำไมต้องรันในแท็บ postman-echo.com เบราว์เซอร์มีกฎความปลอดภัยชื่อ CORS ที่ห้ามหน้าเว็บหนึ่งอ่านคำตอบจากอีกเว็บหนึ่ง ถ้าเว็บนั้นไม่ได้อนุญาตไว้ และ postman-echo ไม่ได้เปิดให้เว็บอื่นอ่าน ถ้ารันโค้ดนี้ใน Console ของแท็บเว็บอื่น จะได้
TypeError: Failed to fetchแทน แต่ถ้ารันในแท็บของ postman-echo เอง ถือว่าเป็นเว็บเดียวกัน จึงไม่ติดกฎนี้
เขียนให้เจอ 404 แล้วไปจบที่ catch
ในงานจริง เรามักอยากให้เลขที่ไม่ใช่ 2xx ไปจบที่ catch เหมือน error ทั่วไป วิธีที่นิยมคือเขียนฟังก์ชันเล็กๆ ที่เช็ก res.ok แล้ว throw เอง
async function getJson(url) {
const res = await fetch(url);
if (!res.ok) {
throw new Error('เซิร์ฟเวอร์ตอบเลข ' + res.status);
}
return res.json();
}
try {
const data = await getJson('https://postman-echo.com/status/500');
console.log('ได้ข้อมูลแล้ว', data);
} catch (err) {
console.log('มีปัญหา:', err.message);
}มีปัญหา: เซิร์ฟเวอร์ตอบเลข 500if (!res.ok)เครื่องหมาย!แปลว่า "ไม่" ถ้าคำตอบไม่ ok ให้ทำในปีกกาthrow new Error(...)โยน error ออกไปเอง โค้ดจะกระโดดไปที่catchทันทีreturn res.json()ถ้า ok ค่อยอ่าน Body เป็น JSON แล้วส่งกลับ
ลองเปลี่ยน URL ในบรรทัด getJson(...) เป็น https://postman-echo.com/get แล้วรันใหม่ จะได้ ได้ข้อมูลแล้ว ตามด้วยข้อมูล JSON แทน
เช็กว่าได้แล้ว: URL ที่เป็น 500 ไปจบที่ มีปัญหา: ส่วน /get ไปจบที่ ได้ข้อมูลแล้ว
throw กับเลขสถานะต่างกันยังไง
fetchจะ throw เองก็ต่อเมื่อ ไม่ได้คำตอบเลย เช่น เน็ตหลุด หาชื่อเว็บไม่เจอ หรือเบราว์เซอร์บล็อก ส่วนถ้าได้คำตอบกลับมา จะเป็นเลขอะไรก็ไม่ throw ฟังก์ชันแบบgetJsonจึงช่วยให้ทั้งสองกรณีมาจบที่catchที่เดียว
เลขที่เจอบ่อย
ไม่ต้องท่องทั้งหมดครับ อ่านผ่านๆ ให้คุ้นตา แล้วกลับมาเปิดดูตอนเจอจริง
ทุกอย่างปกติ (2xx และ 3xx)
| เลข | ชื่อ | แปลว่า |
|---|---|---|
| 200 | OK | สำเร็จ ได้ของที่ขอ |
| 201 | Created | สร้างของใหม่สำเร็จ มักเจอหลัง POST |
| 301 | Moved Permanently | ย้ายที่อยู่ถาวร เบราว์เซอร์ตามไปให้เอง |
| 304 | Not Modified | ไม่มีอะไรเปลี่ยน ใช้ของที่เก็บไว้ได้ |
คำขอมีปัญหา (4xx)
| เลข | ชื่อ | แปลว่า |
|---|---|---|
| 400 | Bad Request | คำขอผิดรูปแบบ เช่น ส่ง JSON ผิด |
| 401 | Unauthorized | ยังไม่รู้ว่าเป็นใคร ต้องล็อกอินก่อน |
| 403 | Forbidden | รู้ว่าเป็นใคร แต่ไม่มีสิทธิ์ |
| 404 | Not Found | ไม่มีหน้าหรือข้อมูลนี้ |
| 429 | Too Many Requests | ขอถี่เกินไป รอแล้วค่อยลองใหม่ |
เซิร์ฟเวอร์มีปัญหา (5xx)
| เลข | ชื่อ | แปลว่า |
|---|---|---|
| 500 | Internal Server Error | โค้ดหลังบ้านพัง |
| 502 | Bad Gateway | ตัวกลางได้คำตอบเสียจากเครื่องข้างหลัง |
| 503 | Service Unavailable | ปิดปรับปรุง หรือคนเยอะจนรับไม่ไหว |
401 กับ 403 คนสับสนกันบ่อย ลองนึกถึงยามหน้าตึก 401 คือเราไม่ได้ยื่นบัตรเลย ยามไม่รู้ว่าเราเป็นใคร ส่วน 403 คือยื่นบัตรแล้ว ยามรู้ว่าเป็นใคร แต่บัตรนี้เข้าห้องนี้ไม่ได้ ส่วน 502 คำว่า "ตัวกลาง" (gateway หรือ proxy) คือเครื่องที่รับคำขอแล้วส่งต่อให้เครื่องข้างหลังอีกที เหมือนพนักงานหน้าร้านที่ไปถามครัวแล้วได้คำตอบที่ใช้ไม่ได้กลับมา
ดูตารางครบทุกเลขได้ที่ MDN: HTTP response status codes
เจอเลขนี้ ทำอะไรต่อ
เจอ 404
- เช็ก URL ทีละตัวอักษร โดยเฉพาะคำที่สะกดง่ายผิดง่าย
- ดูตัวพิมพ์เล็กใหญ่ บางเซิร์ฟเวอร์ถือว่า
/Aboutกับ/aboutเป็นคนละหน้า - ดูเครื่องหมาย
/ท้าย URL บางระบบ/menuกับ/menu/ไม่เหมือนกัน - ถ้าเป็น API ของเราเอง เช็กว่ามี route นั้นอยู่จริงในโค้ดฝั่งเซิร์ฟเวอร์
เจอ 401 หรือ 403
- ล็อกอินอยู่หรือเปล่า token หรือ API key แนบไปกับคำขอหรือยัง หมดอายุหรือยัง
- ถ้าเป็น 403 แปลว่าเซิร์ฟเวอร์รู้จักเราแล้ว ให้เช็กสิทธิ์ของบัญชีว่าเข้าถึงส่วนนี้ได้ไหม
เจอ 500
- ถ้าเป็นเซิร์ฟเวอร์ของเรา ให้ไปดู log ฝั่งเซิร์ฟเวอร์ ข้อความ error ตัวจริงอยู่ที่นั่น ไม่ได้อยู่ในเบราว์เซอร์
- ถ้าเป็นเว็บของคนอื่น เราแก้อะไรไม่ได้ รอสักพักแล้วลองใหม่
เจอ 503
- รอแล้วลองใหม่ และเปิดดูหน้าสถานะ (status page) ของผู้ให้บริการ มักบอกว่ากำลังปิดปรับปรุงหรือมีเหตุขัดข้องอยู่
ไม่ได้เลขอะไรกลับมาเลย
ถ้าไม่มี Status Code กลับมาเลย แปลว่าคำขอไปไม่ถึงเซิร์ฟเวอร์ตั้งแต่แรก ปัญหาจึงอยู่ก่อนหน้านั้น เช่น เน็ตหลุด หรือหาที่อยู่ของเว็บไม่เจอ ลองไล่เช็กด้วยวิธีในบทความ DNS คืออะไร? ดูชื่อเว็บกลายเป็น IP
เจอปัญหา ลองเช็กตามนี้
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| แท็บ Network ว่างเปล่า | เปิด DevTools หลังหน้าโหลดเสร็จ | กด F5 อีกครั้งตอนที่ Network เปิดอยู่ |
PowerShell ขึ้น error ตอนใช้ curl -I | curl เป็นชื่อเล่นของ Invoke-WebRequest | พิมพ์ curl.exe แทน |
fetch ขึ้น Failed to fetch | รันในแท็บเว็บอื่นจนติด CORS หรือเน็ตหลุด | รันใน Console ของแท็บ postman-echo.com |
res.json() ขึ้น Unexpected token '<' | คำตอบเป็นหน้า HTML เช่นหน้า 404 ไม่ใช่ JSON | เช็ก res.ok ก่อนเรียก res.json() |
| เห็น 304 เต็มไปหมด | เบราว์เซอร์ใช้ไฟล์ที่เก็บไว้ | เป็นเรื่องปกติ ไม่ต้องแก้ |
สรุป
- Client ส่ง Request ไป Server ตอบ Response กลับมา และบรรทัดแรกของคำตอบมี Status Code สามหลักเสมอ
- ดูเลขตัวแรก 2 คือสำเร็จ 3 คือไปที่อื่น 4 คือคำขอมีปัญหา 5 คือเซิร์ฟเวอร์มีปัญหา
- ดูเลขจริงได้ในแท็บ Network ของ DevTools,
curl -Iและ Postman fetchไม่ throw ตอนเจอ 404 หรือ 500 ต้องเช็กres.okเอง- 404 เช็ก URL, 401/403 เช็กการล็อกอินและสิทธิ์, 500 ดู log ฝั่งเซิร์ฟเวอร์, 503 รอแล้วลองใหม่
พร้อมแล้วก็ไปทำ Quiz ท้ายบทด้านล่างเพื่อรับ XP ได้เลยครับ