Every FHIR client that only ever does GET search will hit the URL-length limit eventually. The client that only ever does POST search misses out on browser caches, CDN caches, and the intuitive shape of a bookmarkable query. Both endpoints exist, they behave the same on the response side, and choosing between them is one of the more consequential daily decisions in a FHIR client.
The site's FHIR RESTful API cheatsheet has both forms laid out. For the wider REST context, deeper FHIR walkthroughs collects related pieces.
What They Have in Common
Both are search. Both return a searchset Bundle. Both accept the same search parameters. Both hit the same server-side query engine. The response is identical byte-for-byte between a GET and a POST search for the same parameters.
That is the important base fact. The choice is not about behavior, it is about transport.
Use GET When the Query Is Small and Shareable
The GET form is GET /[type]?param=value¶m=value. It is cacheable by intermediaries, bookmarkable, easy to reproduce from a log line, and it is the default that every browser, curl invocation, and dev tools panel understands. For most everyday searches, GET is the right call.
The downside is URL-length limits. Browsers cap around two thousand characters, most proxies cap similar. A search Bundle with fifty concept identifiers as _id parameters can exceed that fast.
Use POST When the Query Is Long or Sensitive
The POST form is POST /[type]/_search with Content-Type: application/x-www-form-urlencoded and the parameters in the body. FHIR reserves the _search suffix specifically to distinguish search POSTs from create POSTs on the same type endpoint. Same parameters, same response, no URL-length ceiling.
Switch when:
- The parameter set is programmatically generated and can exceed length limits
- The parameters carry PHI you do not want to end up in access logs
- The parameter list is so long it hurts to read as a URL
- A CDN or proxy in the path is truncating long GETs
Any one of those is a switch trigger. Two or more is a strong switch trigger.
The Server Contract Is the Same
The CapabilityStatement declares the search parameters once, and both GET and POST search against them equivalently. A server that supports GET but not POST search is out of spec. A client that assumes POST search will fail on a particular server should test rather than assume.
Do Not Sprinkle Both Freely
The temptation is to fall back from GET to POST automatically when a URL grows too long. That works but confuses the request logs and makes caching behavior inconsistent per endpoint. Pick a rule per endpoint or per query family and stick to it. Automatic fallback is fine as long as it is documented, logged, and testable.
Cache Behavior Is the Big Trade
A GET is cacheable by everything in the request path. A POST is cacheable only if the server explicitly opts in — and most do not. If the same search happens repeatedly and the data does not change often, GET buys real intermediate caching. POST does not.
For teams that also want a peek at how the status codes differ, HTTP status codes FHIR reuses vs redefines covers the response side. For the client-shape implications, designing a FHIR client that survives the tricky verbs is the follow-up.
The Short Version
GET search is the default. POST search is the escape hatch for long or sensitive queries. Same server, same response, different transport tradeoffs. Build the rule per endpoint and encode it in the client, not in every caller.
For the wider picture of where FHIR REST verbs differ from vanilla, the FHIR REST verbs that actually differ from vanilla REST is the entry point.
Sources
- HL7 canonical FHIR search specification defining GET and - HL7 canonical FHIR search specification defining GET and POST variants