---
title: HTTP Status Codes Explained: what 404, 500 and 503 really mean
description: Every status code is your server trying to tell you something. Here's a plain-English guide to the ones you'll actually meet — what they mean, whose fault they are, and what to do about each.
canonical: https://watchfor.io/blog/http-status-codes-explained
---

# HTTP Status Codes Explained: what 404, 500 and 503 really mean

2026-06-22 · WatchFor Team · Networking · http, debugging, basics

Every status code is your server trying to tell you something. Here's a plain-English guide to the ones you'll actually meet — what they mean, whose fault they are, and what to do about each.

You push a deploy, refresh the page, and there it is in ugly grey letters: **502 Bad Gateway**. Your stomach drops. Is it the server? The load balancer? The code? The internet itself?

Here's the good news: that number isn't random. Every HTTP status code is your server (or something between you and it) trying to tell you *exactly* what went wrong — if you know how to read it. Learn the handful that matter and you'll diagnose problems in seconds instead of panicking.

## The five families

Every status code is a three-digit number, and the **first digit** tells you the category. Get this and you're already halfway there:

| Range | Family | Rough meaning |
| --- | --- | --- |
| **1xx** | Informational | "Hold on, still working." (You'll rarely see these.) |
| **2xx** | Success | "Here you go." Everything worked. |
| **3xx** | Redirection | "It moved — look over there instead." |
| **4xx** | Client error | "*You* sent something wrong." |
| **5xx** | Server error | "*I* messed up." |

> **The single most useful distinction:** **4xx is your fault, 5xx is the server's fault.** A 404 means the browser asked for something that isn't there; a 500 means the server fell over trying to answer. That one rule points your debugging in the right direction immediately.

## The codes you'll actually meet

You don't need all 70-odd codes. You need these.

### Success and redirects

| Code | Name | What it means |
| --- | --- | --- |
| **200** | OK | The request worked. The happy path. |
| **201** | Created | Your POST created something (common in APIs). |
| **204** | No Content | Worked, but there's nothing to send back. |
| **301** | Moved Permanently | This URL has a new home — forever. Search engines update accordingly. |
| **302** | Found (temporary redirect) | Moved for now; keep using the old URL. |
| **304** | Not Modified | "Nothing changed, use your cached copy." A speed win. |

### Client errors (4xx)

| Code | Name | What it usually means | What to check |
| --- | --- | --- | --- |
| **400** | Bad Request | Malformed request the server can't parse | Your payload, syntax, params |
| **401** | Unauthorized | You're not logged in / no valid credentials | Auth token, login |
| **403** | Forbidden | You're known, but not allowed | Permissions, IP allowlists |
| **404** | Not Found | That URL doesn't exist | The path, typos, deleted pages |
| **429** | Too Many Requests | You're being rate-limited | Slow down, back off and retry |

### Server errors (5xx)

| Code | Name | What it usually means | Likely culprit |
| --- | --- | --- | --- |
| **500** | Internal Server Error | The app crashed handling the request | A bug, an unhandled exception |
| **502** | Bad Gateway | A proxy got a junk response from upstream | App down behind the load balancer |
| **503** | Service Unavailable | Server is up but can't serve right now | Overload, or maintenance mode |
| **504** | Gateway Timeout | Upstream took too long to respond | A slow app, DB or dependency |

## The 5xx trio that causes the most panic

**500, 502, 503 and 504** look similar but tell very different stories:

- **500** — your application *itself* threw an error. Check your logs; there's almost always a stack trace.
- **502** — something in front of your app (a proxy, load balancer, CDN) tried to reach it and got nothing usable. Usually your app crashed or isn't listening.
- **503** — the server is alive and answering, but deliberately saying "not now" — often overload or a maintenance page.
- **504** — the front layer waited for your app and gave up. Your app (or a database/third-party it calls) is too slow.

> **A quick mental shortcut:** 502 = "the thing behind me is **dead**", 504 = "the thing behind me is **slow**". That distinction alone saves a lot of wrong turns.

## Why this matters for monitoring

Status codes are the backbone of uptime monitoring. When a monitor checks your site, the code is the first thing it reads:

- A **2xx** is treated as healthy.
- A **4xx** or **5xx** can be treated as down — though a good setup lets you decide (a 401 on a protected endpoint might be *expected*).
- Sudden **5xx** spikes are the classic signal of a real outage.

But there's a trap: a page can return **200 OK** and still be broken — a blank page, an error rendered in the body, the wrong content entirely. That's why solid monitoring pairs the status code with a **keyword (body) check**, so "200 but broken" still counts as down.

## The bottom line

| If you remember one thing… | …make it this |
| --- | --- |
| First digit | tells you the family: 2 good, 3 moved, 4 your fault, 5 server's fault. |
| 4xx vs 5xx | points your debugging in the right direction instantly. |
| 502 vs 504 | "dead upstream" vs "slow upstream". |
| 200 isn't enough | pair status checks with a content check to catch "200 but broken". |

Status codes feel cryptic until they don't. Once these click, that grey **502** stops being a mystery and starts being a map.

Want something watching your status codes around the clock? Our [HTTP monitoring guide](/docs/monitors/web) shows how to alert on the right ones — and you can inspect any URL's response right now with the free [HTTP header checker](/http-header-checker).

---

Canonical page: https://watchfor.io/blog/http-status-codes-explained · All articles: https://watchfor.io/blog/all.md · Site guide: https://watchfor.io/llms.txt
