Cheatsheet

HTTP Methods Cheatsheet

This cheatsheet compares the nine HTTP request methods by what they promise, whether a retry is safe, whether they carry a body and whether a cache may store the answer. It is for developers designing a REST API or debugging a 405 response. The confusion it clears up is the difference between safe and idempotent, and why PUT and PATCH are not interchangeable. See the HTTP, REST and Idempotent glossary pages for the concepts.

Quick reference

Method properties

Method Safe Idempotent Request body Cacheable response Typical success code
GET Yes Yes No defined meaning Yes 200
HEAD Yes Yes No defined meaning Yes 200, no body
POST No No Yes Only with explicit freshness information 201 or 200
PUT No Yes Yes No 201 if created, 200 or 204 if replaced
PATCH No No, unless you design it so Yes, a patch document Only with explicit freshness information 200 or 204
DELETE No Yes No defined meaning No 200, 202 or 204
OPTIONS Yes Yes Optional No 200 or 204
CONNECT No No Not used No 200, then a tunnel
TRACE Yes Yes Must not be sent No 200

Safe, idempotent and cacheable come from RFC 9110 sections 9.2 and 9.3. PATCH is defined separately in RFC 5789.

What each method means

Method What it asks the server to do
GET Send a current representation of the target resource
HEAD Same as GET but send headers only
POST Process the enclosed data by the resource's own rules, such as creating a child resource
PUT Replace the target resource's state with the enclosed representation
PATCH Apply a partial change described by the enclosed patch document
DELETE Remove the association between the target resource and its functionality
OPTIONS Describe the communication options for the resource, or `*` for the whole server
CONNECT Open a tunnel to the host and port in the request target
TRACE Echo the request back as a loop-back test

Safe versus idempotent

Term Definition Methods
Safe The client expects no state change GET, HEAD, OPTIONS, TRACE
Idempotent Repeating the request has the same intended effect as sending it once GET, HEAD, OPTIONS, TRACE, PUT, DELETE

Every safe method is idempotent. PUT and DELETE are idempotent but not safe.

Error responses about methods

Situation Status Header to send
Method known but not allowed for this resource 405 Method Not Allowed `Allow` listing the allowed methods
Method unknown or not implemented by the server 501 Not Implemented None required
PATCH body in a format the server cannot apply 415 Unsupported Media Type `Accept-Patch`

Common patterns

Create, replace, update and delete one resource

$ curl -X POST -d {"name":"a"} /items
HTTP/1.1 201 Created
Location: /items/1

$ curl -X PUT -d {"name":"b"} /items/7
HTTP/1.1 201 Created

$ curl -X PUT -d {"name":"b"} /items/7
HTTP/1.1 204 No Content

$ curl -X PATCH -d {"qty":2} /items/7
HTTP/1.1 200 OK
Content-Type: application/json

{"name":"b","qty":2}

$ curl -X DELETE /items/7
HTTP/1.1 204 No Content

This is real output from a small Node server. POST returns 201 with a Location header because the server picks the new URL. PUT to a URL the client chose returns 201 the first time and 204 on the repeat.

Prove POST is not idempotent and PUT is

$ curl -X POST -d {"name":"a"} /items
HTTP/1.1 201 Created
Location: /items/1

$ curl -X POST -d {"name":"a"} /items
HTTP/1.1 201 Created
Location: /items/2

Sending the same POST twice created two items, /items/1 and /items/2. Repeating the PUT above left one item at /items/7 both times. That is why a client may retry a PUT after a dropped connection but should not blindly retry a POST.

Discover what a URL allows

$ curl -X OPTIONS /items
HTTP/1.1 204 No Content
Allow: GET, HEAD, POST, OPTIONS

$ curl -X DELETE /items
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, POST, OPTIONS

$ curl -I /items
HTTP/1.1 200 OK
Content-Type: application/json

OPTIONS answers with an Allow header, and a disallowed method gets 405 with the same header. curl -I sends HEAD, which returns headers only.

Make a second DELETE harmless

$ curl -X DELETE /items/7
HTTP/1.1 204 No Content

$ curl -X DELETE /items/7
HTTP/1.1 404 Not Found

The status code differs on the repeat, but the server state is the same, so DELETE is still idempotent. Idempotent describes the effect on the server, not the response.

Send PATCH from fetch without the lowercase trap

const mk = m => new Request('http://localhost:8099/items/7', { method: m }).method;
console.log(mk('patch'), mk('put'), mk('PATCH'));
try { new Request('http://localhost:8099/', { method: 'TRACE' }); }
catch (e) { console.log(e.name + ': ' + e.message); }
try { new Request('http://localhost:8099/', { method: 'GET', body: 'x' }); }
catch (e) { console.log(e.name + ': ' + e.message); }
patch PUT PATCH
TypeError: 'TRACE' HTTP method is unsupported.
TypeError: Request with GET/HEAD method cannot have body.

The Fetch standard uppercases only DELETE, GET, HEAD, OPTIONS, POST and PUT, so patch stays lowercase and can return 405. It also forbids CONNECT, TRACE and TRACK, and Node refuses a body on GET or HEAD.

Pitfalls

  • Lowercase method names: the method token is case-sensitive, and patch is not the same as PATCH. In the run above, fetch normalized put to PUT but left patch alone, and Node printed a warning that it will likely produce a 405. Always write methods in uppercase.
  • Using PUT for a partial update: PUT replaces the whole state. A PUT with only {"qty":2} can wipe the other fields. Use PATCH for partial changes.
  • Assuming PATCH is idempotent: RFC 5789 says PATCH is neither safe nor idempotent by definition. A patch like "append item" repeats its effect, while "set qty to 2" does not.
  • Retrying POST automatically: RFC 9110 says a client should not retry a non-idempotent request unless it knows it is safe. Add an idempotency key on your API, or make the operation a PUT.
  • Sending a body with GET or DELETE: content in a GET has no defined semantics, and a client should not send it. RFC 9110 also warns that a body on DELETE might be rejected, because it resembles request smuggling. Put filters in the query string.
  • Mutating state on GET: a link such as page?do=delete will be fetched by crawlers and prefetchers. RFC 9110 warns that the owner must disable unsafe actions on safe methods.
  • HTML forms only send GET and POST: the method attribute accepts get, post and dialog. Other methods need fetch or a hidden _method field handled by your framework.
  • Returning 404 instead of 405: when the URL exists but the method does not, send 405 with an Allow header. Use 501 only when the server does not know the method at all.
  • Forgetting that CORS preflight uses OPTIONS: a cross-origin PUT, PATCH or DELETE triggers an OPTIONS request first, because only GET, HEAD and POST are CORS-safelisted. Your server must answer it.

Related ZipKit tools

Related cheatsheets