HTTP QUERY: A Safe, Idempotent Request with a Body

In June 2026, HTTP gained a new standardized method: QUERY.
Published as RFC 10008, it addresses a problem API developers have worked around for years: how can we send a complex, read-only query when it is too large or structured for a URL?
The tempting explanation is:
QUERYis aGETwith a body.
That is a useful first intuition, but it is not technically accurate. A GET requests a representation of the resource identified by the URI, and its request body has no generally defined semantics. QUERY asks the target resource to process the enclosed content safely and idempotently, then return the result.
In other words, it carries structured content like POST, while providing the safety and idempotency guarantees associated with GET.
QUERY /products/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
{
"categories": ["books", "electronics"],
"price": { "min": 20, "max": 200 },
"available": true,
"sort": [{ "field": "rating", "direction": "desc" }]
}
Why Not Just Use GET?
GET works perfectly for small filters:
GET /products?category=books&available=true
But complex queries quickly become problematic. URLs have practical length limits across clients, proxies, gateways, and servers. Nested conditions are awkward to encode, percent-encoding hurts readability, and URLs commonly appear in browser history, access logs, analytics tools, and referrer data.
Using a body solves the serialization problem, but a body on GET is not interoperable. Some implementations reject it, others ignore it, and HTTP does not define what it means.
Why Not Just Use POST?
Many APIs already use POST /search or POST /query. This works, but it hides the operation’s intent from generic HTTP infrastructure.
POST is potentially state-changing and potentially non-idempotent. Developers may know that a particular endpoint is read-only, but proxies, caches, retry mechanisms, and generic clients cannot infer that from the method.
QUERY makes the intent explicit.
| Property | GET | QUERY | POST |
|---|---|---|---|
| Safe | Yes | Yes | Not guaranteed |
| Idempotent | Yes | Yes | Not guaranteed |
| Request body semantics | Not defined | Expected | Defined by the resource |
| Cacheable response | Yes | Yes | Limited |
| Large structured input | Poor fit | Good fit | Good fit |
| Ecosystem support | Excellent | Emerging | Excellent |
Safe and Idempotent
QUERY is registered by IANA as both safe and idempotent.
Safe means the client is not asking to change the target resource. The server may still write logs, update metrics, or populate a cache, just as it can for GET. However, an operation that sends an email, charges a card, or changes business data must not use QUERY.
Idempotent means the request can be repeated without requesting additional state changes. A client or gateway can therefore retry it after a connection failure.
This does not mean every response will contain identical data. Results may change over time. It means that repeating the request does not repeat a mutation.
Where QUERY Fits
The method is useful for read-only operations with rich inputs, such as:
- Complex search with nested filters, facets, and ranking controls
- Analytics with dimensions, metrics, grouping, and time ranges
- Geospatial queries containing polygons or GeoJSON
- Graph and relationship traversal
- Batch retrieval of hundreds of IDs
- Query languages such as JSONPath, SPARQL, or a domain-specific language
The request’s Content-Type identifies the query format. A server can also advertise supported formats with the new Accept-Query response header:
HTTP/1.1 204 No Content
Allow: GET, HEAD, QUERY, OPTIONS
Accept-Query: application/json, application/jsonpath
The Trade-offs
Standardized does not mean universally supported.
Some reverse proxies, API gateways, WAFs, CDNs, frameworks, and generated clients may reject an unfamiliar method or fail to apply its retry and caching semantics correctly. The complete path from client to origin must be tested.
Cross-origin browser requests also require a CORS preflight because QUERY is not a safelisted method.
Caching is possible, but more complex than with GET. The cache key must include the request body and relevant metadata, not only the URI. Incorrect body normalization could return the wrong result.
Moving query parameters into the body also reduces accidental exposure through URL-focused logs, but it does not make the data secret. Applications, gateways, and tracing systems may still log request bodies.
Finally, a QUERY is not directly bookmarkable. A server can solve this by returning a Location or Content-Location URI that clients can later access with GET.
Should You Use It Today?
Keep using GET when the query is small, naturally fits in a URI, and benefits from links, bookmarks, and universal caching.
Use QUERY when the operation is genuinely safe and idempotent, its input is too complex for a URI, and you control or have tested the relevant infrastructure.
Keep using POST for mutations and when compatibility is more important than expressing read-only semantics at the protocol level.
QUERY is not simply a new syntax. It gives a precise HTTP meaning to operations that have been awkwardly living behind POST for years.
For simple filters, GET remains the best choice. For mutations, use POST or another appropriate method. For large, structured, read-only operations, HTTP finally has an honest method name.
