Method · safe · idempotent
> QUERY /contacts HTTP/1.1> Host: example.org> Content-Type: application/x-www-form-urlencodedHTTP QUERY Method: Safe Requests With a Body (RFC 10008)
HTTP QUERY is a safe, idempotent method with the query in the body. RFC 10008 status, an example exchange, caching rules, and why GET with a body fails.
- Safe
- Yes
- Idempotent
- Yes
- Cacheable
- Yes (key includes the body)
- Request body
- Yes, required
- Response body
- Yes
- Spec
- RFC 10008
On this page
TL;DR: QUERY is a safe, idempotent HTTP method whose query goes in the request body. It is now a standard, RFC 10008 (June 2026, formerly
draft-ietf-httpbis-safe-method-w-body), and it exists because GET cannot carry a large or structured query reliably and POST tells every proxy the request might change something.
The gap it fills
You have a search endpoint whose filter is a JSON document, a GraphQL-style query, or a form with hundreds of IDs. Putting it in the URL runs into length limits (see 414) and leaks the query into logs and history. Putting it in a POST body works, but POST is neither safe nor idempotent, so a client cannot automatically retry it after a dropped connection, and shared caches will not reuse the response without extra work. A body on GET is not an escape hatch (see below).
QUERY is defined as safe and idempotent: the RFC says the client does not request or expect any change to the target resource’s state, and that a QUERY can be retried, for instance after a connection failure.
Example exchange
The request is the example from RFC 10008, Appendix A.1; the response body is an illustrative sketch:
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json
select=surname,givenname,email&limit=10
HTTP/1.1 200 OK
Content-Type: application/json
[
{ "surname": "Smith", "givenname": "John", "email": "smith@example.org" },
{ "surname": "Jones", "givenname": "Sally", "email": "sally.jones@example.com" }
]
Points from the specification:
- Content is required, and the server must fail the request if
Content-Typeis missing or inconsistent with the content. An unsupported media type gets 415. - The body is not an arbitrary payload: its meaning is defined by its media type and the target resource, such as a form encoding, a JSON query document or SQL.
- A response may include
Content-Locationpointing at a resource where the result can be fetched with a plain GET, andLocationpointing at a resource that repeats the same query without resending the body. A303 See Othersays the query can be answered by a normal retrieval of theLocationURI. - Servers can advertise supported query formats with the
Accept-Queryresponse field, a structured-fields list of media types.
Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
Caching
QUERY responses are cacheable. The difference from GET is the key: RFC 10008 section 2.7 requires that the cache key for a QUERY request incorporate the request content and related metadata. A cache may normalize insignificant differences before keying, such as removing content encoding or applying format conventions like +json, but that only changes the key; the request forwarded upstream is untouched. Standard freshness rules (Cache-Control, Vary) still apply to the response.
Practically, a CDN or reverse proxy that does not know QUERY will not cache it, and may refuse or mishandle it. Do not assume your edge supports the method because the RFC exists.
Why GET with a body is unreliable
RFC 9110 section 9.3.1 says content in a GET request has no generally defined semantics, cannot change the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling vector. In practice:
- Browsers will not do it.
fetchfails withTypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.in Chrome. - Proxies and CDNs differ: some strip the body, some forward it, some return an error. A cache that keys on the URL treats two different bodies as the same request.
- Some HTTP libraries, and tools such as API gateways and WAFs, drop or reject it.
QUERY gives the body defined semantics, so none of this is guesswork.
Using it today
- Check the
Allowheader orAccept-Querybefore relying on it; servers that do not know the method answer 405 or 501. - From a browser,
fetch(url, { method: 'QUERY', body })sends the method name as written. It is not a CORS-safelisted method, so a cross-origin call triggers a preflight and the server must listQUERYinAccess-Control-Allow-Methods. - Keep a POST fallback for clients and intermediaries that cannot pass QUERY through, and say so in your API docs.
curl -i -X QUERY https://api.example.com/contacts \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'select=surname,givenname,email&limit=10'
Related
QUERY keeps the guarantees of GET and the body of POST. For the decision between those two today, see GET vs POST.
Frequently asked questions
What is the HTTP QUERY method?
QUERY is a method that asks the target resource to process the request body as a query, safely and idempotently, and respond with the result. It gives you POST-style bodies with GET-style guarantees, so clients and proxies may retry it and caches may store its responses.
Is QUERY an official standard?
Yes. It was developed as draft-ietf-httpbis-safe-method-w-body and published as RFC 10008 (Proposed Standard) in June 2026. Older articles that call it a draft or an experiment are out of date, though support in servers, proxies, CDNs and client libraries is still uneven.
Why not just send a body with GET?
RFC 9110 says content in a GET request has no defined semantics and some implementations may reject the request or close the connection because of request-smuggling risk. Browsers refuse to send it at all: fetch throws "Request with GET/HEAD method cannot have body". Caches also key on the URL alone, so two different GET bodies can collide.
How is QUERY cached?
The cache key must include the request body and related metadata, so identical queries can hit the cache and different ones cannot collide. RFC 10008 also lets a cache normalize insignificant differences such as content encoding before keying, which only affects the key, not the request sent upstream.
How do I know a server supports QUERY?
A server can advertise it with the Accept-Query response header, which lists the media types it accepts for QUERY, for example Accept-Query: "application/jsonpath", application/sql;charset="UTF-8". Otherwise expect 405 or 501 from servers that do not know the method, and check the Allow header.
Sources
Related
HTTP GET Method: Complete Guide with Examples
Learn how the HTTP GET method works. Understand when to use GET requests, query parameters, caching, and best practices with real-world examples.
HTTP POST Method: Complete Guide with Examples
Learn how the HTTP POST method works. Understand when to use POST requests, request bodies, form submissions, and API calls with practical examples.
Idempotent
Learn what idempotent means in HTTP. Understand why GET, PUT, and DELETE are idempotent, why POST is not, and how idempotency affects API design.
HTTP HEAD Method
Learn how HTTP HEAD requests retrieve resource metadata (headers) without downloading the body. Useful for checking existence, size, and modification dates.