HTTP methods

HTTP & the web · Essentials · 10 min

Methods tell caches, proxies, browsers and API clients what a request may do, and when it's safe to retry.

The method says what the client wants to do with the target resource.

  • GET: retrieve a representation. No body, no side effects intended.
  • HEAD: like GET but only the headers, for checking existence, size or freshness.
  • POST: process the enclosed data: create a resource in a collection, submit a form, trigger an action.
  • PUT: replace the resource at this URL with the body, creating it if absent.
  • PATCH: apply a partial modification.
  • DELETE: remove the resource.
  • OPTIONS: ask what's allowed; used by CORS preflight requests.

Two properties matter more than the names.

Safe methods (GET, HEAD, OPTIONS) are read-only by contract. Crawlers, prefetchers and link previews issue GETs freely, so a GET that deletes or changes data will eventually be triggered by a bot.

Idempotent methods (the safe ones plus PUT and DELETE) have the same effect whether sent once or many times. Deleting an item twice leaves it deleted; PUTting the same body twice gives the same state. Clients and proxies can therefore retry them after a timeout. POST and PATCH are not idempotent in general: retrying a POST may create two orders, which is why payment APIs add idempotency keys.

Browsers' HTML forms only send GET and POST; JavaScript's fetch can send any method. And idempotent doesn't mean the response is identical: a second DELETE may return 404.

Example

const base = "https://api.example.com/v1/articles";

await fetch(base);                                     // GET: list
await fetch(`${base}/42`, { method: "HEAD" });         // headers only

await fetch(base, {                                    // POST: create in collection
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Hello" }),
});

await fetch(`${base}/42`, {                            // PUT: replace whole resource
  method: "PUT",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Hello", body: "...", tags: [] }),
});

await fetch(`${base}/42`, {                            // PATCH: change one field
  method: "PATCH",
  headers: { "Content-Type": "application/merge-patch+json" },
  body: JSON.stringify({ title: "Hello again" }),
});

await fetch(`${base}/42`, { method: "DELETE" });       // idempotent: safe to retry

Remember

  • GET reads, POST processes/creates, PUT replaces, PATCH modifies, DELETE removes
  • Safe = no side effects: GET, HEAD, OPTIONS
  • Idempotent = repeating has the same effect: safe methods + PUT + DELETE
  • Never change data in a GET handler

Watch out for

  • Implementing 'GET /items/5/delete', which crawlers and link prefetchers will happily trigger.

Check yourself

  1. A request times out and the client doesn't know if it was processed. Which method is safe to resend automatically?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods