developer · · Updated
HTTP Status Codes You Will Actually See, From One Real Site
By Chirag
Lists of HTTP status codes are easy to find. What's harder to picture is which ones a real site actually sends, and why. On 26 September 2026 this site, plus the two outside services it talks to, were probed with curl, and between them they returned eight different status codes. Each one below is a real response, and each teaches something a list doesn't.
What came back
| Request | Status | What it means here |
|---|---|---|
http://devbiztoolshub.com/about | 301 Moved Permanently → https://www.devbiztoolshub.com/about | Old protocol and the bare domain both redirect, in one hop |
https://www.devbiztoolshub.com/about/ | 308 Permanent Redirect → /about | The trailing-slash form redirects to the canonical URL |
https://www.devbiztoolshub.com/about | 200 OK | The page itself |
https://www.devbiztoolshub.com/does-not-exist | 404 Not Found | A real 404, with an error page as the body |
POST https://www.devbiztoolshub.com/about | 405 Method Not Allowed | A static page can't accept a form post |
A hashed JavaScript file, sent with If-None-Match | 304 Not Modified | The browser's cached copy is still current |
POST /api/track (the page-view counter) | 204 No Content | Counted; nothing to send back |
GET /api/track | 404 Not Found | Only POST is handled; a GET falls through to the 404 page |
Two outside services added three more:
| Request | Status |
|---|---|
https://api.frankfurter.app/latest?from=USD&to=INR (exchange rates, old address) | 301 → https://api.frankfurter.dev/v1/latest?... |
| Formspree contact form, posted empty | 400 Bad Request, body {"error":"Can't send an empty form"} |
| Formspree, posted to a form ID that doesn't exist | 404 Not Found, body {"error":"Form not found"} |
301 and 308: both permanent, not identical
Both tell browsers and search engines that the resource has a new permanent address, and Google treats them the same way for indexing. The difference is the request method. With a 301, clients are allowed to turn a POST into a GET when they follow the redirect, and browsers do. With a 308, the method and body must be repeated unchanged (RFC 9110). For page URLs that only ever receive GETs, either works. For an API endpoint that receives form posts, a 301 can silently turn a submission into an empty GET.
Notice the 308's Location header was just /about, a path rather than a full URL. That's allowed: clients resolve it against the URL they requested.
When a redirect breaks the request: CORS
The exchange-rate service used to live at api.frankfurter.app. That address now answers with a 301 to api.frankfurter.dev, but the redirect response carries no Access-Control-Allow-Origin header. A browser making a cross-origin fetch checks CORS on every response in the chain, including redirects. So the request failed in the browser with a CORS error, while the same URL worked perfectly from curl, which doesn't enforce CORS. This site's currency converter fell back to an old rate for exactly this reason until it was pointed at the new address. When an API call fails in the browser but not in curl, check the redirect chain for missing CORS headers.
304: the fastest response is no body
The JavaScript file came back with an ETag, an identifier for that exact version of the file. Sending the ETag back in If-None-Match got a 304 and no body: the server confirmed the browser's copy was current without resending it. That file also had Cache-Control: public, max-age=31536000, immutable: its name contains a hash of its contents, so a new version always gets a new name, and the old one can be cached for a year. The HTML pages have no ETag and a one-hour max-age, so a browser checks for a new version at most an hour later.
204 and the empty-body trap
A 204 means success with nothing to return. Calling response.json() on it throws Unexpected end of JSON input in Chrome, because an empty body isn't JSON. Check the status before parsing. The common JSON errors guide lists what each browser says for this and other parse failures.
400 vs 404 from an API
Formspree used both codes precisely. An empty submission to a real form is the client's fault in a way the server can describe (400, "Can't send an empty form"); a submission to a form ID that doesn't exist is 404. Both came with a JSON body naming the problem, which is what makes an API pleasant to debug. A bare status code tells you less.
405 without an Allow header
The POST to a page got 405, the right code. RFC 9110 says a 405 must include an Allow header listing the methods that would work, but this one didn't; Cloudflare's static hosting leaves it out. The counter endpoint shows the other common behaviour: a GET to a URL that only handles POST came back as 404, not 405. Many frameworks answer that way, so a 404 on an API call can mean "wrong method" as well as "wrong URL".
404 is only honest if it is a 404
A made-up URL on this site returns a real 404 status with an error page as the body. A site that shows its error page with a 200 status (a "soft 404") tells search engines the page exists; Google then has to guess from the content, reports such URLs as soft 404s in Search Console, and leaves them out of results. curl -I on a nonsense URL shows the true status in a second.
To look up a code you haven't met yet, the HTTP Status Code Reference lists the common ones by class, with a search box.
Related guides
- camelCase, snake_case, kebab-case and Title Case: Which Goes Where · The naming convention each language, database and URL expects, the PostgreSQL quirk that breaks camelCase columns, and what automatic case conversion does to acronyms like XMLHttpRequest and names like iPhone.
- Understanding UUIDs — What They Are and Why Developers Use Them · Why UUIDs are used instead of auto-incrementing IDs, what the version number means, and when a UUID is (or isn't) the right choice.
- On-Page SEO Basics: Meta Tags, Robots.txt, and Favicons · The technical basics that decide how a page appears in search and link previews: title, description and canonical tags, what robots.txt can and can't do, and the favicon sizes search engines actually use.