428 Precondition Required

The request must be conditional.

When to use it

Requiring If-Match on updates to avoid lost writes.

Common causes and fixes

428 tells the client the server only accepts conditional requests here: send If-Match with the ETag you last read, so concurrent edits can’t silently overwrite each other, the lost update problem. A client that gets 428 should GET the resource, take its ETag header and resend the PUT or PATCH with If-Match. If the ETag is stale by then, the answer is 412.

As an API designer, require it only where lost updates matter, and document it, because most HTTP clients never send conditional headers on their own. Return the current ETag on every GET and successful write. Proxies don’t generate 428; it always comes from the application. Make sure CDNs and compression don’t rewrite ETags, or If-Match will never match.

Client error (4xx)

4xx codes are client errors: the request itself is wrong, unauthorised or points at something that isn’t there. Retrying the same request won’t help.

What it looks like

HTTP/1.1 428 Precondition Required

How to send it

Node.js / Expressres.status(428).end()
Python / Flaskreturn '', 428
nginxreturn 428;

How to check it

curl -s -o /dev/null -w "%{http_code}\n" https://example.com/

Open HTTP Status Codes