The methods at a glance
RFC 9110 defines eight methods, and RFC 5789 adds PATCH. The standard requires every general-purpose server to support GET and HEAD; all the others are optional. Each method has three properties that decide how the rest of the web treats it:
| Method | Asks the server to | Safe | Idempotent | Cacheable |
|---|---|---|---|---|
| GET | Transfer a current representation of the resource | Yes | Yes | Yes |
| HEAD | Same as GET, without the response content | Yes | Yes | Yes |
| POST | Have the resource process the request content | No | No | Only with explicit freshness |
| PUT | Create or replace the resource with the request content | No | Yes | No |
| PATCH | Apply a set of changes to the resource | No | No | Only with explicit freshness |
| DELETE | Remove the resource's association with its current function | No | Yes | No |
| OPTIONS | Describe the communication options for the resource | Yes | Yes | No |
| TRACE | Loop the message back along the path, for testing | Yes | Yes | No |
| CONNECT | Open a tunnel to the server through a proxy | No | No | No |
Safe: read-only by definition
RFC 9110 calls a method safe when its semantics are essentially read-only: the client does not request, and does not expect, any change on the server. GET, HEAD, OPTIONS and TRACE are safe. The server may still write a log line or count a view; what matters is that the client did not ask for it.
The reason for the distinction is automation. Search engine crawlers, link checkers and browsers that prefetch pages follow GET links freely, because GET is supposed to be harmless. The RFC gives a warning example: a content tool that deletes pages through a link like page?do=delete. If that works with GET, the first crawler that follows every link empties the site. The RFC says the owner must disable such an action for safe methods. Anything that changes data belongs behind POST, PUT, PATCH or DELETE.
Idempotent: safe to repeat
A method is idempotent when sending the same request several times has the same intended effect as sending it once. PUT, DELETE and all safe methods qualify. Deleting order 42 twice leaves it deleted; putting the same address twice leaves the same address.
This decides what happens when a connection drops before the answer arrives. RFC 9110 says a client can retry an idempotent request, and should not automatically retry a non-idempotent one unless it knows the request is safe to repeat. A proxy must never retry one automatically. A POST that places an order is the classic case: sent twice, it can place two orders.
Cacheable: mostly GET
RFC 9110 defines caching for GET, HEAD and POST, and notes that most caches only support GET and HEAD. It also says outright that responses to PUT, DELETE, OPTIONS, TRACE and CONNECT are not cacheable. A POST response is cacheable only with explicit freshness information and a Content-Location equal to the request URL, and it can then only answer a later GET or HEAD, never another POST. In practice, if you want something cached, serve it with GET and set Cache-Control, as the Cache-Control guide explains.
One resource, five requests
An API for orders shows the methods side by side:
GET /orders list orders
POST /orders create an order, server picks the ID
GET /orders/42 read order 42
PUT /orders/42 replace order 42 with the body
PATCH /orders/42 change some fields of order 42
DELETE /orders/42 remove order 42 Note the difference between POST and PUT for creating. POST goes to the collection and the server assigns the new URL. PUT goes to the exact URL the client chose; repeating it does not create a second resource. RFC 9110 also says what a server should answer:
| Situation | Status | Detail |
|---|---|---|
| POST that creates | 201 Created | Location header with the new resource's URL |
| PUT that creates | 201 Created | Required when the resource did not exist |
| PUT that replaces | 200 OK or 204 No Content | Required when it existed and was changed |
| DELETE, done | 204 No Content or 200 OK | 200 if the response describes the result |
| DELETE, queued | 202 Accepted | Will likely succeed but has not happened yet |
| Method not allowed here | 405 Method Not Allowed | Must carry an Allow header listing the methods |
| Method unknown to the server | 501 Not Implemented | Recommended by the spec |
The HTTP status codes guide covers the rest of the list, including 303 See Other, which RFC 9110 suggests when a POST would produce something that already exists.
GET or POST in an HTML form
An HTML form uses GET unless it says otherwise. MDN describes the two: with method="get" the form data is appended to the action URL after a ?, and with method="post" it is sent as the request body, encoded as application/x-www-form-urlencoded by default, or multipart/form-data when the form uploads files. A search form is a good GET form:
GET /search?q=red+shoes&size=9 The result has its own URL, so it can be bookmarked, shared and cached, and repeating it changes nothing. The URL encoder and decoder shows how spaces and special characters are written in that query string.
Use POST when the form changes something, such as a sign-up, a comment or a payment, or when it carries data that should not sit in a URL. RFC 9110 notes that data placed in a URL can be inappropriate to disclose and suggests POST for it, since URLs end up in browser history, server logs and shared links. There is also a size question. RFC 9110 only recommends that software support URLs of at least 8000 octets, so long data belongs in a body.
HEAD and OPTIONS: the quiet two
HEAD is GET without the body. RFC 9110 says the server must not send content in the response, and should send the same header fields it would send for GET. The RFC names its typical uses: testing links and finding recent modifications. A link checker can confirm thousands of URLs answer 200 without downloading a single page, and a script can read Content-Length or Last-Modified before deciding whether to fetch a large file.
OPTIONS asks what a resource supports without asking it to do anything. RFC 9110 describes it as a way to learn the options or requirements of a resource, or the capabilities of a server, without implying a resource action. An OPTIONS request with * as its target applies to the server as a whole. Browsers send it on their own for CORS preflights, which is where most developers first meet it.
Methods in the browser
JavaScript can send any method with fetch(), but cross-origin requests with PUT, PATCH or DELETE trigger a preflight: the browser first asks the server with OPTIONS whether the method is allowed. The CORS guide explains what the server has to answer. A route that only knows GET and POST can answer that OPTIONS request with 405, and RFC 9110 requires a 405 response to include an Allow header listing the methods that do work. The HTTP header checker shows that header along with the status code.
Rules of thumb
- Reading data: GET. Never change anything in response to a GET.
- Creating with a server-chosen ID, or running an action: POST.
- Writing the full resource at a known URL: PUT. Partial update: PATCH.
- Removing: DELETE, answered with 204 when there is nothing more to say.
- Passwords and personal data: POST over HTTPS, never in a URL.
Frequently asked questions
What is the difference between GET and POST?
GET asks for a resource and is defined as safe: the client does not request any change on the server. POST sends content for the server to process, for example a form or a new order, and may change things. GET responses are cacheable and GET form data ends up in the URL; POST data goes in the request body.
Can a GET request have a body?
Technically a message can carry one, but RFC 9110 says content in a GET request has no generally defined semantics, cannot change the meaning of the request, and may make some implementations reject the request. Clients should not send it unless the server has said it supports it. Put parameters in the query string instead.
What does idempotent mean?
Sending the same request several times has the same intended effect as sending it once. RFC 9110 lists PUT, DELETE and the safe methods as idempotent. That matters for retries: if the connection drops before the answer arrives, a client may safely send a PUT again, but should not resend a POST unless it knows the request is safe to repeat.
When should I use PUT instead of PATCH?
PUT replaces the whole resource with what you send, so a second identical PUT changes nothing. PATCH, defined in RFC 5789, sends a set of changes, which RFC 5789 says is neither safe nor idempotent, because applying the same change twice can give a different result, such as adding an item twice. Use PUT when you have the full new state and PATCH for partial updates.
Is POST more secure than GET?
Neither method encrypts anything; HTTPS does that for both. The difference is where data travels. GET form data goes into the URL, which can end up in logs, history and bookmarks, so RFC 9110 suggests POST for sensitive information that would be inappropriate in a URI. Passwords and personal data should always go in a POST body over HTTPS.
Sources
- RFC 9110, HTTP Semantics, section 9 (the method table; GET and HEAD required, others optional; 405 and 501 for disallowed or unknown methods; safe methods GET, HEAD, OPTIONS, TRACE; idempotent methods PUT, DELETE and the safe ones; retry rules; caching defined for GET, HEAD and POST; content in GET has no defined semantics; POST and 201 with Location; PUT and 201, 200 or 204; DELETE and 202, 204 or 200; POST for sensitive data)
- RFC 9110, section 4.1 (support for URIs of at least 8000 octets recommended) and section 15.5.6 (405 must include an Allow header)
- RFC 5789, PATCH Method for HTTP (a set of changes in a patch document; PATCH is neither safe nor idempotent; a response is only cacheable with explicit freshness information)
- MDN Web Docs: Cross-Origin Resource Sharing (simple requests allow GET, HEAD and POST; other methods are preflighted with an OPTIONS request)
- MDN Web Docs: the form element (method get appends form data to the action URL with a ? separator and is the default; post sends it as the request body; enctype values and the default application/x-www-form-urlencoded)