Behavior of Axios GET request bodies across browsers and servers
0 reputation · 05 May 2023, 20:49 UTC
0 reputation · 05 May 2023, 20:49 UTC
Determine how Axios handles a request body when the HTTP method is GET, given that the HTTP/1.1 specification discourages bodies on GET requests. The question is whether Axios should automatically strip the body or allow it to be sent, and how different environments behave.
Axios currently allows a data payload on GET requests. It is unclear if this should be considered a feature or a bug, and whether a stricter compliance mode should be introduced.
32275 reputation · 06 May 2023, 00:06 UTC
Axios does not strip the data payload from a GET request — it hands the body to whichever adapter is active. What happens next depends on the environment. In a browser, the underlying XHR or Fetch implementation typically refuses or silently drops a body on GET, so the server never sees it. In Node.js, the http module will happily write the body onto the wire, and whether the server reads it is entirely up to that server's implementation. So the behavior you're seeing is neither a clean feature nor a clean bug: Axios is pass-through, and the inconsistency lives one layer below.
Confirmed (well-established behavior):
data in the config for any method, including GET, and passes it to the adapter without filtering by method.fetch(url, {method: 'GET', body: ...}) throws a TypeError. XHR's send() historically ignores the body for GET. Either way, the body does not reliably reach the network in a browser.http.request imposes no such restriction; if Axios supplies a body, it is transmitted with a Content-Length or chunked encoding.Likely explanation for your confusion: you tested in Node (or against a lenient server) and saw the body transmitted, then tested in a browser or behind a proxy and saw it vanish. Both observations are correct; the variable is the transport, not Axios.
Even when the bytes arrive, most production stacks discard them. Nginx as a reverse proxy generally does not forward GET bodies by default. Many frameworks (Express with default body parsers, for example) only parse bodies for methods where they're expected, so req.body stays empty even though the payload was sent. WAFs and strict servers may go further and reject the request outright, since GET-with-body is a classic HTTP request smuggling signal. The result is the worst kind of failure: the client believes it sent data, the server silently ignores it, and nothing errors.
In the browser, open DevTools → Network and inspect the request: a GET issued via Axios with data set will show no payload. In Node, capture the traffic to confirm the body leaves the process:
tcpdump -i any -A 'tcp port 3000' | grep -A5 GET
Or point Axios at a minimal echo server that reads the raw stream:
const http = require('http');
http.createServer((req, res) => {
let b = '';
req.on('data', c => b += c);
req.on('end', () => { console.log(req.method, JSON.stringify(b)); res.end('ok'); });
}).listen(3000);
// elsewhere:
require('axios').get('http://localhost:3000/', { data: { hello: 'world' } });
If the body prints in Node but not via the browser against the same server, you've confirmed the adapter difference directly.
Stripping by default would be a breaking change: a minority of legacy APIs (some Elasticsearch-style query endpoints historically accepted GET bodies) depend on the current pass-through behavior in Node. A reasonable middle ground is what you can do today without waiting for the library: strip it yourself in an interceptor so behavior is identical across environments:
axios.interceptors.request.use(cfg => {
if (cfg.method?.toLowerCase() === 'get' && cfg.data != null) {
cfg.params = { ...cfg.params, ...cfg.data }; // or drop it
delete cfg.data;
}
return cfg;
});
Practical recommendation: treat GET bodies as unsupported. Move the payload to query params, or switch to POST if the payload is large or sensitive. That removes the environment lottery entirely rather than depending on any particular Axios policy.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.