HTTP QUERY: The New Method for Complex API Queries

HTTP QUERY: The New Method for Complex API Queries
For years, developers have worked with the same familiar HTTP methods:
GET, POST, PUT, PATCH, and DELETE.
In June 2026, the HTTP ecosystem gained another standardized method:
QUERY.
Defined by RFC 10008, the QUERY method provides a standardized way to send a query in the request content while keeping the operation explicitly safe and idempotent.
That solves a problem many API developers have already encountered: what do you do when a read/query becomes too large or too complex to comfortably express in a URL?
The familiar approach: GET with query parameters
For simple queries, GET works extremely well.
GET /products?category=phone&brand=apple&page=2&limit=20
This is readable, easy to share, and fits naturally with how HTTP GET works.
For things like:
- Pagination
- Sorting
- Simple filters
- Search keywords
- Small sets of query parameters
GET is still a great choice.
The problem appears when the query itself becomes much more complicated.
When the URL starts getting complicated
Imagine a product dashboard with filters for:
- Multiple categories
- Multiple brands
- Price ranges
- Ratings
- Locations
- Availability
- Multiple sorting rules
- Date ranges
- Nested conditions
- Large lists of IDs
You can technically encode a lot of this into a URL, but it quickly becomes difficult to read and maintain.
For example:
GET /products?category=phone&category=laptop&brand=Apple&brand=Samsung&priceMin=10000&priceMax=150000&ratingMin=4&location=Chennai&location=Salem&sort=price_desc&page=3&limit=50
And more complex query structures often require additional encoding conventions just to represent the data inside the URI.
The HTTP specification also recognizes that URI size limits can become problematic because a request can pass through multiple systems with different constraints. RFC 10008 notes that HTTP implementations are recommended to support at least 8000 octets, but larger requests can still encounter intermediary limitations.
So what have developers traditionally done?
A common solution is to use POST.
For example:
POST /products/search
Content-Type: application/json
{
"filters": {
"category": ["phone", "laptop"],
"brands": ["Apple", "Samsung"],
"price": {
"min": 10000,
"max": 150000
},
"rating": {
"min": 4
},
"locations": ["Chennai", "Salem"]
},
"sort": [
{
"field": "price",
"order": "desc"
}
],
"pagination": {
"page": 3,
"limit": 50
}
}
This works.
In fact, many real-world APIs use exactly this pattern.
But there is a semantic mismatch.
We're using POST because it gives us request content, while the operation itself may simply be asking:
"Give me the data that matches this query."
We're not necessarily creating anything or modifying the resource.
This is the gap that QUERY addresses.
Enter HTTP QUERY
With QUERY, the same idea can be expressed explicitly as a query operation:
QUERY /products
Content-Type: application/json
{
"filters": {
"category": ["phone", "laptop"],
"brands": ["Apple", "Samsung"],
"price": {
"min": 10000,
"max": 150000
}
},
"sort": [
{
"field": "price",
"order": "desc"
}
],
"pagination": {
"page": 3,
"limit": 50
}
}
The important difference isn't simply that the query is now inside a body.
QUERY is a distinct HTTP method with its own semantics.
RFC 10008 defines QUERY as a method for initiating a server-side query where the request content and its media type define the query.
GET vs QUERY
A useful mental model is:
GET
Client
|
| Query parameters
v
/products?category=phone&page=2
|
v
Server
Compared with:
QUERY
Client
|
| Query content
v
/products
{
"category": ["phone"],
"page": 2
}
|
v
Server
The important distinction is where the query is represented.
GET
The query is represented primarily through the URI.
GET /products?category=phone&page=2
QUERY
The query is represented through request content.
QUERY /products
Content-Type: application/json
{
"category": ["phone"],
"page": 2
}
QUERY is not "GET with a body"
This distinction is important.
It is tempting to describe QUERY as:
"GET, but with a larger body."
Technically, that isn't accurate.
QUERY is a new HTTP method with its own semantics.
RFC 10008 explicitly defines QUERY as:
- Safe
- Idempotent
- Cacheable under the HTTP caching rules
- Expected to contain request content
GET is also safe and idempotent, but the methods have different semantics.
In particular, HTTP does not define general semantics for content in a GET request, whereas QUERY explicitly expects the request content to describe the query.
Why not just keep using POST?
You absolutely can.
POST isn't wrong simply because you're performing a query.
The issue is that POST does not inherently communicate that the operation is a safe, idempotent query.
With:
POST /products/search
a client or intermediary cannot determine the complete semantics of the operation from the method alone.
With:
QUERY /products
the method itself communicates that the request is a query operation with safe and idempotent semantics.
That distinction can matter for things such as retries and caching.
The practical mental model
For everyday API development, a useful starting point is:
Simple read
|
v
GET
|
| Query in URI
v
/products?page=2&limit=20
For more complex body-based queries:
Complex read/query
|
v
QUERY
|
| Query in request content
v
/products
{
"filters": {...}
}
For operations that are not safe/idempotent queries:
Create / general operation
|
v
POST
And the other familiar methods continue to have their own roles:
GET → Retrieve a representation
QUERY → Perform a safe, idempotent query
POST → Create or perform a general operation
PUT → Replace a resource
PATCH → Partially modify a resource
DELETE → Delete a resource
This isn't a rule that says every API must follow one exact CRUD mapping. HTTP method semantics are broader than CRUD.
A realistic example: an advanced data table
Imagine a SaaS dashboard containing a large customer table.
A simple request might be:
GET /customers?page=2&limit=25
Then the product grows.
Now the user can filter by:
{
"status": ["active", "trial"],
"countries": ["India", "USA", "UK"],
"revenue": {
"min": 10000,
"max": 500000
},
"signupDate": {
"from": "2026-01-01",
"to": "2026-09-01"
},
"plans": ["pro", "enterprise"],
"sort": [
{
"field": "revenue",
"direction": "desc"
}
]
}
At that point, many teams would naturally create something like:
POST /customers/search
QUERY provides another option:
QUERY /customers
Content-Type: application/json
{
"status": ["active", "trial"],
"countries": ["India", "USA", "UK"],
"revenue": {
"min": 10000,
"max": 500000
},
"signupDate": {
"from": "2026-01-01",
"to": "2026-09-01"
},
"plans": ["pro", "enterprise"],
"sort": [
{
"field": "revenue",
"direction": "desc"
}
]
}
This is the kind of API design where QUERY becomes particularly interesting.
QUERY doesn't require JSON
Another important detail from RFC 10008:
QUERY does not define JSON as its only request format.
The request content's media type defines the query format supported by the target resource.
For example, the RFC demonstrates:
QUERY /contacts
Content-Type: application/x-www-form-urlencoded
Accept: application/json
select=surname,givenname,email&limit=10
It also demonstrates other query formats such as JSONPath and XSLT.
A server can advertise supported query formats using the Accept-Query response header.
For example:
Accept-Query: "application/jsonpath", application/sql
So QUERY is the HTTP-level mechanism.
JSON is just one possible representation of the query.
What about URL length?
This is one of the practical reasons QUERY exists.
A request might travel through several systems:
Browser
|
v
CDN
|
v
Proxy
|
v
Load Balancer
|
v
Web Server
|
v
Application
There isn't one universal practical URI limit that every component shares.
A URL that works through one stack may encounter a limit somewhere else.
There are also other considerations.
URIs are more likely to be logged by intermediaries, and complex query structures can be inefficient to encode into URI syntax.
Moving the query into request content can therefore be useful for both structural and operational reasons.
Should every GET become QUERY?
No.
That would defeat the purpose.
For example:
GET /users?page=2&limit=20
is already clean.
There is little reason to turn it into:
QUERY /users
Content-Type: application/json
{
"page": 2,
"limit": 20
}
The RFC itself notes that if a query is short enough to fit comfortably in a URI, GET is likely the better choice.
A good practical approach is:
Simple query
↓
GET
Large or structured query
↓
QUERY
Create / general operation
↓
POST
The decision should be based on the semantics and shape of the API rather than an arbitrary number of fields.
Is QUERY ready for every production API?
Not necessarily.
The standard is now published, but the HTTP ecosystem is much larger than the specification itself.
For a QUERY-based API to work reliably, the relevant infrastructure needs to understand the method.
That can include:
- Client libraries
- Browsers and Fetch implementations
- Backend frameworks
- Reverse proxies
- CDNs
- API gateways
- CORS configuration
- Observability tools
- Caching infrastructure
RFC 10008 specifically notes that QUERY is not a CORS-safelisted method, so browser-based cross-origin requests can require a CORS preflight.
This means the existence of the standard does not automatically mean you should replace every existing POST /search endpoint today.
Ecosystem support matters.
The bigger idea
The interesting part of QUERY isn't simply:
"HTTP got another method."
It's that HTTP now has a standardized way to express an operation that developers have been implementing for years:
"I need to send a complex query to the server, but I'm not asking the server to change the target resource."
Previously, one common solution was:
POST /search
Now HTTP provides another option:
QUERY /search
That doesn't make POST obsolete.
It doesn't make GET obsolete.
It simply gives API designers another tool when a query is too large or structured for a convenient URI representation.
The HTTP method lineup
A simplified mental model now looks like this:
GET
Simple/resource-oriented retrieval
|
v
QUERY
Safe, idempotent body-based querying
|
v
POST
Creation and general operations
|
v
PUT
Full replacement
|
v
PATCH
Partial modification
|
v
DELETE
Removal
The important thing is not to memorize this as a rigid CRUD table.
Instead, think about the semantics of the operation you're designing.
Final takeaway
If you're building an API today, don't replace every GET with QUERY just because QUERY exists.
Use GET when the query fits naturally into the URI.
Use QUERY when you need a safe, idempotent query whose input is better represented as request content.
And continue using POST when the operation actually fits POST semantics.
The most interesting change is that developers now have a standardized alternative to the familiar pattern of:
POST /search
when the only reason for using POST was:
"We have a large or structured query and need somewhere to put it."
HTTP QUERY gives that use case its own method.
RFC 10008 — The HTTP QUERY Method
Published by the IETF in June 2026.
Ready to elevate your digital presence?
Implement these exact performance standards and luxury aesthetics into your next project.