Three Digits That Say Everything
You’ve seen 404. You’ve seen 500. You’ve probably seen 403 and had no idea what it meant. Maybe you’ve seen 301 in a URL bar and wondered why a website “moved.”
Those three-digit numbers are HTTP status codes, and they’re the entire vocabulary a server uses to tell the client what just happened. Once you know how to read them, every API error, every browser behaviour, every weird redirect, every “the site is broken” complaint — all of it becomes legible. you stop guessing.
This is one of the highest-leverage days in Module 1. Let’s take it properly.
The shape of a number
A status code is always three digits. The first digit tells you the class of the response — the general category of what happened. The last two tell you the specific outcome within that class.
4 0 4
│ │ │
│ └─┴── specific reason
└────── class (4xx = client error)
Five classes exist. Memorise them by digit:
| First digit | Class | Meaning |
|---|---|---|
| 1xx | Informational | “Hold on, still working on it” |
| 2xx | Success | “Done. Here’s what you asked for.” |
| 3xx | Redirection | “Not here. Try over there.” |
| 4xx | Client error | “You messed up the request.” |
| 5xx | Server error | “We messed up on our end.” |
HTTP status code — A three-digit integer in the status line of an HTTP response that indicates the outcome of the request. Defined by the HTTP specification and maintained in a public registry by IANA.
In plain terms: the server’s one-word summary of what happened — before any explanation.
HTTP needed a compact, machine-readable way for servers to communicate outcome without the client having to parse prose. A three-digit number does it in a way that’s fast, unambiguous, and works across every language and platform.
Think of it like a hospital triage system. The nurse doesn’t answer with a paragraph — she writes a code that tells everyone in the building what to do next. Status codes are the same: the server tells the client a code, and the client knows instantly how to react.
But a hospital triage code is about severity, while HTTP status codes are about responsibility — whose side of the conversation needs to act. That’s a distinction hospitals don’t have.
The 1xx family — the quiet ones
1xx codes are informational. They mean: “I received your request. Here’s a heads-up before I finish.”
You’ll almost never see these in normal browser traffic. But two exist worth knowing:
- 100 Continue — the server is telling the client: “I got the first part of your request. Keep sending the rest.” Used with large POSTs.
- 101 Switching Protocols — used when a connection upgrades, like switching from HTTP to WebSocket. You’ll meet this when we cover real-time communication.
For now: 1xx exists, it’s rare, and it means “hold on.”
The 2xx family — success
2xx codes mean the request worked. But “worked” isn’t one thing — the specific code tells you what kind of success.
200 OK
The most common code in the world. It means: the request succeeded, and here’s the result. Used for GETs, successful POSTs that return data, and most API responses.
201 Created
The request succeeded and a new resource was created. The response usually includes a Location header pointing to the new resource.
HTTP/1.1 201 Created
Location: /api/tasks/43
Use this when a POST creates something. A good API distinguishes 200 from 201 — it tells the client “something was made.”
204 No Content
The request succeeded, but there’s nothing to send back. Common with DELETE and some PUTs.
HTTP/1.1 204 No Content
There’s a status line and headers, but no body. Because there’s nothing to say. The action worked. Move on.
206 Partial Content
Used when the client asked for part of a resource — like requesting a specific byte range of a video. This is how streaming works. You don’t download the whole video at once; you ask for pieces, and the server replies with 206 for each piece.
200 OK — The standard response for a successful HTTP request; the meaning depends on the method: for GET it is the resource, for POST the result of the action.
In plain terms: “It worked. Here’s the answer.”
The specific codes under 2xx exist so clients can behave differently. A 201 tells a client “your new resource is at this URL — go fetch it.” A 204 tells a client “don’t wait for a body.” A 206 tells a video player “keep playing — more pieces are coming.” The class is the same; the behaviour is not.
A food delivery arriving at your door: the meal is here. That’s 200.
Except a delivery doesn’t tell you what kind of arrival it was. Did they hand it to you? Leave it at the door? Partial delivery with a second bag coming? The status code does.
The 3xx family — redirection
3xx codes mean: “What you asked for isn’t here — it’s somewhere else. Go there.”
This is where things get interesting, because redirects aren’t all the same, and the differences matter.
301 Moved Permanently
The resource has moved for good. The client should update its bookmarks and never ask this URL again.
Browsers and search engines cache 301s aggressively. Once you’ve received one, you’ll be redirected for a very long time. This is why SEO people are terrified of accidental 301s — they can be permanent in more ways than one.
302 Found
The resource is temporarily at a different URL. The client should redirect this time, but keep asking the original URL next time.
Before 2014, “302” was vague — different browsers interpreted it differently, sometimes changing the method of the redirected request. This is why 307 and 308 exist.
304 Not Modified
This one is special. The client asked: “Has this resource changed since the version I already have?” The server said: “No. Use your cached copy.”
A 304 has no body. It’s a way of saying “don’t waste bandwidth — you already have the answer.”
This is how caching works at the HTTP level. Your browser keeps a copy of a page or file, and on the next request, it sends a header like If-Modified-Since. If the resource hasn’t changed, the server sends 304, and the browser loads its cached copy instantly. No download.
307 and 308 — the method-preserving ones
- 307 Temporary Redirect — Like 302, but guarantees the request method will not change on the redirected request.
- 308 Permanent Redirect — Like 301, but guarantees the request method will not change on the redirected request.
The reason these exist: if you POST to a URL and get redirected with 301 or 302, some browsers convert your POST into a GET for the redirect — which breaks the semantics. 307 and 308 prevent that. The method stays the same; only the destination changes.
301 Moved Permanently — The target resource has been assigned a new permanent URI; clients should update their references.
In plain terms: “This thing has moved for good. Update your address book.”
Some URLs need to change — a rebranding, a restructure, a domain migration — and old links need to keep working. Redirects let a URL outlive the page it originally pointed to.
Changing your home address and leaving a forwarding order at the post office. Letters to the old address still arrive.
Except a post office forwarding order eventually expires. A 301 doesn’t — not unless you deliberately change the server configuration that produced it. Browsers will remember it forever.
The 4xx family — you messed up
4xx codes mean: “The problem is on your end, client. The request you sent was wrong in some way.”
This is the most relatable family because it’s the one that tells you what you did wrong.
400 Bad Request
The request is malformed — a syntax error in the protocol, a missing required field, invalid JSON. The server can’t even process it because the request itself is broken.
401 Unauthorized
Poorly named. It should be called Unauthenticated. It means: “You haven’t proven who you are.”
The client needs to authenticate — log in, send a token, include credentials. Without that, the server has no idea who’s asking.
403 Forbidden
The client has been authenticated, but isn’t allowed to do what they’re trying to do. You proved who you are — but you don’t have permission.
This is the classic 401 vs 403 confusion. Here’s the way to remember it:
401 — “Who are you?”
403 — “I know who you are. Still no.”
404 Not Found
The famous one. The URL doesn’t correspond to any resource on the server.
Fun fact: 404 is not just a status code — it’s a designed artifact. Tim Berners-Lee and the CERN team wanted a way for the web to say “this page doesn’t exist” without crashing the browser. Without 404, every missing link would have been a mystery. The code gave the web a way to fail gracefully.
The other famous detail: 404 pages are supposed to be a UX opportunity. Companies write personalised 404 pages, hide easter eggs, offer search bars. The original spec is just a code. The culture built around it is the industry.
405 Method Not Allowed
The URL exists, but not for the method you used. You tried POST on a URL that only accepts GET. Or you tried DELETE on something that can’t be deleted.
The response usually includes an Allow header listing what is permitted.
409 Conflict
The request conflicts with the current state of the resource. Classic example: two clients trying to update the same record at the same time. Or trying to create a username that’s already taken.
422 Unprocessable Entity
Used by many APIs (especially Rails and Laravel) to mean: the request parsed fine, but the data is semantically wrong. Wrong email format, password too short, date in the past when it should be future.
The distinction from 400: 400 means the request is malformed; 422 means it’s well-formed but semantically invalid.
429 Too Many Requests
You’re being rate-limited. The server is telling you: “Slow down.” Usually accompanied by a Retry-After header saying when you can try again.
404 Not Found — The server cannot find a current representation for the target resource, or is not willing to disclose that one exists.
In plain terms: “There’s nothing here at this address.”
The web needed a way to fail gracefully — a code that says “this doesn’t exist” without implying the server is broken. Without 404, missing pages would look like server failures.
Knocking on a door and nobody answers. Empty.
Except the door isn’t necessarily empty — the person might just not want to answer. That’s why 404 is sometimes used as a security measure: to hide the existence of resources you’re not allowed to access (instead of replying with 403, which would confirm they exist).
The 5xx family — we messed up
5xx codes mean: “The problem is on our end, server. Something broke while we were trying to process the request.”
This is the family that makes developers groan, because it means something went wrong in code you control. Or your infrastructure controls.
500 Internal Server Error
The catch-all. Something broke on the server and nobody handled it. This is the code for “I don’t know what happened but I can’t do what you asked.”
A 500 in production should trigger an alert. It means an unhandled exception reached the outer edge of your app.
502 Bad Gateway
The server acting as a gateway or proxy received an invalid response from an upstream server. In plain terms: the client connected to the front door, the front door tried to reach the kitchen, and the kitchen gave back garbage.
Common with reverse proxies like Nginx in front of a Node.js app. If the Node app crashes, Nginx returns 502.
503 Service Unavailable
The server is up, but it can’t handle the request right now — usually because it’s overloaded or under maintenance. The response often includes a Retry-After header.
504 Gateway Timeout
The gateway or proxy sent a request upstream, but the upstream server didn’t respond in time. Different from 502: 502 means the upstream gave back garbage; 504 means the upstream gave back nothing at all.
500 Internal Server Error — The server encountered an unexpected condition that prevented it from fulfilling the request.
In plain terms: “Something broke on our end. It’s not your fault.”
Servers need a way to distinguish “we broke” from “you broke it.” Without 5xx, every error would look like the client’s fault, and developers would spend forever debugging the wrong side of the connection.
A restaurant where the kitchen catches fire mid-order. The customer did nothing wrong — the meal just isn’t coming.
Except in real life, someone would run out and explain. In HTTP, a 500 might tell the client nothing about why it happened. The details go to the server logs, not to the response. This is deliberate — leaking internal errors to clients is a security risk.
The code you should never see in production (but do)
And then there’s the code that should not exist: 418 I’m a teapot.
A joke. A real one. Written into RFC 2324 in 1998 as an April Fools’ joke about the Hyper Text Coffee Pot Control Protocol (HTCPCP). The joke was: the server is a teapot, and you asked it to brew coffee. Hence, “I’m a teapot.”
But 418 escaped the joke. It became a symbol. Some servers actually return it. Some browsers display a hidden teapot animation on 418. It’s a small piece of cultural rebellion in a protocol that’s otherwise extremely serious.
The takeaway isn’t that 418 is useful. It’s that the web has a culture — a set of inside jokes and shared references that coders pass along. Knowing 418 exists is a way of saying: “I’m part of this.”
Backstory: where these numbers came from
HTTP didn’t invent status codes. It inherited them.
1985 — FTP gets three-digit reply codes. The File Transfer Protocol defined numeric codes to tell clients what happened. This was one of the first systems to use three digits with a class-based structure.
1991 — The first HTTP spec. When Tim Berners-Lee wrote the first HTTP specification, he borrowed the idea directly from FTP. Status codes like 200 and 404 appear in the very first version of the web.
1996 — HTTP 1.0 formalises them. The first broadly-supported HTTP spec, RFC 1945, defines the codes we still use today.
1997 — HTTP 1.1 expands the map. RFC 2068 (and later RFC 2616, and eventually the modern RFC 9110) fill in the gaps and formalise the classes.
1998 — 418 exists. The teapot joke becomes official in an RFC that itself is a joke.
2000s — Growing pains. As APIs proliferate, developers invent new codes for situations the spec didn’t anticipate. 422, 429, and others become de facto standards even before official recognition.
2010s — Consolidation. IANA maintains an official registry of status codes. Many ad-hoc codes get formalised. REST APIs settle on a subset of codes as best practice.
Today — The map is mostly stable. A handful of new codes (like 103 Early Hints, formalised in 2017) still appear, but the majority of codes you’ll use daily haven’t changed in decades. The three-digit class system from 1985 is still doing its job.
The codes worth memorising
You don’t need all 60+ registered codes in your head. But you should know these by heart:
Success (2xx)
- 200 — OK
- 201 — Created
- 204 — No Content
Redirect (3xx)
- 301 — Moved Permanently
- 302 — Found
- 304 — Not Modified
Client error (4xx)
- 400 — Bad Request
- 401 — Unauthorized (you haven’t identified yourself)
- 403 — Forbidden (you’ve identified yourself but you’re not allowed)
- 404 — Not Found
- 405 — Method Not Allowed
- 409 — Conflict
- 422 — Unprocessable Entity
- 429 — Too Many Requests
Server error (5xx)
- 500 — Internal Server Error
- 502 — Bad Gateway
- 503 — Service Unavailable
- 504 — Gateway Timeout
Eighteen codes. An afternoon of study. A lifetime of usefulness.
What you’d say in the room
If an interviewer asks “the API returned 500 — whose fault is it?” — here’s the answer:
A 500 means the server hit an unexpected condition — an unhandled exception in application code. It is, by definition, a server-side problem, not a client problem. But the code alone doesn’t say where on the server: 500 points at the application, 502 and 504 point at the proxy’s view of the application (garbage response, or silence), and 503 usually means capacity or maintenance rather than a bug. The first debugging step is the logs, not the client.
If an interviewer asks “what’s the difference between 401 and 403?” — here’s the answer:
401 means the client has not authenticated — the server doesn’t know who is asking, so the fix is credentials. 403 means the client is authenticated but not authorised — identity is established, permission is denied, and no amount of re-logging-in will change it. One sentence: 401 is who you are; 403 is what you can do.
Say it like a professional
The definitions from today, in one block. Say each out loud. If you stumble, go back.
- HTTP status code — A three-digit integer in the status line of an HTTP response that indicates the outcome of the request. Defined by the HTTP specification and maintained in a public registry by IANA.
- 200 OK — The standard response for a successful HTTP request; the meaning depends on the method: for GET it is the resource, for POST the result of the action.
- 201 Created — The request succeeded and a new resource was created, usually with a Location header pointing to the new resource.
- 204 No Content — The request succeeded, but there is no body to return.
- 301 Moved Permanently — The target resource has been assigned a new permanent URI; clients should update their references.
- 302 Found — The target resource resides temporarily under a different URI.
- 304 Not Modified — The resource has not been modified since the version the client already has, so the client should use its cached copy.
- 307 Temporary Redirect — Like 302, but guarantees the request method will not change on the redirected request.
- 308 Permanent Redirect — Like 301, but guarantees the request method will not change on the redirected request.
- 400 Bad Request — The server cannot process the request due to a client error, such as malformed syntax.
- 401 Unauthorized — The client has not provided valid authentication credentials; the request lacks proven identity.
- 403 Forbidden — The server understood the request but refuses to authorize it; identity may be proven but permission is denied.
- 404 Not Found — The server cannot find a current representation for the target resource, or is not willing to disclose that one exists.
- 405 Method Not Allowed — The method specified in the request-line is not allowed for the target resource.
- 409 Conflict — The request conflicts with the current state of the target resource.
- 422 Unprocessable Entity — The request is well-formed but contains semantically invalid data.
- 429 Too Many Requests — The client has sent too many requests in a given amount of time, typically accompanied by a Retry-After header.
- 500 Internal Server Error — The server encountered an unexpected condition that prevented it from fulfilling the request.
- 502 Bad Gateway — The server, acting as a gateway or proxy, received an invalid response from an upstream server.
- 503 Service Unavailable — The server is currently unable to handle the request due to overload or maintenance.
- 504 Gateway Timeout — The server, acting as a gateway or proxy, did not receive a timely response from an upstream server.
Close the tab
Reproduce these from memory. Then reopen and check.
- What do the five first-digit classes mean?
- What’s the difference between 200, 201, and 204?
- What’s a 304, and why does it exist?
- What’s the difference between 301 and 302? And between 307 and 308?
- Explain 401 vs 403 in one sentence.
- What’s the difference between 400 and 422?
- What does 429 mean, and what header usually accompanies it?
- What’s the difference between 500, 502, 503, and 504?
- What is 418, and why does it exist?
- Where did HTTP status codes originally come from?
If you can answer all ten without peeking, Day 6 is done. If not, read those sections again.
Tomorrow
You now know how a request is shaped, what verb says what you want, and what number says what happened. But there’s a piece we’ve glossed over every single day: the URL itself.
You’ve typed them. You’ve shared them. You’ve probably never stopped to think about how readunderstory.ink actually becomes a server that answers. That’s DNS — the internet’s phone book. And tomorrow, we’re going to watch a domain name transform into an IP address, one lookup at a time, and meet the caching layers that make the whole thing feel instant.
Close the loop
0/3 sentences