skip to content

What do the HTTP methods GET and POST actually mean on the wire, and what determines which one an operation should use?

level: juniorimportance: must knowfreq 85%

answer

  1. GET = retrieval, safe, params in URI, cacheable
  2. POST = "process this representation", body, open-ended
  3. GET that mutates → crawlers/prefetch fire it
  4. POST 201+Location / 200 / 202 / 204
  5. POST isn't "more secure" — just not in the URL

basics

~20 s

GET requests a representation of a resource — retrieval only, parameters in the URL, no intended side effects. POST asks the target resource to process the enclosed representation according to its own semantics — creating, submitting, or triggering work, with data in the body.

solid answer

~50 s

**GET** means "give me a current representation of this target resource". Its meaning is retrieval; RFC 9110 defines it as **safe**, so a GET is not expected to change state, and inputs travel in the URI (path and query string). Because of that, GETs can be cached, prefetched by browsers and link scanners, logged in full in access logs and proxies, and repeated freely. **POST** means "process this representation according to the target resource's own semantics". It is deliberately open-ended: create a subordinate resource, submit a form, run a search too complex for a query string, kick off a job. Data travels in the body with a declared `Content-Type`. POST is neither safe nor idempotent, so repeating one may repeat its effect. The practical test is **not** "how much data" but **"does this change state or carry sensitive input?"** Anything that mutates or that must not appear in a URL belongs in POST. A GET that deletes something is a real bug: crawlers and prefetchers will fire it.

code

http · 8 lines
http
GET /api/products?category=shoes&page=2 HTTP/1.1
Host: api.example.com

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=60

{"items":[...],"page":2}

go deeper

for a junior

State the core meanings — GET retrieves and is safe with parameters in the URL; POST submits a body for the server to process — and give one example of each.

for a middle

Add caching and bookmarkability, the correct POST status codes with Location, and why POST is not inherently more secure.

for a senior

Discuss crawler/prefetch damage from unsafe GETs, query-string leakage into logs and referrers, the complex-search tradeoff, and deduplication for repeated POSTs.

for a principal

Frame it as interface policy: which operations get URL identity and cacheability, how that shapes CDN strategy and observability, and where a non-cacheable POST search is an accepted cost.

## GET: retrieval, and the promises around it RFC 9110 defines **GET** as a request for a *current representation* of the target resource. Two consequences shape everything else: 1. **Inputs live in the URI.** Path segments and the query string carry the parameters. That makes the request trivially bookmarkable, shareable, and cacheable — the URL *is* the cache key. 2. **GET is declared safe.** "Safe" means the method is not *intended* to cause state change. The server may still write logs, counters or analytics; what matters is that the client is not held responsible for changes, so automated agents feel free to issue GETs. That licence is the source of the classic disaster: an app exposes `GET /delete?id=42`, a crawler or a browser prefetcher walks the links, and rows disappear. Nothing violated HTTP — the application lied about the method's meaning. The URI placement also has security consequences. Query strings show up in browser history, `Referer` headers sent to third parties, proxy and CDN access logs, and server logs. Tokens, passwords and personal data therefore do not belong in a GET query string. ## POST: "process this" **POST** is the least constrained method. RFC 9110 says the target resource should **process the representation enclosed in the request according to the resource's own semantics**. That is intentionally vague, and it is why POST covers so much ground: - **Creating a subordinate resource**: `POST /orders` with an order body; the server picks the identifier and replies **201 Created** with a `Location` header pointing at the new resource. - **Submitting data for processing**: a form, a payment, an email send, an import job. - **Appending to a collection or a log.** - **Non-retrieval queries**: a search whose criteria are too large or too structured for a query string. POST is neither safe nor idempotent: the server may do something, and doing it twice may do it twice. That is a property of the method's definition, not a flaw. What POST returns depends on what it did: **201 Created** plus `Location` (and usually the created representation) for creation; **200 OK** with a result body for processing that produced something; **202 Accepted** when work was queued and the outcome is not known yet, ideally with a status URL; **204 No Content** when nothing needs to come back. ## Choosing between them The decision procedure that survives interviews: 1. **Does the request change server state in a way the client is responsible for?** If yes → POST (or PUT/PATCH/DELETE when they fit better). If no → GET. 2. **Does the input contain secrets or personal data?** If yes, keep it out of the URI → POST. 3. **Is the input too large or too structured for a query string?** Practical URL limits (browsers and intermediaries commonly cap around a few thousand characters, and servers enforce their own) push complex queries to POST. 4. **Do you want caching, bookmarking and sharing?** That argues strongly for GET, since URL-keyed caching is free. Note what is *not* on the list: "POST is more secure". A POST body is exactly as visible as a query string to anyone who can read the traffic; only TLS protects either. POST merely keeps values out of URLs, histories, referrers and logs — real, but a different benefit. ## The awkward middle: complex search A search with a dozen filters is *conceptually* a retrieval but does not fit in a URL. The common compromise is `POST /search` with a JSON body, accepting the loss of cacheability and bookmarkability. Alternatives are to shorten the encoding, or to POST the criteria once, receive an identifier, and then GET the results by that id — which restores caching. An HTTP working-group effort to standardise a safe, cacheable **QUERY** method addresses exactly this gap; naming it shows you know the tradeoff is a known protocol wart, not a personal preference. ## Caching asymmetry GET responses are cacheable by default when freshness information allows. POST responses are cacheable only in narrow, rarely implemented conditions and are, in practice, treated as uncacheable; a POST also invalidates stored responses for the effective request URI in a shared cache. Treat "POST results are not cached" as the operating assumption. ## Repeatability in practice Because a POST may be repeated by an impatient user or a retrying network layer, any POST that must not happen twice needs an application-level guard — a deduplication key stored server-side, or a state check that makes the second attempt a no-op. This is the everyday consequence of the method's definition.

  • Is POST more secure than GET because the data is in the body?
    No. On the wire both are equally exposed without TLS and equally protected with it. What POST avoids is the URI-specific leakage: query strings land in browser history, bookmarks, Referer headers sent to third parties, and proxy, CDN and server access logs. That is a real reason to keep credentials and personal data out of GET, but it is not encryption.
  • You need a search with fifteen filter fields. GET or POST, and what do you give up?
    GET is semantically right but the criteria may exceed practical URL length limits, so many APIs use POST /search with a JSON body. The cost is cacheability and bookmarkability, since caches key on the URI and POST responses are effectively not cached. A middle path is to POST the criteria, get back an id, then GET the results by id so the result set is cacheable.
  • What status codes are appropriate for a POST and when?
    201 Created with a Location header when a new resource was created; 200 OK when processing produced a result body; 202 Accepted when the work was queued and the outcome is not yet known, ideally with a link to a status resource; 204 No Content when the action succeeded and there is nothing to return.

saying these in an interview costs you the question

  • "POST is more secure than GET" as a blanket claim
  • Using GET for state-changing actions like /delete?id=42
  • Believing the choice is decided by payload size alone
  • Assuming POST responses are cached like GET responses
  • Returning 200 with no Location after a POST that created a resource

context