# How to Use an Axios POST Request to Send Form Data to an Express Server

> Learn how to send form data with an Axios POST request to your Express server. Discover how to use URLSearchParams or FormData and configure express.urlencoded middleware for seamless data handling.

- Repository: [expressjs/express](https://github.com/expressjs/express)
- Tags: how-to-guide
- Published: 2026-02-12

---

**Use `URLSearchParams` for simple key-value pairs or `FormData` for multipart uploads, ensuring your Express server uses `express.urlencoded()` middleware to parse the payload into `req.body`.**

Sending form data from a client to a server is a fundamental pattern in web development. When using an **axios POST request to send form data** to an Express.js backend, you must align the client-side encoding with the server-side parsing middleware. This guide references the actual implementation in the `expressjs/express` repository to show you the proper configuration.

## Understanding Form Data Encoding Types

Before writing code, you need to choose the correct payload format. The two primary standards for HTML form submission are `application/x-www-form-urlencoded` for simple key-value pairs and `multipart/form-data` for binary data like files. Your choice determines which Axios API to use and which Express middleware must be active.

## Sending Simple Form Data with URLSearchParams

For standard text fields, the `URLSearchParams` interface provides a clean, native way to construct an `application/x-www-form-urlencoded` payload. Axios automatically detects this object and sets the `Content-Type: application/x-www-form-urlencoded` header for you.

```javascript
import axios from 'axios';

const params = new URLSearchParams();
params.append('username', 'bob');
params.append('email', 'bob@example.com');

axios.post('http://localhost:3000/login', params)
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

```

### Express Server Configuration

On the server side, the `express.urlencoded()` middleware parses this payload. According to the source code in [`lib/express.js`](https://github.com/expressjs/express/blob/main/lib/express.js), this middleware is a thin wrapper around the **body-parser** library's `urlencoded` parser. The test suite in [`test/express.urlencoded.js`](https://github.com/expressjs/express/blob/main/test/express.urlencoded.js) validates that the middleware correctly populates `req.body` with the submitted fields.

```javascript
import express from 'express';
const app = express();

// Enable parsing of urlencoded bodies
// Source: lib/express.js
app.use(express.urlencoded({ extended: true }));

app.post('/login', (req, res) => {
  // req.body contains { username: 'bob', email: 'bob@example.com' }
  console.log(req.body);
  res.send('Received');
});

app.listen(3000);

```

The `extended: true` option instructs the underlying `qs` library to support rich objects and arrays, while `extended: false` uses the simpler `querystring` library.

## Handling Multipart Form Data and File Uploads

When you need to transmit files or binary data, you must use `multipart/form-data` encoding. In this scenario, `URLSearchParams` is insufficient; you need the `FormData` API. Unlike `URLSearchParams`, Axios does not automatically set the `Content-Type` header for `FormData` because the boundary string must be calculated by the browser or the `form-data` polyfill.

```javascript
import axios from 'axios';

const form = new FormData();
form.append('title', 'My Photo');
form.append('photo', fileInput.files[0]); // Browser File object

axios.post('http://localhost:3000/upload', form, {
  headers: { 'Content-Type': 'multipart/form-data' }
})
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

```

Note that `express.urlencoded()` does **not** parse `multipart/form-data`. For this content type, you need a dedicated parser such as **multer** or **formidable**. The example below uses `multer` to handle the file stream and text fields:

```javascript
import express from 'express';
import multer from 'multer';
const upload = multer();
const app = express();

app.post('/upload', upload.single('photo'), (req, res) => {
  // req.body contains text fields
  console.log(req.body.title);
  // req.file contains the binary data
  console.log(req.file.originalname);
  res.send('File received');
});

app.listen(3000);

```

## Alternative: Manual Query String Encoding

For environments where you need explicit control over serialization options—such as defining array formats or delimiter characters—you can use the `qs` library to manually construct the payload string before sending your **axios POST request to send form data**.

```javascript
import axios from 'axios';
import qs from 'qs';

const data = qs.stringify({ 
  username: 'bob', 
  tags: ['admin', 'editor']
});

axios.post('http://localhost:3000/login', data, {
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

```

This approach bypasses `URLSearchParams` and allows you to specify encoding parameters that match your server's expectations.

## Summary

- Use `URLSearchParams` for simple `application/x-www-form-urlencoded` payloads; Axios automatically sets the correct `Content-Type` header.
- Use `FormData` for `multipart/form-data` when transmitting files or binary data; you must manually set the `Content-Type` header or let the browser set it with the proper boundary.
- Configure your Express server with `express.urlencoded()` (exported from [`lib/express.js`](https://github.com/expressjs/express/blob/main/lib/express.js)) to parse urlencoded bodies into `req.body`.
- For multipart uploads, use `multer` or similar middleware instead of `express.urlencoded()`.
- For advanced serialization control, use the `qs` library to manually stringify objects before sending.

## Frequently Asked Questions

### Does Axios automatically set Content-Type for form data?

Axios automatically sets `Content-Type: application/x-www-form-urlencoded` when you pass a `URLSearchParams` object as the request body. However, when using `FormData` for multipart uploads, you must explicitly set the `Content-Type: multipart/form-data` header or allow the browser to set it automatically with the correct boundary string.

### What is the difference between URLSearchParams and FormData?

`URLSearchParams` creates an `application/x-www-form-urlencoded` payload suitable for simple key-value pairs of text data. `FormData` constructs a `multipart/form-data` payload that supports binary files, streams, and complex field structures. Choose `URLSearchParams` for login forms and search queries; use `FormData` for image uploads and file transfers.

### Why is my Express req.body empty when receiving form data?

An empty `req.body` typically indicates that the `express.urlencoded()` middleware is not active, or that the client sent `multipart/form-data` without the server using a compatible parser like `multer`. Ensure you have called `app.use(express.urlencoded({ extended: true }))` before your route handlers, and verify that the `Content-Type` header in the request matches the parser configuration as tested in [`test/express.urlencoded.js`](https://github.com/expressjs/express/blob/main/test/express.urlencoded.js).

### Can I send files using URLSearchParams instead of FormData?

No, `URLSearchParams` only supports string values and cannot encode binary file data. To upload files to an Express server, you must use `FormData` on the client side and a multipart parser such as `multer` on the server side. Attempting to append a File object to `URLSearchParams` will result in the string `"[object File]"` being transmitted instead of the actual file content.