HTTP status code · Client errors (4xx)
418 I'm a teapot
418 I'm a teapot is a joke status code from RFC 2324, the 1998 April Fools' Hyper Text Coffee Pot Control Protocol, for a teapot asked to brew coffee. It is not part of HTTP; if you get one, the server is refusing your request on purpose, usually with a wink.
| Class | 4xx, Client errors |
|---|---|
| Defined in | RFC 9110 §15.5.19 |
| Cacheable by default | Only with explicit Cache-Control or Expires |
| Safe to retry | Pointless; the server is refusing on purpose, usually as a joke |
| Relevant headers | None specific to this code |
| Status | Deprecated: Reserved as "(Unused)" in RFC 9110 §15.5.19; not assignable to any real purpose. |
What 418 means
RFC 2324 defined HTCPCP for controlling coffee pots, and gave 418 to a teapot that refuses to brew coffee; RFC 7168 later extended the joke to tea. The code spread anyway: Node.js, Go (http.StatusTeapot) and Python (HTTPStatus.IM_A_TEAPOT) all know it, and Google has served a teapot page at google.com/teapot.
In 2017 a proposal to drop 418 from Node.js and Go met loud pushback. RFC 9110, section 15.5.19, settled it by marking 418 "(Unused)": it stays reserved in the IANA registry precisely because it has been deployed as a joke too widely to give it a real meaning.
Common causes
If you are visiting the site
- You reached an easter egg page or a developer joke endpoint.
- The site uses 418 as a playful way to refuse traffic it thinks is automated, such as a scraper or an unusual user agent.
If you run the server
- A route or firewall rule returns 418 deliberately; search your code and WAF rules for 418 or StatusTeapot.
- A mock server or test fixture uses 418 as an obviously fake status and it leaked into a real environment.
How to fix it
If you are visiting the site
- If you were blocked as a bot, try a normal browser without automation extensions or VPN; otherwise, enjoy the joke.
If you run the server
- For real refusals use a real code: 403 for a blocked client, 429 for rate limiting, 405 for an unsupported method. Monitoring and client libraries understand those.
How to send 418
app.post('/brew', (req, res) => {
res.status(418).json({ error: 'I\'m a teapot' });
});// app/brew/route.ts
export async function POST() {
return Response.json({ error: 'I\'m a teapot' }, { status: 418 });
}mux.HandleFunc("POST /brew", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusTeapot) // 418
w.Write([]byte(`{"error":"I'm a teapot"}`))
})from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.post("/brew")
def brew():
raise HTTPException(status_code=418, detail="I'm a teapot")location = /coffee {
return 418;
}Commonly confused with
- 418 vs 403
- 403 is the standard way to refuse a client; 418 is a joke that clients and monitoring treat only as a generic 4xx.
- 418 vs 405
- A teapot asked to brew coffee is, seriously speaking, a method the resource does not support: 405.
Frequently asked questions
- Is 418 a real HTTP status code?
- Not for HTTP. It comes from RFC 2324, an April Fools' RFC, and RFC 9110 lists 418 as "(Unused)" and reserved, so it can never be assigned a real meaning while the joke remains in use.
- Why did I get 418 from a website?
- The site returns it on purpose, either as an easter egg or to turn away traffic it considers automated. It carries no standard meaning beyond "request refused".
- Should my API return 418?
- No. Pick the standard code that describes the refusal, such as 403, 405 or 429, so clients, SDKs and monitoring can react correctly.
Last reviewed by Arielton Oberek.