428 Precondition Required

HTTP response status code 428 Precondition Required is returned by the server to indicate HTTP requests of this type must be made conditionally, yet no precondition was included.

Usage

The 428 Precondition Required status code signals the server expects HTTP requests of this type to be conditional and include an appropriate HTTP header such as If-Match, If-None-Match, If-Modified-Since, and If-Unmodified-Since.

These HTTP headers are optionally used by clients when supported by the server, but in this case, the server requires their use. Depending on the use case, this is intended to reduce instances of data loss such as the "lost update" problem.

A lost update occurs when a client uses GET to obtain a resource, modifies the resource, and uses PUT to send the modified version back to the server. Without third-party interference, there is no problem. If after the initial GET a third party modified the state of the resource on the server, a conflict arises. If the client uses PUT without first checking the state of the resource, the third party's update is overwritten (a lost update).

By enforcing conditional tests using ETags and dates, the opportunities for clients to overwrite updates are lowered because fewer assumptions are made about the state of the resource.

This is related to the 412 Precondition Failed response, sent by the server when one or more of the conditions does not pass.

SEO impact

Search engines like Google will not index a URL with a 428 response status. Previously indexed URLs returning this status code will be removed from search results.

Example

The client had previously obtained a copy of the resource and has since modified the local copy. When the client attempts to PUT the resource and update the server, the server responds with 428 Precondition Required because the HTTP headers did not include a conditional test.

Request

PUT /reservations.txt HTTP/1.1
Host: www.example.re

Response

HTTP/1.1 428 Precondition Required
Content-Type: text/html
Content-Length: 193

<html>
  <head>
    <title>Conditional Update Required</title>
  </head>
  <body>
   <p>This PUT request must be done conditionally.
   Try again using If-Unmodified-Since.</p>
  </body>
</html>

How to fix

Fetch the resource with a GET request first and extract the ETag value from the response headers. Then re-send the modifying request (PUT, PATCH, or DELETE) with an If-Match header set to the retrieved ETag value.

Alternatively, use the If-Unmodified-Since header with the Last-Modified date from the initial GET response. The server compares the date and proceeds only if the resource has not changed since.

The ETag approach is more precise. Timestamps have second-level granularity and miss rapid successive edits. ETags change on every modification regardless of timing.

Make sure the GET used to retrieve the ETag targets the same resource as the subsequent modifying request. Using an ETag from a different record triggers a 412 Precondition Failed response.

APIs built on SAP, Salesforce, and similar platforms commonly enforce conditional requests on update and delete operations. Check the API documentation for which endpoints require preconditions and which validator headers are accepted.

On the server side, the 428 response helps prevent the "lost update" problem, where two clients editing the same resource overwrite each other. Including ETag headers on all mutable resources gives clients the values they need for conditional requests.

Code references

.NET

HttpStatusCode.PreconditionRequired

Rust

http::StatusCode::PRECONDITION_REQUIRED

Rails

:precondition_required

Go

http.StatusPreconditionRequired

Symfony

Response::HTTP_PRECONDITION_REQUIRED

Python3.5+

http.HTTPStatus.PRECONDITION_REQUIRED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_PRECONDITION_REQUIRED

Angular

@angular/common/http/HttpStatusCode.PreconditionRequired

Takeaway

The 428 Precondition Required status code is a client error sent by the server when the client needs to submit the HTTP request conditionally, but no appropriate HTTP header was part of the request. The client needs to add the precondition and resubmit.

See also

Last updated: March 5, 2026