Blog
Wild & Free Tools

Escape JSON for a curl Command — The Practical Guide

Last updated: February 2026 6 min read
Quick Answer

Table of Contents

  1. Bash and zsh — Single Quotes Win
  2. PowerShell and Windows cmd
  3. The File-Based Workaround
  4. When Stuff Still Goes Wrong
  5. When to Skip curl Entirely
  6. Frequently Asked Questions

The fastest way to send JSON in a curl request without escape pain is to put the JSON in a file and use curl --data @body.json. The shell never sees the content; you never have to escape anything. For one-line requests where you want the body inline, here are the patterns that work in each common shell.

Bash and zsh — Single-Quote the JSON

In bash and zsh, single quotes are literal — nothing inside gets interpreted. Wrap your JSON in single quotes and the internal double quotes need no escaping at all.

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alex", "email": "[email protected]"}'

This is the canonical pattern. The only problem character is the single quote itself — if your JSON contains a single quote (in a name, a string field), you have to break out of the single-quoted string and escape it:

-d '{"name": "O'\''Brien"}'

That sequence — '\'' — closes the single quote, escapes a single quote, and reopens the single quote. It's ugly but it's the bash-compliant way. For anything more than one or two single quotes, switch to the file approach.

PowerShell and Windows cmd Are Different

PowerShell has its own quoting rules and they're not the same as bash. The double-quote-and-escape pattern is more common in PowerShell:

curl -X POST https://api.example.com/users -H "Content-Type: application/json" -d "{\"name\": \"Alex\"}"

Or use here-strings for multi-line JSON:

$body = @"
{
  "name": "Alex",
  "email": "[email protected]"
}
"@
curl -X POST https://api.example.com/users -d $body

Windows cmd is even more painful. PowerShell's Invoke-RestMethod is usually a better choice on Windows than command-line curl, since it takes a hashtable that gets converted to JSON automatically. Mixing curl on Windows is mostly worth avoiding.

Sell Custom Apparel — We Handle Printing & Free Shipping

The File-Based Approach (Use This for Complex JSON)

For any JSON that's longer than one line or contains characters that fight the shell, save it to a file:

# body.json
{
  "name": "Alex",
  "bio": "He said \"hi\".",
  "tags": ["a", "b"]
}

# Then curl with --data @file
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d @body.json

The shell never parses the JSON content. Quotes, slashes, single quotes, dollar signs — all literal. This is the most reliable pattern and the one to use any time you're hitting a real API with a non-trivial body.

You can also pipe stdin: cat body.json | curl -d @- ... if you're generating the JSON dynamically.

When Stuff Still Goes Wrong

Three frequent causes of "my curl is sending the wrong body":

1. Trailing whitespace. A trailing newline in your -d argument can confuse some servers. Use --data-binary instead of -d to send exactly what you provide, no normalization.

2. Forgotten Content-Type. Without -H "Content-Type: application/json", curl defaults to application/x-www-form-urlencoded — and many servers will reject your JSON or parse it as form data.

3. Bad escape inside the JSON itself. If your JSON has unescaped quotes, even the file approach won't save you — the JSON parser at the server will reject it. Run the JSON through a JSON formatter to validate before sending.

Use curl -v to see exactly what's being sent. The > lines are your request — verify the body matches what you expect before debugging the server response.

When to Skip curl Entirely

For one-off API exploration, GUI tools handle JSON better than the shell:

curl is the right tool when you're scripting requests in CI or shell pipelines. For interactive API work, the GUI tools save time.

Escape JSON for curl

For when --data @file.json is not an option. Paste JSON, get a shell-safe escaped string.

Open Free JSON Escape / Unescape Tool

Frequently Asked Questions

Why does my curl JSON keep failing with "unexpected token"?

Usually the shell ate or modified your quotes. Use --data @file.json or wrap the JSON in single quotes (bash) and check what curl -v actually sends.

How do I send JSON with a single quote in curl on bash?

Either escape with \'\\'\' (ugly) or save to a file and use --data @body.json (clean).

What is the difference between -d and --data-binary?

-d strips newlines and may transform some characters. --data-binary sends exactly what you give it. Use --data-binary for JSON to avoid surprises.

Can I send JSON without a Content-Type header?

Most servers will reject it or parse it as form data. Always include -H "Content-Type: application/json".

Andrew Walsh
Andrew Walsh Developer Tools & API Writer

Andrew worked as a developer advocate at two SaaS startups writing API documentation used by thousands of engineers.

More articles by Andrew →
Launch Your Own Clothing Brand — No Inventory, No Risk