418 (Unused)
Client error response defined by RFC 9110 §15.5.19.
Last updated July 27, 2026
Common causes at a glance
- A framework or demo route deliberately returning the teapot as an easter egg
- A WAF or bot filter using 418 as a deliberately meaningless rejection
- A test fixture exercising unknown-status handling that leaked into a real environment
- An HTCPCP implementation, which exists only as a joke
Reproduce it
curl -i https://api.example.com/v1/brewWhat 418 (Unused) means
Reservation is the whole meaning. The IANA registry marks 418 unusable so that no future revision of HTTP can give it a real definition and collide with a decade of joke handlers already deployed. A 418 carries no protocol semantics.
That has a consequence for API design. Middleware, retry logic, and monitoring treat 418 as an unrecognised 4xx and fall back to generic client-error handling, the defined behaviour for any unknown status in that class. Returning it for a real condition means callers cannot distinguish it from a bug, so pick a code that exists.
What the spec says
RFC 9110 §15.5.19 states the position directly: RFC 2324 was an April 1 RFC lampooning the ways HTTP was abused, one abuse being an application-specific 418, and it has been deployed as a joke often enough to be unusable for any future purpose. It is therefore reserved in the IANA HTTP Status Code Registry, with a note that it could be reassigned if the 4xx space is ever exhausted. The original definition is RFC 2324 §2.3.2, the Hyper Text Coffee Pot Control Protocol, extended for tea by RFC 7168. Neither is Standards Track.
Where the teapot actually shows up
Every 418 in the wild is intentional. The common sources are easter-egg routes shipped by web frameworks, tutorial code nobody removed, and bot mitigation layers answering suspected scrapers with a code carrying no information, on the theory that an unknown status reveals less than a 403 about why the request was blocked. It also turns up in test suites as a status no real handler produces, which occasionally escapes into staging. If you are emitting it, the honest alternatives are 403 for a refusal, 422 for content you understood and rejected, or 429 for rate limiting.
How to debug it
There is nothing to diagnose in the protocol, so the work is finding who
generated it. Check the Server header and body to distinguish an
application easter egg from an edge appliance:
curl -i https://api.example.com/v1/brew | head -20
If the origin returns 200 for the same path while the edge returns 418, a bot filter or
WAF rule is responsible and the rule needs adjusting rather than the application. If it
comes from your own stack, grep the codebase for the literal 418; the route
is usually a one-liner somebody added years ago. Client-side, treat any unrecognised 4xx
as non-retryable and log the status verbatim so the oddity stays visible. The
status code lookup confirms whether a code is registered before
you build behaviour around it.
Working examples
curl
# Nothing special about the request; 418 is entirely a server-side choice.
curl -i https://api.example.com/v1/brew | head -20
# Compare edge against origin to find out which layer invented it.
curl -i --resolve api.example.com:443:203.0.113.10 \
https://api.example.com/v1/brew | head -5
Python (requests)
import requests
resp = requests.get("https://api.example.com/v1/brew", timeout=10)
print(resp.status_code, resp.headers.get("Server"))
# 418 is reserved, so it carries no semantics. Do not build retry logic on it.
if resp.status_code == 418:
print("reserved status; treat as a generic 4xx and do not retry")
print(resp.text[:200])
resp.raise_for_status() # requests raises HTTPError like any other 4xx
Node (fetch)
const res = await fetch("https://api.example.com/v1/brew");
console.log(res.status, res.headers.get("server"));
// Generic 4xx handling is the correct treatment for any unregistered code.
if (!res.ok) {
const retryable = res.status === 408 || res.status === 429;
console.log(`status ${res.status}, retryable: ${retryable}`);
console.log((await res.text()).slice(0, 200));
}Reference and tooling
The authoritative list of assigned status codes is theIANA HTTP Status Code Registry. For a searchable copy with the semantics summarised, use theHTTP status code reference on this site. To see exactly what a server is sending, theheader inspector shows the raw status line and response headers, and thecurl builder assembles the request flags for you.
Other 4xx codes
- 400 Bad Request
- 401 Unauthorized
- 402 Payment Required
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 406 Not Acceptable
- 407 Proxy Authentication Required
- 408 Request Timeout
- 409 Conflict
- 410 Gone
- 411 Length Required
- 412 Precondition Failed
- 413 Content Too Large
- 414 URI Too Long
- 415 Unsupported Media Type
- 416 Range Not Satisfiable
- 417 Expectation Failed
- 419 Page Expired
- 421 Misdirected Request
- 422 Unprocessable Content
- 423 Locked
- 424 Failed Dependency
- 425 Too Early
- 426 Upgrade Required
- 428 Precondition Required
- 429 Too Many Requests
- 431 Request Header Fields Too Large
- 444 No Response
- 451 Unavailable For Legal Reasons
- 494 Request Header Too Large
- 495 SSL Certificate Error
- 496 SSL Certificate Required
- 497 HTTP Request Sent to HTTPS Port
- 499 Client Closed Request