
HTTP Methods Reference
Complete reference for all 9 HTTP methods - descriptions, idempotency, safety, request body, use cases, and examples.
Last reviewed: April 2026New to this tool? Click here for instructions
Quick Comparison Table
| Method | Safe | Idempotent | Request Body | Response Body | Cacheable |
|---|
Browse, search, and reference every standard HTTP method — including the WebDAV extensions — with their safety, idempotency, and cacheability properties pulled directly from RFC 9110 and the related specs. Use the search box above to filter by method name, semantic property, or use case.
What This Tool Does
This reference covers all nine core HTTP methods defined in the current HTTP semantics specification — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE, and CONNECT — plus the most common WebDAV extension methods you will encounter in real-world API surfaces: MKCOL (create a collection), COPY, MOVE, LOCK, UNLOCK, and PROPFIND. For each method, the cards above expose four authoritative semantic properties: safe (whether the method is defined as read-only with no externally observable side effects), idempotent (whether repeated identical requests have the same final effect as a single request), request-body allowed, and cacheable by default.
The semantic properties shown are not opinions — they are the values codified in RFC 9110 (the consolidated HTTP Semantics specification, published 2022, which replaced and superseded RFCs 7230–7235 and 7231–7234). For PATCH, the source is RFC 5789; for WebDAV methods, RFC 4918. Every property in the comparison table maps to a specific section of one of those documents, which is why an HTTP intermediary that respects the specs will behave consistently across implementations — Apache, nginx, Cloudflare, AWS API Gateway, and your custom Node service all draw their semantics from the same source of truth.
Knowing these properties matters because real systems depend on them. Reverse proxies cache GET responses but not POST. Load balancers retry idempotent requests on connection failure but not non-idempotent ones. Browser fetch() sends a CORS preflight before any non-simple request. Search engine crawlers refuse to issue non-safe methods, which is why a GET-vs-POST decision can determine whether your endpoint is ever indexed. Getting the method right at the API design stage prevents the entire transport layer from quietly working against you.
How to Use It
The search box above filters the method grid live. Type any of three things and the list narrows to matches: a method name (POST, PUT), a semantic property keyword (idempotent, safe, cacheable), or a use-case phrase (REST, create, delete). Filtering happens client-side with a 200 ms debounce, so even slow typing won't trigger redundant re-renders.
Each method card collapses to a one-line summary by default — name, plain-English description, and the two most-cited properties (Safe / Idempotent). Click the card header to expand it. The expanded body reveals five additional fields: the full specification reference (RFC section number), a longer behavioral description, a list of five typical use cases drawn from production APIs, an example raw HTTP request showing the method line and required headers, and an example response showing the canonical status code and response headers for a successful invocation.
Below the method grid is the Quick Comparison Table. This is the view to use when designing a new endpoint: scan a single row to see whether the method is safe, idempotent, has a defined request body, has a defined response body, and is cacheable by default. The table reflects the same filtered set as the cards above, so a search query narrows both views in lockstep — useful when you want to see only the methods that are both safe and cacheable, for example.
The reference is intentionally cache-friendly: every method's properties and use cases are baked into the page at build time, so no API calls are made when you search or expand a card. The entire reference works offline once the page is loaded, and it functions correctly inside the service-worker cache when the device is fully disconnected.
Worked Example: Designing a REST Endpoint for /articles/{id}
The fastest way to internalize HTTP method semantics is to design a concrete resource. Consider an article-management API with the canonical URL pattern /articles/{id} for a single article and /articles for the collection. Each operation maps to one method, and each successful invocation returns a specific status code.
1. Reading an Article: GET /articles/123
The client requests a representation of article 123. GET is safe (no server state changes), idempotent (repeated reads return the same content modulo intervening writes), and cacheable by default. The server returns 200 OK with the article as JSON, plus Cache-Control, ETag, and Last-Modified headers so intermediaries and the client can cache. If the article does not exist, the server returns 404 Not Found. If the client provided a conditional If-None-Match header that matches the current ETag, the server returns 304 Not Modified with no body, saving bandwidth.
2. Creating a New Article: POST /articles
The client posts a JSON body containing the new article's fields — title, body, author_id — to the collection URL, not a specific article URL. The server generates an article ID, persists the record, and returns 201 Created. The response must include a Location header pointing to the new resource: Location: /articles/124. The response body conventionally echoes the full created resource so the client can grab the server-assigned ID and any default fields without an extra round trip. POST is not idempotent: if the client retries the POST after a network timeout, two articles will be created. The standard mitigation is the Idempotency-Key request header — the client sends a UUID, and the server caches the first response keyed by that UUID, returning the same response on retry.
3. Replacing an Article Fully: PUT /articles/123
The client submits the complete article body to the article's specific URL. PUT semantically replaces the resource — any field not present in the request body is removed from the stored representation. This is the critical distinction from PATCH. PUT is idempotent: sending the same PUT body 10 times leaves the resource in the same final state as sending it once, and proxies are allowed to retry PUT requests on connection failure. The server returns 200 OK with the new representation, or 204 No Content if it chooses not to echo the body. If the resource did not previously exist and the server is willing to create it at the client-specified URL, 201 Created is returned — this is the "upsert" pattern.
4. Partially Updating an Article: PATCH /articles/123
The client submits only the fields it wants to change. With a simple JSON Merge Patch body of {"title": "New Headline"}, only the title field is updated and every other field — including body, author_id, and tags — is left untouched. The server returns 200 OK with the updated resource or 204 No Content if the body is intentionally omitted. PATCH's idempotency depends on the patch format and the field types involved: JSON Merge Patch (RFC 7396) is idempotent for scalar fields but non-idempotent for arrays, because each merge call replaces the array wholesale. JSON Patch (RFC 6902) operations like {"op": "add", "path": "/tags/-", "value": "draft"} are explicitly non-idempotent — every retry appends another tag.
5. Deleting an Article: DELETE /articles/123
The client issues a DELETE against the resource URL. The server removes the article and returns 204 No Content with an empty body, or 200 OK if it returns a confirmation payload. DELETE is idempotent: deleting an already-deleted article should not be an error. The standard response is to return 404 on the second call if the resource has already been removed and a record is not retained, or 204 again if the server treats the operation as a no-op. Both behaviors are spec-compliant; the choice depends on whether the API maintains a tombstone for deleted records.
This five-operation mapping — GET, POST, PUT, PATCH, DELETE against /articles and /articles/{id} — is the canonical REST CRUD pattern that nearly every modern HTTP API derives from. Following it gives you HTTP caching for free on reads, safe retry semantics on writes, and a URL surface that is legible to anyone with REST experience.
Common Use Cases
Designing a REST API
REST's resource-oriented design assigns one method per operation per resource URL. Lists are GET on the collection URL; creation is POST on the collection; reads, replacements, partial updates, and deletes are GET/PUT/PATCH/DELETE on the item URL. This convention is so deeply baked into tooling — OpenAPI, Postman, code generators, API gateways — that deviating from it loses you the entire ecosystem's free tooling. The first design decision when adding a new endpoint should be which method best matches the operation's semantics, not what's easiest to implement.
Designing GraphQL HTTP Transport
GraphQL deliberately uses only one HTTP method: POST. The query itself — including the operation type (query, mutation, subscription) — is encoded in the JSON request body. This intentional design choice forfeits HTTP's per-URL caching layer because every GraphQL request hits the same single URL (typically /graphql), making URL-based caches like CDNs and reverse-proxy caches useless. GraphQL clients like Apollo and Relay compensate with their own normalized client-side caches that key on the query AST plus variable values. GET is permitted by the GraphQL HTTP transport spec for cacheable read-only queries, with the query as a URL-encoded query string parameter, but adoption is rare because deeply nested queries exceed practical URL-length limits.
CORS Preflight Requests
Browsers issue an automatic OPTIONS preflight before any cross-origin request that uses a non-simple method or non-simple headers. Simple requests — GET, HEAD, or POST with application/x-www-form-urlencoded, multipart/form-data, or text/plain — skip preflight entirely. Anything else triggers the OPTIONS handshake: the browser asks the server which methods, headers, and origins are allowed; the server responds with Access-Control-Allow-* headers; only after a successful preflight does the browser dispatch the real request. The Access-Control-Max-Age response header tells the browser how long to cache the preflight result, typically 600–86400 seconds, eliminating repeated preflights for chatty APIs.
HEAD for Cache Validation
HEAD is identical to GET except the server must not return a response body. Headers — Content-Length, ETag, Last-Modified, Content-Type — are returned exactly as they would be for a GET. The classic use case is checking whether a large file has changed before re-downloading it: a HEAD request returns the ETag in a few hundred bytes; if the client's cached ETag matches, no download is needed. Link checkers and uptime monitors use HEAD for the same reason — verify a URL responds without paying the bandwidth cost of the full body.
Browser fetch() vs. XMLHttpRequest Defaults
The modern fetch() API defaults to GET when no method is specified and parses the response based on the Content-Type response header. XMLHttpRequest requires the method to be passed explicitly to open() and returns either a string (responseText) or a parsed XML document (responseXML) depending on the responseType property. Both APIs respect the same CORS rules — preflight on non-simple requests, no-cors mode opacity, credentials inclusion via credentials: 'include' or withCredentials = true. fetch() is the recommended modern choice; XMLHttpRequest remains for legacy code and the one capability fetch lacks: upload progress events.
Edge Cases and Pitfalls
HTTP method semantics carry footguns that are easy to step on if you don't know they exist. The following sections cover the most common ones.
POST Is Not Idempotent — Do Not Auto-Retry
A network library that automatically retries failed POSTs is a bug factory. Every retry potentially duplicates the operation — two charges to a credit card, two emails sent, two records inserted. The correct pattern is either (a) require an explicit Idempotency-Key header and have the server deduplicate by that key for a defined retention window, (b) use PUT against a client-chosen URL when the resource ID is known in advance, or (c) make retries the application's explicit decision after the user re-confirms. Stripe, PayPal, AWS SQS, and Shopify all use the Idempotency-Key pattern; their documentation is the canonical reference.
PUT vs. PATCH: The Replacement Trap
PUT replaces the entire resource — any field omitted from the body is removed. Sending PUT /users/123 with body {"name": "Alice"} when the existing record contains {"name": "Alice", "email": "alice@example.com", "role": "admin"} will leave the user with no email and no role. RFC 5789 was added precisely because PUT's "all-or-nothing" semantics were a poor fit for partial updates, which is what most clients actually want. The rule: use PUT only when the client is sending the full intended state. For anything else, use PATCH.
DELETE With a Body Is Controversial
RFC 9110 § 9.3.5 says a body on DELETE "has no defined semantics" but does not prohibit one. In practice, behavior is wildly inconsistent. Some servers strip the body. Some proxies drop the request. The browser Fetch API has historically refused to send a body on DELETE in some implementations. ElasticSearch is the famous outlier that requires DELETE bodies for the _delete_by_query endpoint, and that decision has caused years of integration friction. The portable pattern is to encode deletion parameters in the URL query string or to use POST against a /delete sub-resource. If your API design seems to require a DELETE body, that's usually a signal to revisit the resource model.
TRACE Is a Security Risk: Cross-Site Tracing (XST)
TRACE echoes the entire received request back in the response body, including cookies, Authorization headers, and any proxy-injected headers. In 2003, security researcher Jeremiah Grossman demonstrated Cross-Site Tracing (XST): an attacker combines an XSS vulnerability with a TRACE request to read HttpOnly cookies — bypassing the very protection HttpOnly was designed to provide. Modern Apache (2.0.55+), IIS (7+), and nginx all disable TRACE by default. PCI DSS scanners flag enabled TRACE as a finding. There is no production use case that requires it.
CONNECT for HTTPS Tunneling Through Proxies
CONNECT is the method browsers use to ask an HTTP proxy to open a raw TCP tunnel to an HTTPS server. The proxy responds with 200 Connection Established, and then the TLS handshake happens directly between the browser and the origin server — the proxy sees only encrypted bytes flowing in both directions, which is why HTTPS through a proxy preserves end-to-end confidentiality. Corporate "SSL inspection" appliances break this guarantee by terminating the original TLS connection at the proxy, decrypting, inspecting, and re-encrypting on a new outbound connection using a corporate root CA installed on managed devices. From a protocol standpoint, this is a man-in-the-middle that the browser explicitly trusts.
WebDAV Methods Extend HTTP for File-System Semantics
RFC 4918 defines WebDAV as an extension to HTTP that adds file-system-style operations: MKCOL creates a collection (directory), COPY and MOVE manipulate resources, PROPFIND retrieves resource metadata, and LOCK/UNLOCK manage exclusive write access. WebDAV underpins macOS Finder's "Connect to Server" feature, Microsoft Office's "Open from URL", and the calendaring (CalDAV) and contacts (CardDAV) extensions. Most public-facing HTTP APIs do not implement WebDAV — but Nextcloud, ownCloud, SharePoint, and Apache mod_dav do, and any integration with those systems needs to handle the extended method set.
Browser Form Submissions Only Support GET and POST
An HTML <form> element's method attribute accepts only two values: GET and POST. The HTML specification does not permit PUT, PATCH, or DELETE on form submissions. This is the historical reason why frameworks like Rails introduced the convention of a hidden _method form field — the form actually submits via POST, but the framework's request middleware reads _method and dispatches as if the request used PUT or DELETE. Modern single-page applications sidestep this by submitting forms via fetch() instead of native form submission, which removes the method restriction.
Behind the Scenes: HTTP Versions, Method Semantics, and the Spec Lineage
HTTP/1.1, HTTP/2, and HTTP/3 — Same Methods, Different Wire Formats
HTTP/1.1 (originally RFC 2616, then RFC 7230–7235, now consolidated into RFC 9112 for message syntax and RFC 9110 for semantics) is a plain-text protocol: requests and responses are ASCII strings with a request line, headers, a blank line, and an optional body. HTTP/2 (RFC 9113) re-encodes the same semantics over a binary framing layer — methods, headers, and bodies are all just data in binary frames multiplexed over a single TCP connection. HTTP/3 (RFC 9114) replaces TCP with QUIC, a UDP-based transport that provides multiplexed streams with per-stream loss recovery. The crucial point is that the method semantics defined in RFC 9110 are identical across all three versions: a GET in HTTP/3 means exactly what a GET in HTTP/1.1 means. Only the wire encoding changed.
"Method" vs. "Verb" — Terminology
The HTTP specification consistently uses method. The term verb appeared in early REST literature — Roy Fielding's 2000 dissertation and the books that followed — as a more intuitive English word for what a GET or POST "does." The two terms are interchangeable in casual use, but RFC 9110 only uses "method." When writing API documentation, prefer "method" for precision; when teaching the concept to newcomers, "verb" is often clearer because it cues the read/write distinction.
Safe, Idempotent, Cacheable — Three Independent Properties
The three core method properties are independent, not nested. Safe means the method must not produce externally observable side effects on server state (GET, HEAD, OPTIONS, TRACE). Idempotent means the same request repeated N times has the same effect as N=1 (GET, PUT, DELETE, HEAD, OPTIONS, TRACE). Cacheable by default means an intermediary may store the response and reuse it for subsequent equivalent requests without revalidation, unless the response indicates otherwise (GET, HEAD; POST is conditionally cacheable when explicit cache-control headers permit). Every safe method is idempotent, but not every idempotent method is safe: DELETE is idempotent (repeated DELETEs of the same resource end in the same final state — the resource is gone) but not safe (the first DELETE has a side effect: the resource is removed).
Why DELETE Is Idempotent But Not Safe
The first DELETE of a resource modifies server state — the resource is removed. By definition, that is a side effect, so DELETE is not safe. But the second DELETE of the same resource cannot remove what is already gone; the resource is in the same final state (absent) regardless of whether DELETE was called once or one hundred times. This is the exact definition of idempotence: the same final state after one or many invocations. Idempotence is about end state; safety is about whether any side effect occurred at all. They measure different things.
RFC 9110: The Single Source of Truth Since 2022
Prior to 2022, HTTP semantics were spread across multiple RFCs: RFC 7230 (message syntax), RFC 7231 (semantics and content), RFC 7232 (conditional requests), RFC 7233 (range requests), RFC 7234 (caching), and RFC 7235 (authentication). RFC 9110 consolidated semantics, conditional requests, range requests, and authentication into a single document, with caching split off into RFC 9111 and message syntax into RFC 9112 (for HTTP/1.1) or RFC 9113 (for HTTP/2). When someone asks "what does the HTTP spec say about X?", the modern answer is almost always "section N of RFC 9110."
Comparison: REST vs. GraphQL HTTP vs. gRPC HTTP/2
REST: One Method Per Operation
REST as practiced in 2026 maps each HTTP method to one CRUD-like operation per resource URL. GET reads, POST creates on the collection, PUT replaces, PATCH partially updates, DELETE removes. The method semantics — safety, idempotency, cacheability — are exposed to the network layer, which means CDNs, reverse proxies, and load balancers can apply method-aware optimizations without understanding the application protocol. A GET response can be cached for hours by a CDN; a POST response cannot. A 5xx response to an idempotent PUT can be retried automatically by a proxy; a 5xx response to a POST cannot. REST is the only architectural style that fully leverages HTTP's built-in transport semantics.
GraphQL HTTP: One Method, One URL, One Schema
GraphQL HTTP transport uses POST against a single URL — typically /graphql — for every operation, regardless of whether it is a read, write, or subscription. The operation type lives inside the JSON request body, not in the HTTP method line. This design intentionally forfeits HTTP's URL-based caching layer in exchange for a single strongly-typed schema and the ability to fetch exactly the fields the client needs in one round trip. Persisted queries (where the client sends a hash of a known query rather than the full query text) reintroduce some HTTP-layer caching, but the dominant caching strategy remains client-side normalized caches (Apollo, Relay) keyed on the query AST plus variable values.
gRPC: HTTP/2 Streams as a Transport, RPC Semantics on Top
gRPC uses HTTP/2 purely as a transport — multiplexed binary streams, header compression, server push — with Protocol Buffers as the message format. The HTTP method is always POST; the actual operation is encoded in the URL path (e.g., POST /package.Service/Method) and in the binary message body. From an HTTP-semantics perspective, every gRPC call is a POST, which is why gRPC services do not benefit from HTTP method-based caching, retry, or proxy semantics. In exchange, gRPC provides streaming RPC patterns (unary, server-streaming, client-streaming, bidirectional-streaming) that don't fit cleanly into request/response REST, plus a binary wire format that's significantly smaller than JSON.
When REST Is Right and When It Isn't
REST is the right choice when (a) your operations map naturally to CRUD on resources, (b) you want HTTP-layer caching for reads, (c) external developers will integrate with your API and benefit from familiar method semantics, and (d) clients are heterogeneous — browsers, mobile, CLI, server-to-server. REST is the wrong choice when (a) clients need to request highly variable field subsets and over-fetching is a real cost (GraphQL wins), (b) operations are inherently streaming or bidirectional (gRPC wins), or (c) the API is internal-only and the team values strong typing and code generation more than HTTP transparency (gRPC or GraphQL win). Most public APIs that need broad ecosystem adoption stay REST; most internal microservice meshes have moved to gRPC; most modern front-end-heavy applications use GraphQL for the front-end-to-backend layer.
Frequently Asked Questions
What's the difference between PUT and PATCH?
PUT replaces an entire resource with the request body; any field omitted from the body is removed from the resource. PATCH applies a partial modification — only the fields included in the body are touched, and everything else is left unchanged. PUT is always idempotent (RFC 9110 § 9.3.4): sending the same PUT body twice leaves the resource in the same final state. PATCH is not guaranteed idempotent by the spec (RFC 5789), and certain patch formats — most notably JSON Merge Patch (RFC 7396) applied to array fields — are non-idempotent in practice because each call appends rather than replaces.
Is POST idempotent?
No. POST is explicitly defined as non-idempotent in RFC 9110 § 9.3.3. The semantic intent of POST is to create a new subordinate resource at a server-chosen URL, so sending the same POST twice creates two resources. This has practical implications for retry logic: a client that retries a POST after a network timeout may create a duplicate. The standard mitigations are an Idempotency-Key header (used by Stripe, PayPal, and others), client-generated UUIDs in the body, or switching to PUT against a client-chosen URL when the resource identifier is known in advance.
Can DELETE have a request body?
Technically yes — RFC 9110 § 9.3.5 says a body "has no defined semantics" on DELETE but does not prohibit one. In practice, behavior is inconsistent: some servers and reverse proxies strip the body entirely, the Fetch API in browsers refuses to send a body on DELETE through some implementations, and intermediate caches may treat the body as undefined. The portable pattern is to put deletion parameters in the URL query string or to use POST against a /delete sub-resource. ElasticSearch is the famous counter-example that does require DELETE bodies, and that decision has caused integration friction for years.
Why does CORS use OPTIONS?
Browsers issue an automatic OPTIONS preflight before any cross-origin request that uses a non-simple method (anything except GET, HEAD, or POST with a simple Content-Type) or non-simple headers. The OPTIONS preflight asks the target server: "Will you accept a POST from this origin with these headers?" The server replies with Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers. Only after a successful preflight does the browser send the real request. OPTIONS was chosen because it is the one HTTP method that has always been defined to describe communication options for the target resource — exactly what CORS needed.
What's a safe HTTP method?
A safe method is one defined to be "read-only" from the client's perspective — the request must not produce any externally observable side effects on the server's state. RFC 9110 § 9.2.1 lists GET, HEAD, OPTIONS, and TRACE as the safe methods. Safety is a semantic guarantee given by the client's intent and the method's contract; it does not forbid internal logging, metrics, or cache updates that happen as a consequence of any request. Safe methods can be retried freely after a network failure without risk of duplicate side effects, and search engine crawlers will only issue safe methods when indexing.
Can I use TRACE in production?
No — TRACE should be disabled on every production server. The method echoes the entire received request back in the response body, including any cookies, Authorization headers, and proxy-injected headers. Combined with a cross-site scripting vulnerability, this enables Cross-Site Tracing (XST), a 2003-era attack that bypasses HttpOnly cookie protection by reading the cookie value out of the TRACE echo. OWASP's recommendation is unambiguous: TRACE is disabled by default in Apache 2.0.55+, IIS 7+, and nginx, and PCI DSS scanners flag it as a finding. There is no production use case that requires it.
Why does GraphQL only use POST?
GraphQL queries are typically too large for a URL — a deeply nested query with fragments can easily exceed the 2 KB practical URL length limit that proxies and CDNs enforce. The official GraphQL HTTP transport specification standardizes on POST with the query in a JSON request body. GET is allowed as an option for cacheable read-only queries, with the query as a URL-encoded query-string parameter, but in practice most clients send everything as POST for consistency. This design intentionally forfeits HTTP's per-URL caching layer, which is one of the trade-offs that pushed Apollo and Relay toward dedicated normalized client-side caches.
What status code should I return for a successful POST?
It depends on what the POST did. If the POST created a new resource, return 201 Created with a Location header pointing to the new resource and the created resource in the response body — this is the canonical RESTful create response. If the POST processed a request that did not result in a resource creation (a search, an action, a webhook), return 200 OK with the result body. If the request was accepted for asynchronous processing and a job is now running in the background, return 202 Accepted with a Location header pointing to a status-polling endpoint. Returning 204 No Content for a create is technically valid but loses the opportunity to surface the new resource ID to the client.