Skip to content

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.

Facts about this status code
Class4xx, Client errors
Defined inRFC 9110 §15.5.19
Cacheable by defaultOnly with explicit Cache-Control or Expires
Safe to retryPointless; the server is refusing on purpose, usually as a joke
Relevant headersNone specific to this code
StatusDeprecated: 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

Express (Node.js)
app.post('/brew', (req, res) => {
  res.status(418).json({ error: 'I\'m a teapot' });
});
Next.js App Router route handler
// app/brew/route.ts
export async function POST() {
  return Response.json({ error: 'I\'m a teapot' }, { status: 418 });
}
Go net/http
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"}`))
})
Python FastAPI
from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.post("/brew")
def brew():
    raise HTTPException(status_code=418, detail="I'm a teapot")
Nginx
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.