If you have ever built a search endpoint, you already know the argument. Someone on the team wants to use GET because “it’s a read, it should be safe and cacheable.” Someone else points out that the filter object is now 3 kilobytes of nested JSON and won’t fit comfortably in a URL. So you reach for POST, feel vaguely guilty about it, and move on. The HTTP QUERY method is the proposed fix for exactly this decade-old awkwardness, and it is worth understanding now even though it is still finding its feet.
In short: the HTTP QUERY method gives you a request that is safe and idempotent like GET, but carries a request body like POST. That single combination quietly solves a surprising number of problems.
The search-request dilemma QUERY solves
Today, when you need to send a non-trivial query to an API, you have three options and all of them cost you something.
Option 1: GET with a query string
This is the “correct” choice semantically. GET is safe, idempotent, and cacheable, which is precisely what a read should be. The trouble starts when your query outgrows the URL. Browsers and servers cap URL length somewhere between 2 KB and 8 KB, and encoding nested filters, geospatial bounds, or a GraphQL document into query parameters gets ugly fast. Worse, everything you put in the URL leaks into access logs, browser history, and analytics — not ideal when the query contains an email address or an auth-adjacent token.
Option 2: GET with a body
Some tools (Elasticsearch being the famous one) send a body with GET. The HTTP specification does not forbid it, but it explicitly gives it no defined meaning, so intermediaries are free to ignore or strip the body. That is undefined behavior dressed up as a feature, and it breaks the moment a proxy or client library decides to be strict.
Option 3: POST
So most of us settle on POST. It happily carries a body of any size, but it throws away the semantics we actually wanted. POST is neither safe nor idempotent, so caches, crawlers, and retry logic all treat it as “this might change something.” You lose caching, and you lose the honest signal that this request is just a read.
What the HTTP QUERY method actually is
QUERY is a new HTTP method defined by the IETF HTTP Working Group in the draft “The HTTP QUERY Method”. Think of it as GET that is allowed to have a body. Its defining properties are:
- Safe — it must not cause side effects, exactly like
GETandHEAD. - Idempotent — sending the same QUERY twice is the same as sending it once.
- Body-carrying — the request content is the query, and it has its own
Content-Type(JSON, SQL, a form-encoded body, a GraphQL document, whatever fits). - Cacheable — and this is the important one, because the cache key includes the request body.
A QUERY request in practice
Here is what a product search might look like. Notice that the query lives in the body where it belongs, not smashed into the URL.
QUERY /products HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
{
"filter": {
"category": "keyboards",
"price": { "lte": 150 },
"tags": ["mechanical", "wireless"]
},
"sort": [{ "price": "asc" }],
"limit": 20
}
And a response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /products/results/8a1f9c
Cache-Control: max-age=60
{ "total": 42, "results": [ /* ... */ ] }
It reads like a GET, behaves like a GET, and yet the client was able to send a rich, structured query without a single %5B in sight.
Why the HTTP QUERY method is cacheable when POST isn’t
This is the part that makes QUERY genuinely new rather than “POST with better manners.” Caches key their entries on the request. For GET, that key is the URL. POST responses are generally not cached at all, because the body isn’t part of the cache key and two different bodies to the same URL would collide.
QUERY changes the rules: the request content participates in the cache key. That means two different query bodies sent to /products are cached as two separate entries, and an identical repeat query can be served straight from cache. For high-traffic search and analytics endpoints, that is the difference between hammering your database and letting a CDN absorb the load.
Content-Location and canonical result URLs
Did you notice the Content-Location header in the response above? The server can hand back a URL that represents the result of your query. A client can then GET that URL directly — it is bookmarkable, shareable, and cacheable through the plain old GET path. You get the expressiveness of a body on the way in and a clean, linkable resource on the way out. That is a genuinely elegant piece of design.
Should you use the QUERY method today?
Here is the honest part. As of early 2025 the HTTP QUERY method is still an Internet-Draft, not a finished RFC. That has real consequences:
- Browser
fetch()andXMLHttpRequestdo not let you send a QUERY request yet. - Many servers, frameworks, proxies, load balancers, and CDNs don’t recognize the method and may reject or mishandle it.
- Your observability and API tooling probably has no idea what QUERY is.
So for production traffic today, POST is still the pragmatic choice for large or sensitive queries. What has changed is that there is now a light at the end of the tunnel: a standards-track answer to a problem we have been papering over for years. If you build API infrastructure, this is the moment to start tracking the draft, and maybe to make sure your own gateway doesn’t hard-reject unknown methods.
Final thoughts
The HTTP QUERY method is one of those changes that sounds small — “a new verb, great” — but actually closes a real gap in the web’s design. Safe, idempotent, cacheable, and able to carry a body: it is the request that search endpoints have quietly needed all along. It will not land everywhere overnight, but the direction is right, and knowing about it now means you will recognize the better pattern the moment your stack can support it.
