The HTTP QUERY Method: Finally, a Home for Safe, Body-Based Requests
For as long as most developers have been building APIs, we've had exactly two tools for reading data from a server: GET and POST. Neither one was ever quite right for complex, read-only requests. In June 2026, the IETF closed that gap by publishing RFC 10008, which defines a new HTTP method called QUERY. It's a small addition to the protocol with an outsized impact on how REST API design will evolve over the next few years.
This article walks through why QUERY exists, how it differs from GET and POST, what it looks like in practice, and what implementation actually requires today.
The Problem: GET Wasn't Built for Complexity
GET has always had the right semantics for reading data: it's safe (no server-side side effects), idempotent (repeating it changes nothing), and cacheable by default. The trouble is that GET has no defined semantics for a request body, so every parameter has to be packed into the URL:
GET /posts?author=jane&tag=technology&tag=science&sort=recent&status=published&min_likes=50
This breaks down in a few concrete ways:
- Unpredictable size limits. A request can pass through several uncoordinated intermediaries — load balancers, proxies, CDNs — each with its own cap. RFC 9110 only recommends 8,000 octets as a floor, not a guarantee.
- Awkward encoding of structured data. Nested filters, arrays, and arbitrary JSON don't map cleanly onto query-string syntax. Developers end up inventing bracket notation or JSON-in-a-query-param hacks.
- Logging exposure. URLs are far more likely to be logged, cached in browser history, or captured in access logs than request bodies, which is a poor fit for sensitive filter criteria.
- Readability collapse. A ten-parameter filter with nested boolean logic becomes an unreadable wall of encoded text.
Why POST Became the Workaround
Because of these limitations, teams building complex search functionality have long reached for POST instead:
POST /search HTTP/1.1
Content-Type: application/json
{
"author": "jane",
"tags": ["technology", "science"],
"sort": "recent",
"filters": {
"status": "published",
"min_likes": 50
}
}
This works, but it's semantically dishonest. POST is defined as neither safe nor idempotent, so nothing in the protocol tells a cache, proxy, retry mechanism, or monitoring tool that this particular POST is actually just a read. Caches skip it. Browsers won't prefetch it. Automatic retries on network failure are risky, because the client can't assume it's safe to resend. The workaround solves the body problem but throws away GET's safety guarantees in the process.
Introducing QUERY
QUERY is designed to close exactly this gap. As the RFC describes it, a QUERY request asks the target resource to process the enclosed content in a safe and idempotent manner and return the result — the same safety model as GET, but with a request body like POST.
QUERY /posts HTTP/1.1
Host: example.org
Content-Type: application/json
Accept: application/json
{
"author": "jane",
"tags": ["technology", "science"],
"sort": "recent",
"filters": {
"status": "published",
"min_likes": 50
}
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"results": [
{ "id": 4821, "title": "Why REST still matters", "author": "jane" },
{ "id": 4790, "title": "A tour of query languages", "author": "jane" }
],
"count": 2
}
Because the query criteria lives in the body rather than the URL, structured, deeply nested filters are just JSON — no encoding gymnastics required.
How QUERY Differs From GET and POST
Safe, idempotent, cacheable
No body support
Body support
Not safe, not idempotent
Body support
Safe, idempotent, cacheable
The key distinction is that safety and idempotency for QUERY are protocol-level guarantees, defined by the method's registration, not conventions a client has to trust blindly. A generic HTTP client, cache, or proxy can treat any QUERY request as safe to retry, prefetch, or cache — the same way it already treats GET — without needing resource-specific knowledge.
QUERY also introduces a discovery mechanism: the Accept-Query response header lets a resource advertise that it supports QUERY and which media types it accepts, so clients don't have to guess or trial-and-error their way past a 405 Method Not Allowed.
HTTP/1.1 200 OK
Accept-Query: application/json, application/x-www-form-urlencoded
Real-World Examples
Search APIs
QUERY /search HTTP/1.1
Content-Type: application/json
{
"query": "distributed systems",
"filters": { "language": "en", "published_after": "2025-01-01" },
"page": 1,
"page_size": 20
}
Analytics Dashboards
Dashboards often need to send large, nested filter objects — date ranges, segment definitions, dimension breakdowns — that are painful to express as query strings.
QUERY /analytics/events HTTP/1.1
Content-Type: application/json
{
"metric": "active_users",
"date_range": { "start": "2026-06-01", "end": "2026-06-30" },
"group_by": ["country", "device_type"],
"filters": { "plan": ["pro", "enterprise"] }
}
Reporting Systems
QUERY /reports/revenue HTTP/1.1
Content-Type: application/json
{
"fiscal_quarter": "2026-Q2",
"breakdown": ["region", "product_line"],
"compare_to_previous_period": true
}
Filtering Large Datasets
QUERY /inventory/items HTTP/1.1
Content-Type: application/json
{
"category": "electronics",
"in_stock": true,
"price_range": { "min": 100, "max": 500 },
"attributes": { "brand": ["acme", "globex"], "rating_min": 4 }
}
Social Media Applications
A social network with advanced post search is a natural fit for QUERY. Consider a platform like a community-driven social app that lets users filter posts by author, hashtags, engagement thresholds, media type, and date range simultaneously. Today, that typically means either a truncated GET with a handful of parameters, or a POST endpoint that quietly breaks caching and retry semantics. QUERY lets such a platform express rich, nested filter logic as JSON while still allowing CDNs and edge caches to cache popular queries (say, "top posts about a trending topic this week") the same way they would a GET request — something a POST-based search endpoint can't offer without custom-built caching logic.
QUERY /posts/search HTTP/1.1
Content-Type: application/json
{
"hashtags": ["launchday"],
"min_likes": 100,
"media_type": "video",
"posted_after": "2026-07-01",
"exclude_muted_authors": true
}
GET vs POST vs QUERY
| Aspect | GET | POST | QUERY |
|---|---|---|---|
| Primary purpose | Retrieve a resource | Submit data / trigger processing | Retrieve data via structured, safe request |
| Request body support | No | Yes | Yes |
| Safety | Safe | Not safe | Safe |
| Idempotency | Idempotent | Not idempotent | Idempotent |
| Typical use cases | Simple lookups, static resources | Form submission, resource creation, ad hoc "search" workaround | Complex search, filtering, reporting, analytics |
| Cache behavior | Cacheable by default | Not cacheable by default | Cacheable, but cache key must include body |
| URL limitations | Constrained by intermediary URI length limits | Not applicable (params in body) | Not applicable (params in body) |
Implementation Considerations
Servers and Frameworks
Frameworks need explicit routing support for a method beyond the usual GET/POST/PUT/DELETE/PATCH set. Node.js's core HTTP parser has been able to recognize the QUERY method since early 2024, ahead of standardization, but higher-level framework support (Express, Fastify, Django, Spring) is still rolling out and often requires a small amount of manual wiring today.
Proxies, Gateways, and WAFs
Reverse proxies, API gateways, load balancers, and web application firewalls frequently enforce method allowlists written before QUERY existed. Because QUERY carries a body, it needs the same content inspection (SQL injection, XSS, payload size limits) that a POST body receives — its "safe" designation only refers to server-side side effects, not to the trustworthiness of its content.
Caches
Caching QUERY responses correctly requires including a hash of the request body in the cache key, not just the URL and headers. A cache that only keys on the URL (as it might for GET) risks serving one user's query results to another — a cache poisoning or cache deception risk that implementers need to actively design against.
Browsers
QUERY is not a CORS-safelisted method, so browser-based JavaScript issuing cross-origin QUERY requests will trigger a CORS preflight, just as a custom-header POST or a PUT would.
const response = await fetch('https://api.example.org/posts/search', {
method: 'QUERY',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hashtags: ['launchday'],
min_likes: 100
})
});
const data = await response.json();
Node.js and Express Example
Express doesn't yet expose a first-class .query() routing verb, but QUERY can be handled today with minimal glue code:
const express = require('express');
const app = express();
app.use(express.json());
// Manual QUERY method support
app.use((req, res, next) => {
if (req.method === 'QUERY') {
return handleQuery(req, res);
}
next();
});
function handleQuery(req, res) {
const { hashtags, min_likes, media_type } = req.body;
const results = postsDatabase.filter(post => {
const matchesTags = !hashtags || hashtags.every(t => post.hashtags.includes(t));
const matchesLikes = !min_likes || post.likes >= min_likes;
const matchesMedia = !media_type || post.mediaType === media_type;
return matchesTags && matchesLikes && matchesMedia;
});
res.set('Accept-Query', 'application/json');
res.json({ results, count: results.length });
}
app.listen(3000);
Note that Node's underlying HTTP server must be configured to parse QUERY as a recognized method with a body, since Express's default routing layer assumes bodies only arrive on POST, PUT, and PATCH.
Current State of Adoption
It's worth being direct about where things stand: RFC 10008 was published as a Proposed Standard only in June 2026, and ecosystem support is still catching up. As of writing:
- Node.js has been able to parse QUERY at the HTTP protocol layer since before standardization, but most frameworks require manual routing support.
- OpenAPI 3.2 has a defined place to document QUERY operations, but tooling that generates client/server code from those specs is uneven.
- Major CDNs and cloud proxies have not uniformly rolled out QUERY-aware caching or routing rules yet.
- Browser
fetch()implementations generally allow issuing a QUERY request, but developer tooling (DevTools, HTTP clients) support varies. - Corporate firewalls, older API gateways, and WAF rule sets written before mid-2026 frequently don't recognize QUERY as a distinct method and may reject it outright.
This means GET and POST will remain the dominant methods for read-and-filter operations for the foreseeable future. QUERY is best treated as an emerging option to adopt deliberately and incrementally, not a drop-in replacement to roll out overnight.
When Should You Use QUERY?
- Your API needs to express complex, nested, or variable-length filter criteria that don't fit comfortably in a URL.
- You want safe-request guarantees (cacheability, retry-safety) for what is fundamentally a read operation, and POST's ambiguity around side effects is a genuine concern for your clients or infrastructure.
- You control or can influence both ends of the request — client and server — and can verify that intermediaries between them (proxies, gateways, WAFs) either support QUERY or can be configured to pass it through safely.
- You're designing a new endpoint and can afford to offer QUERY as an addition alongside an existing GET or POST option, rather than a hard replacement.
It's premature to use QUERY as the only way to reach an endpoint. A safer rollout pattern is to expose a QUERY endpoint alongside an existing POST-based search endpoint, advertise support via Accept-Query, and let clients migrate as their own tooling catches up.
Potential Challenges
- Intermediary compatibility. Many proxies, load balancers, and firewalls have method allowlists that predate QUERY and may reject or mishandle it.
- Cache correctness. Any cache implementation needs to be updated to key on request body content, not just the URL, or it risks serving stale or mismatched results.
- Security tooling gaps. WAFs and intrusion detection systems tuned for GET/POST/PUT/DELETE patterns need explicit rules for QUERY bodies; otherwise inspection coverage has a blind spot.
- CSRF assumptions. Because QUERY is "safe" by specification, it's easy to assume it needs no CSRF protection — but any endpoint that layers side effects onto a nominally safe method still needs the usual scrutiny.
- Tooling maturity. Client libraries, API documentation generators, and testing tools built around the conventional method set will need updates before QUERY feels like a first-class citizen in day-to-day development.
Conclusion
QUERY fills a real, long-standing gap in HTTP: a method that's safe and idempotent like GET, but that can carry a structured request body like POST. For search APIs, analytics dashboards, reporting systems, and platforms with advanced filtering — including social applications that need to search and filter large volumes of posts efficiently — it offers a semantically honest way to express complex read requests without sacrificing cacheability or retry safety.
That said, this is infrastructure-level change, and infrastructure-level change is slow by nature. Servers, proxies, caches, browsers, and security tooling all need to catch up before QUERY can be relied on as more than an experimental addition. For the near term, GET and POST will remain the workhorses of API design, with QUERY appearing first in newer endpoints, greenfield projects, and platforms willing to adopt it deliberately and test it thoroughly before depending on it in production.


