CalculatorWala
Blog
Web Development

HTTP QUERY Method: The Complete Guide to RFC 10008

Laptop screen showing an HTTP QUERY request to /products with a JSON body, next to an RFC 10008 diagram of a client sending a QUERY to a server with its key properties: safe, idempotent, cacheable, request body with meaning, and query not in URL or logs

In June 2026, the IETF published RFC 10008, and HTTP got its first new method since PATCH in 2010. It's called QUERY, and it fixes a gap that every backend developer has hit at least once: you need to send a complex query to a server, it's too big or too sensitive for a URL, but it's semantically a read, not a write. For decades the answer was "use POST and hold your nose." Now there's a proper answer.

This guide covers what QUERY is, why it was needed, the exact problems it solves, how caching and error handling work, and how to start using it.

The problem QUERY solves

HTTP methods carry promises. GET promises it's safe (it changes nothing on the server) and idempotent (retrying is harmless), which is why browsers prefetch it, proxies cache it, and clients retry it freely. POST promises none of that — every intermediary must assume a POST might charge a credit card, so nothing caches it and nothing retries it automatically.

The trouble starts when a read is too complicated for a URL:

  • URL length limits. GET queries live in the query string, and the practical ceiling is around 2,000–8,000 characters depending on the browser, proxy, and server. A search with 40 filters, a GraphQL document, or a list of 500 IDs simply doesn't fit.
  • GET bodies don't work. HTTP technically allows a GET request to carry a body, but the spec says it has no defined meaning, and many servers, proxies, and CDNs silently drop it. Elasticsearch famously tried GET-with-body for _search and half the ecosystem couldn't send it.
  • Sensitive data leaks through URLs. Query strings end up in server access logs, browser history, analytics tools, and Referer headers. Personal data or search terms you wouldn't want logged shouldn't travel in a URL.
  • The POST workaround throws away the read semantics. Moving the query into a POST body works mechanically, but now caches won't cache it, clients won't safely retry it after a dropped connection, and monitoring tools can't tell your harmless search from a destructive write.

Every search API, reporting API, and GraphQL endpoint has been living with one of these compromises. That's the decades-old gap.

What QUERY is

QUERY is a safe, idempotent HTTP method that carries the query in the request body. In the RFC's own words, a QUERY request asks the server to "process the enclosed content in a safe and idempotent manner and then respond with the result."

Think of it as: GET's promises + POST's body.

Property GET POST QUERY
Safe (no server state change)
Idempotent (retry freely)
Cacheable response Rarely
Request body with meaning
Query visible in URL/logs ✅ (a problem)

What a QUERY request looks like

The shape is deliberately boring — it looks like a POST but means a GET:

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

{
  "category": "electronics",
  "price": { "max": 25000 },
  "in_stock": true,
  "sort": "-rating",
  "limit": 50
}

The server runs the query and responds with a normal 200 OK carrying the results. The Content-Type header on the request is mandatory — the body is a query document, and the server needs to know its format.

With curl:

curl --request QUERY https://shop.example.com/products \
  -H "Content-Type: application/json" \
  -d '{"category":"electronics","limit":50}'

With JavaScript fetch (note: like any non-simple method, QUERY triggers a CORS preflight on cross-origin requests):

const res = await fetch("/products", {
  method: "QUERY",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ category: "electronics", limit: 50 }),
});
const results = await res.json();

How a server advertises support: Accept-Query

A brand-new method needs discovery. RFC 10008 defines the Accept-Query response header: a server includes it to say "I support QUERY here, and these are the query formats I understand":

Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"

Clients can probe with an OPTIONS request first, or attempt QUERY and fall back if they get a 405 Method Not Allowed. Error handling is spelled out too:

  • Missing or unsupported Content-Type415 Unsupported Media Type
  • Body parses but the query itself is invalid → 422 Unprocessable Content

Caching: the clever part

This is where QUERY earns its RFC. GET responses are cached by URL. But two QUERY requests to the same URL can carry completely different bodies — so RFC 10008 requires that the cache key incorporate the request content, not just the URL.

Caches are also allowed to normalize the body before keying it, so semantically identical queries hit the same cache entry even if the bytes differ — for example, JSON with different whitespace or key order can be treated as the same query. That means a CDN can genuinely cache your search results, something that was never safely possible with POST-based search.

Real use cases

  • Search and filter APIs — the obvious one. Complex faceted search with dozens of parameters, sent as structured JSON instead of a 4,000-character query string.
  • GraphQL — GraphQL reads have been sent over POST since the beginning, sacrificing HTTP caching entirely. QUERY finally gives GraphQL queries the read semantics they always had in spirit.
  • Database-style endpoints — Elasticsearch/OpenSearch _search, SQL-over-HTTP services, and analytics engines that accept full query documents.
  • Batch lookups — "give me these 800 SKUs" as a JSON array in the body, retryable and cacheable.
  • Privacy-sensitive reads — medical, legal, or financial searches where query terms must never appear in access logs or browser history. (The same reason you shouldn't paste production tokens into random websites — which is why our JWT decoder runs entirely in your browser.)

Why it took so long

The idea isn't new — the IETF HTTP working group draft (draft-ietf-httpbis-safe-method-w-body) went through years of iterations, and an even older attempt was called SEARCH (borrowed from WebDAV). The hard problems were never the method itself but the details this guide just covered: how caches should key on a body, how normalization works without changing meaning, and how servers advertise supported query formats. RFC 10008, published as a Proposed Standard in June 2026, is the answer to those questions.

Interestingly, the ecosystem started moving early: Node.js has been able to parse QUERY requests since early 2024, well before the RFC was final.

Should you use it today?

On the server: if you control both ends (internal services, your own API + SDK), yes — the semantics are valuable immediately, and runtimes like Node already parse it. Add Accept-Query to your responses and route QUERY like a body-carrying GET.

On the public web: check your chain first. Every CDN, load balancer, WAF, and framework between the client and your handler needs to pass the method through. Adoption is catching up fast in 2026, but a stray proxy that rejects unknown methods still shows up. The graceful pattern is: try QUERY, fall back to POST on a 405.

What not to do: don't use QUERY for anything that changes state. The whole value of the method is its promise of safety — a "QUERY" that mutates data breaks caching and retry assumptions in ways that will corrupt data eventually. And treat query bodies with the same injection paranoia as any other input: a safe method is not a safe parser.

FAQ

Is QUERY replacing GET? No. Simple reads with a handful of parameters should stay on GET — it's simpler, universally supported, and prefetchable. QUERY is for reads whose parameters are too large, too structured, or too sensitive for a URL.

Is it just POST with a different name? Semantically, it's the opposite of POST. The name tells every cache, proxy, retry layer, and monitoring tool that this request is safe to retry and safe to cache. POST tells them the opposite. Same wire format, completely different promises.

Do browsers support it? fetch() sends custom methods fine, so QUERY works from browser JavaScript today (with CORS preflight cross-origin). What browsers won't do is generate QUERY from HTML forms or address-bar navigation — it's an API method, not a document-navigation method.

What happens if a server doesn't support it? You'll typically get 405 Method Not Allowed (or 501 from older servers). Well-behaved clients detect that and fall back to the POST pattern.

Where's the official spec? RFC 10008 at the RFC Editor and the IETF datatracker page.


If you work with APIs daily, the practical takeaway is simple: the next time you catch yourself designing a POST /search endpoint, you now have a semantically honest alternative. And while you're testing your query payloads, our JSON formatter now runs full-width with large editors — built for exactly the kind of big query documents QUERY was invented for.