x-www-form-urlencoded format
URLSearchParams
By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, you can use the URLSearchParams API, which is supported in the vast majority of browsers,and Node starting with v10 (released in 2018).
const params = new URLSearchParams({ foo: 'bar' });
params.append('extraparam', 'value');
axios.post('/foo', params);Query string Very old
For older browsers or environments without URLSearchParams, you can use the qs library to serialize objects to the application/x-www-form-urlencoded format.
const qs = require('qs');
axios.post('/foo', qs.stringify({ bar: 123 }));For full control over headers and method, pass qs.stringify output as the request data and set Content-Type explicitly:
import qs from 'qs';
const data = { bar: 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url: '/foo',
};
axios(options);In very old versions of Node.js, you can use the built-in querystring module that ships with Node.js. Note that this module has been deprecated in Node.js v16 — prefer URLSearchParams or qs for new code.
const querystring = require('querystring');
axios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));Prefer qs for nested objects
The qs library is preferable if you need to stringify nested objects, as the querystring method has known issues with that use case.
Automatic serialization to URLSearchParams New
Starting from v0.21.0, axios automatically serializes JavaScript objects to URLSearchParams if the Content-Type header is set to application/x-www-form-urlencoded. This means that you can pass a JavaScript object directly to the data property of the axios request config. For example when passing data to a POST request:
const data = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: 'Peter', surname: 'Griffin' },
{ name: 'Thomas', surname: 'Anderson' },
],
};
await axios.postForm('https://postman-echo.com/post', data, {
headers: { 'content-type': 'application/x-www-form-urlencoded' },
});The data object will be automatically serialized to URLSearchParams and sent in the application/x-www-form-urlencoded format. The server will receive the following data:
{
"x": "1",
"arr[]": ["1", "2", "3"],
"arr2[0]": "1",
"arr2[1][0]": "2",
"arr2[2]": "3",
"users[0][name]": "Peter",
"users[0][surname]": "Griffin",
"users[1][name]": "Thomas",
"users[1][surname]": "Anderson"
}If your backend body-parser (like body-parser of express.js) supports nested objects decoding, you will get the same object on the server-side automatically
Depth limit for params serialization
When axios serializes a params object via AxiosURLSearchParams, the same recursive walker used by the FormData serializer is called. A maxDepth option (default 100) limits how deeply it will recurse. Payloads exceeding the limit throw an AxiosError with code: 'ERR_FORM_DATA_DEPTH_EXCEEDED' instead of overflowing the call stack.
// Raise the limit if your params object legitimately nests deeper than 100 levels:
axios.get('/api', { params: deepObject, paramsSerializer: { maxDepth: 200 } });Security note
Only raise maxDepth if your schema genuinely requires it. The default of 100 protects server-side code that forwards client-controlled data to axios as params from DoS attacks via deeply nested objects.
var app = express();
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.post('/', function (req, res, next) {
// echo body as JSON
res.send(JSON.stringify(req.body));
});
server = app.listen(3000);