cURL
JSON

How do I POST JSON data with cURL?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Posting JSON with curl is mostly about sending the correct request body and telling the server what format that body uses. The minimal pattern is to set the Content-Type header to application/json and pass the JSON document with -d.

Basic POST Request

A standard JSON request looks like this in a Unix shell:

bash
1curl -X POST \
2  -H "Content-Type: application/json" \
3  -d '{"name":"Alice","age":30}' \
4  https://example.com/api/users

These flags do the important work:

  • '-X POST chooses the HTTP method'
  • '-H sets a request header'
  • '-d sends the request body'

In many cases curl infers POST automatically when -d is present, but writing -X POST makes the command explicit and easier to read.

Send JSON From A File

Inline JSON is fine for small payloads, but it gets messy once the document grows. A file is more maintainable.

Create data.json:

json
1{
2  "name": "Alice",
3  "age": 30,
4  "admin": false
5}

Then send it with:

bash
1curl -X POST \
2  -H "Content-Type: application/json" \
3  -d @data.json \
4  https://example.com/api/users

The @ prefix tells curl to read the body from a file instead of from the command line.

Include Authentication Headers

APIs often require a token or API key in addition to the JSON body.

bash
1curl -X POST \
2  -H "Content-Type: application/json" \
3  -H "Authorization: Bearer YOUR_TOKEN" \
4  -d '{"title":"example"}' \
5  https://example.com/api/items

This pattern works for most bearer-token APIs. If the server expects another header format, keep the JSON body the same and change only the authentication header.

See The Request And Response Details

When a server rejects your JSON, the fastest next step is to make curl verbose.

bash
1curl -v -X POST \
2  -H "Content-Type: application/json" \
3  -d '{"title":"example"}' \
4  https://example.com/api/items

Verbose mode shows request headers, response headers, TLS negotiation details, and the status line. That is usually enough to tell whether the problem is authentication, content type, routing, or malformed JSON.

Windows Quoting Differences

On Windows, shell quoting can trip people up. In PowerShell, single quotes are often the easiest way to protect JSON containing double quotes.

powershell
1curl -X POST `
2  -H "Content-Type: application/json" `
3  -d '{"name":"Alice","age":30}' `
4  https://example.com/api/users

If quoting becomes painful, use a file and -d @data.json instead. That removes most shell-specific escaping issues.

Content-Type Versus Accept

Content-Type tells the server what you are sending. Accept tells the server what response format you would like back.

bash
1curl -X POST \
2  -H "Content-Type: application/json" \
3  -H "Accept: application/json" \
4  -d '{"name":"Alice"}' \
5  https://example.com/api/users

You often want both, but only Content-Type is required to describe the JSON request body.

Common Pitfalls

The most common mistake is forgetting the Content-Type: application/json header. Some servers then treat the body as plain form data or reject it outright.

Another mistake is malformed shell quoting. If the shell changes your quotes before curl sees them, the server receives broken JSON. Using a file is the safest fix.

A third issue is confusing -d with multipart upload options such as -F. -F builds a multipart/form-data request, which is different from a raw JSON body.

Summary

  • Use -H "Content-Type: application/json" and -d to send JSON with curl.
  • Inline JSON works for small payloads, but @file.json is easier to maintain.
  • Add authentication headers separately when the API requires them.
  • Use -v to debug rejected requests.
  • If shell quoting is a problem, move the JSON into a file and post that file.
  • 'Accept: application/json can help when an API varies its response format.'

Course illustration
Course illustration

All Rights Reserved.