POST

When a client needs to submit data for server-side processing, it sends an HTTP POST request.

Usage

A POST request submits an entity to the specified resource. The server determines how to handle the enclosed representation based on the resource's own semantics. Unlike PUT, which targets a specific resource URI, POST delegates processing to the resource identified by the target URI.

The Content-Type header indicates the format of the request body. Three encodings are common in HTML forms and APIs.

application/x-www-form-urlencoded

The default encoding for HTML forms. Data is structured as key-value pairs separated by ampersands (&), with keys and values joined by equals signs (=). Non-alphanumeric characters use Percent-Encoding.

name=Alice&role=admin

multipart/form-data

Each field occupies a separate part delimited by a boundary string declared in the Content-Type header. This encoding supports binary data such as file uploads. The Content-Disposition header within each part names the field.

text/plain

HTML forms encode each field as name=value on a line of its own, separated by CRLF. The format carries no escaping rules, so values containing newlines or = arrive ambiguous, one reason the other two encodings dominate.

Repeated POST requests are not idempotent. Submitting the same form twice creates two resources or triggers processing twice, unlike PUT where a repeated request produces the same server state.

POST responses are cacheable only when the response includes explicit freshness information and a matching Content-Location header.

Properties

Property Value
Safe No
Idempotent No
Cacheable Conditional

Example

Form submission

A client submits form data using URL-encoded format. The server creates a job and responds with 201 Created.

Request

POST /jobs HTTP/1.1
Host: api.example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 17

name=backup&pri=2

Response

HTTP/1.1 201 Created
Location: /jobs/47
Content-Type: application/json
Content-Length: 38

{"id":47,"name":"backup","priority":2}

Multipart file upload

A client uploads a file using multipart encoding. The boundary string ----Boundary separates each part. The server accepts the upload and returns 202 Accepted.

Request

POST /uploads HTTP/1.1
Host: api.example.re
Content-Type: multipart/form-data; boundary=----Boundary
Content-Length: 353

------Boundary
Content-Disposition: form-data; name="title"

Q4 Report
------Boundary
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdf

<152 bytes of PDF data>
------Boundary--

Response

HTTP/1.1 202 Accepted
Location: /uploads/91
Content-Length: 0

JSON API

A client sends a JSON payload to create a new user. The server returns the created resource with an id field.

Request

POST /users HTTP/1.1
Host: api.example.re
Content-Type: application/json
Content-Length: 41

{"email":"alice@example.re","role":"ops"}

Response

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 50

{"id":112,"email":"alice@example.re","role":"ops"}

CORS

POST is a CORS-safelisted method, so the method itself never triggers a preflight. The request headers decide: a Content-Type of application/x-www-form-urlencoded, multipart/form-data, or text/plain is safelisted and the request goes out directly. A POST with application/json or any other content type carries a non-safelisted Content-Type header and triggers a preflight OPTIONS request.

Caches and POST

A successful POST invalidates what caches hold for the target URI. Any non-error status code in response to an unsafe method forces intervening caches to drop their stored responses for the URI, and caches also treat URIs named in Location and Content-Location as invalidation candidates. A POST creating a resource therefore clears the stale GET copy of the same address on the way through.

POST vs GET

POST carries data in the request body rather than the URL. This keeps parameters out of browser history, server logs, and Referer headers, making POST better suited for sensitive data.

POST responses are not cached by default and are not bookmarkable. POST is neither safe nor idempotent, so repeated submissions create duplicate resources or trigger processing multiple times.

The protocol imposes no body size limit on POST, though server configurations cap request body sizes in practice. GET carries data in the URL, where server and proxy request-line and header caps, commonly around 8 KB, set the practical bound.

A read-only query needing a body sits between the two methods, and QUERY now fills the slot: body semantics like POST, safety and cacheability like GET.

Cookies with SameSite=Lax are withheld from cross-site POST requests but sent on cross-site top-level GET navigations. This gives POST a degree of built-in CSRF protection that GET lacks.

Security

POST data does not appear in URLs, browser history, or Referer headers. This reduces the risk of accidental data exposure compared to GET.

POST is still vulnerable to CSRF attacks without proper tokens. Forms on malicious pages submit POST requests to other origins automatically. SameSite=Lax cookies provide partial protection by blocking cross-site POST cookie transmission, but dedicated CSRF tokens remain necessary.

POST over plain HTTP transmits data as cleartext. HTTPS is required to protect the request body in transit.

POST vs PUT

PUT replaces the resource at the target URI with the request body, and repeating the request repeats the same replacement, so PUT is idempotent. POST hands the body to the target resource for processing, and the server decides the outcome, commonly creating a subordinate resource at a new URI. The choice follows URI ownership: a client knowing the final address uses PUT on the address, while a client posting to a collection lets the server mint the address and answer 201 with a Location header.

POST vs PATCH

POST creates new resources at server-chosen URIs. PATCH modifies existing resources at known URIs.

POST delegates processing semantics entirely to the server. PATCH has defined patch formats such as JSON Patch and JSON Merge Patch that describe specific modifications to apply.

When a client needs to update specific fields on an existing resource, PATCH is the appropriate method. POST is for creating new resources or triggering server-side processing.

See also

Last updated: August 18, 2026