Skip to content

/commands/curl/curl-post-json

curl POST JSON: send a JSON body with curl

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · curl 8.21.0 (x86_64-w64-mingw32) libcurl/8.21.0 Schannel zlib/1.3.2updated
tool
curl
versions
curl 7.82+, curl 8.x
os
linux, macos, windows

To POST JSON with curl, pass the body with -d and set the content type yourself: curl -H 'Content-Type: application/json' -d '{"name":"Ada"}' URL. Since curl 7.82.0, --json '{"name":"Ada"}' does the same in one option and also sets Accept: application/json. Without the header, -d sends Content-Type: application/x-www-form-urlencoded, which many APIs reject.

Example against a local server

A small Node.js server prints what it receives:

bash
cat > server.js <<'EOF'
const s = require("http").createServer((req, res) => {
  let body = "";
  req.on("data", (c) => (body += c));
  req.on("end", () => res.end(`${req.method} type=${req.headers["content-type"]} accept=${req.headers["accept"]} body=${body}\n`));
});
s.listen(4310, "127.0.0.1");
setTimeout(() => process.exit(0), 5000);
EOF
node server.js &
sleep 1
URL=http://127.0.0.1:4310/users
curl -s -d '{"name":"Ada"}' "$URL"
curl -s -H 'Content-Type: application/json' -d '{"name":"Ada"}' "$URL"
curl -s --json '{"name":"Ada"}' "$URL"
echo '{"name":"Grace"}' > user.json
curl -s --json @user.json "$URL"

Output

POST type=application/x-www-form-urlencoded accept=*/* body={"name":"Ada"}
POST type=application/json accept=*/* body={"name":"Ada"}
POST type=application/json accept=application/json body={"name":"Ada"}
POST type=application/json accept=application/json body={"name":"Grace"}

The first request shows the wrong default content type; the others send JSON correctly. @file reads the body from a file, and @- from standard input.

Options

OptionEffect
-d, --data DATASend DATA as the body of a POST (strips newlines when reading from a file)
--data-binary @fileSend the file exactly as it is, newlines included
--json DATALike --data-binary plus Content-Type and Accept set to application/json (curl 7.82.0+)
-H "Content-Type: application/json"Set the content type explicitly
-X PUT / -X PATCHUse another method with the same body options
-f / --fail-with-bodyExit with code 22 on HTTP 4xx/5xx; --fail-with-body also prints the response

Quoting on Windows

In cmd.exe, single quotes are not quote characters, so escape the double quotes inside the JSON: curl -H "Content-Type: application/json" -d "{\"name\":\"Ada\"}" URL. In PowerShell, curl may be an alias of Invoke-WebRequest in Windows PowerShell 5.1; call curl.exe explicitly. Reading the body from a file with @user.json avoids quoting problems in every shell.

Sources