RFC 10008 · June 2026

HTTP QUERY
vs GET vs POST

The shortest useful mental model: QUERY lets you send a rich query in the request body, while still declaring “this operation is read-only and safe to retry.”

Do not confuse the QUERY method with a URL query string. GET /products?color=blue uses the GET method plus a URI query component. QUERY /products is a distinct HTTP method whose query instructions normally live in the request body.

1. The three verbs in one screen

GET

“Give me a representation of this resource.”

Query inputs are commonly encoded into the URL.

safe idempotent cache-friendly
QUERY

“Run this read-only query against this resource.”

Query instructions are carried in the request content/body.

safe idempotent cacheable
POST

“Process this content according to this resource's semantics.”

Can create, mutate, trigger, submit — or even query. The method itself does not promise read-only behavior.

potentially unsafe potentially non-idempotent

2. Why QUERY exists

GET
Great semantics for reads
but complex query data in the URI gets awkward
→
POST
Great at carrying a body
but does not advertise “safe + retryable query”
→
QUERY
Body-based query
+ explicit safe/idempotent semantics
Property GET QUERY POST
Safe?
Client does not request state change
Yes Yes Potentially no
Idempotent?
Repeating has the same intended effect
Yes Yes Potentially no
Request body semantics No defined semantics Expected; defines query Expected; resource-specific
Where query input naturally goes Usually URI Request body Request body
Can a QUERY response be cached for another QUERY? — Yes; body participates in cache key No equivalent POST-to-POST reuse promised here

3. Progressive example: product search

1

Small search → GET is ideal

You have only a few short filters. The URL is readable, shareable, bookmarkable and naturally identifies the request.

GET /products?category=book&maxPrice=30 HTTP/1.1
Host: shop.example

Use GET when the URI remains a sensible representation of the query.

2

The query grows → stuffing everything into the URI becomes unpleasant

GET /products?category=book&authors=...hundreds...&facets=...&ranking=...&filters=...
Host: shop.example

Long URIs face practical intermediary limits, encoding overhead and higher exposure in logs/history.

3

Traditional workaround → POST the query body

POST /products/search HTTP/1.1
Host: shop.example
Content-Type: application/json

{
  "authors": ["A", "B", "..."],
  "maxPrice": 30,
  "facets": ["publisher", "year"]
}
Technically workable.

But an HTTP intermediary sees POST. It cannot infer from the method that this operation is read-only, safe to automatically retry, or meant to behave like a query.

4

RFC 10008 → express the intent directly with QUERY

QUERY /products HTTP/1.1
Host: shop.example
Content-Type: application/json
Accept: application/json

{
  "authors": ["A", "B", "..."],
  "maxPrice": 30,
  "facets": ["publisher", "year"]
}
The body remains rich.

But now the HTTP method itself declares the operation safe and idempotent. That semantic signal is available to generic HTTP infrastructure.

4. The retry difference

Client sends request
Connection drops before response arrives.
→
POST?
Generic client must be cautious: did the server already change something?
vs
QUERY?
The method is idempotent, so automatic retry/restart is semantically allowed.
Important nuance: “safe” does not mean the server performs literally zero side effects. Logging, metrics, cache population, etc. may still occur. It means the client is not asking for a change to the target resource's state.

5. QUERY can graduate into GET

A server may give the query, or its result, a URI. That lets later traffic use normal GET semantics without resending the body.

① Run rich query
QUERY /products

{ ...filters... }
→
② Server responds
HTTP/1.1 200 OK
Location:
/stored-queries/42
The Location URI identifies an equivalent resource for the query.
→
③ Later
GET /stored-queries/42
No need to resend the original query body.
Also available: Content-Location can identify a GET-able resource corresponding to the particular result that was returned, while Location can identify an equivalent resource that re-runs the same query semantics.

6. What caching means

GET cache key

Traditionally starts from the request URI plus relevant request metadata.

GET /products?maxPrice=30

QUERY cache key

Must incorporate the request content and related metadata.

QUERY /products

{"maxPrice":30}

This makes QUERY caching more complex than GET caching, because a cache has to read the request body to distinguish queries.

7. One practical decision rule

GET

Choose when your operation is retrieval and the query fits naturally in a URI.

QUERY

Choose when you need a body to describe a potentially large/structured read-only query and want HTTP to know it is safe + idempotent.

POST

Choose when the operation may create/change state, trigger non-idempotent processing, or when you intentionally need generic POST semantics.

8. Two implementation gotchas

Content-Type is mandatory for QUERY content. RFC 10008 requires the server to reject QUERY when Content-Type is missing or inconsistent with the body.

CORS requires preflight. QUERY is not a CORS-safelisted method, so browser cross-origin usage needs a preflight request.

Deployment support matters. Because QUERY is a newly standardized method, applications still need their server/framework/proxy/CDN chain to accept and correctly handle it.