---
title: "Search with QUERY when the filter outgrows · Agent Wranglers"
url: https://agentwranglers.se/playbook/api-design/lists/query-method
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Search with QUERY when the filter outgrows the address

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/api-design/rules.json) holds every rule of this playbook as JSON.

- Level: Optional
- Chapter: [Lists](https://agentwranglers.se/playbook/api-design/lists)
- Rule: Send a search that is too long for query parameters, or that holds personal data, in the body of a QUERY request. Never send it as a GET with a body.
- How: RFC 10008 defines QUERY as safe and idempotent, like GET, so clients may retry it after a dropped connection. The search travels in the body, which servers and proxies log less often than addresses. That keeps search terms out of logs, as [Keep secrets out of addresses](https://agentwranglers.se/playbook/api-design/api-security/no-secrets-in-urls) asks. List the body types you accept in the `Accept-Query` header. Answer 400 when `Content-Type` is missing, and 415 with `Accept-Query` for a type you don't accept. Answer 422 when the body parses but the search can't run. Send `Location` when the same search can be fetched again with GET. Keep plain parameters for short filters.
- Check: Send the same `QUERY /orders` with a JSON body twice. Both answers are 200 with the same items, and no stored data changed. The request without `Content-Type` gets 400, and one sent as `text/plain` gets 415 with `Accept-Query`.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### HTTP example

```http
QUERY /orders HTTP/1.1
Content-Type: application/json
Accept: application/json

{"customerEmail":"anna@example.com","status":["paid","shipped"],"limit":50}

HTTP/1.1 200 OK
Content-Type: application/json
Accept-Query: application/json

{ "items": [ ... ], "nextCursor": "b3JkXzlhMXo" }
```

### JavaScript example

```js
const response = await fetch('https://api.example.com/orders', {
  method: 'QUERY',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
  body: JSON.stringify({ customerEmail: 'anna@example.com', status: ['paid', 'shipped'], limit: 50 }),
})
```

### Python example

```python
import httpx

response = httpx.request(
    "QUERY", "https://api.example.com/orders",
    headers={"Authorization": f"Bearer {token}"},
    json={"customerEmail": "anna@example.com", "status": ["paid", "shipped"], "limit": 50},
)
```

## Sources

- [RFC 10008 The HTTP QUERY Method](https://www.rfc-editor.org/rfc/rfc10008)
- [RFC 10008 section 2.1 Media Types and Content Negotiation](https://www.rfc-editor.org/rfc/rfc10008#section-2.1)

## Related rules

- [Keep secrets out of addresses](https://agentwranglers.se/playbook/api-design/api-security/no-secrets-in-urls) in API design

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/api-design/lists/query-method">Agent Wranglers API design playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Return empty lists as empty](https://agentwranglers.se/playbook/api-design/lists/empty-lists)
- [Lists](https://agentwranglers.se/playbook/api-design/lists)
