ToolForge
How-toJSON

How to Escape Strings in JSON

Escaping one string for JSON takes a second: quotes and backslashes get a backslash, real line breaks become the two characters backslash-n. Then someone asks you to put a JSON document inside a JSON field, or send a payload through curl, and suddenly you are counting backslashes and losing.

The escapes themselves are [tabulated in the syntax reference](/articles/json-syntax-guide). This is about the layers — where the difficulty actually is.

Written by toolforge.websitePublished Last reviewed How we build and check these tools

What escaping is actually doing

A JSON string is delimited by double quotes, which creates one problem: the string cannot contain an unescaped double quote, or the parser would think it had ended. The same applies to the backslash, because the backslash is what marks an escape.

So escaping is bookkeeping for delimiters. One layer of quoting means one round of escaping:

You want the string to containYou write
She said "hi""She said \"hi\""
C:\Users\ada"C:\\Users\\ada"
Two lines"line one\nline two"
A tab"col\tcol"

The critical thing to hold onto is that the backslashes are not in your data. "She said \"hi\"" is the JSON representation of a string whose actual content is She said "hi" — five characters shorter. Parse it and the backslashes vanish, because they were never part of the value. Every confusion later in this article comes from losing track of that distinction.

Which means: if you are writing code, do not escape by hand. Your language's serialiser does it correctly, including the control characters you would forget. Hand-escaping is for pasting a value into a file, a form field or a curl command.

Escaping a string

For a one-off — a certificate, a SQL query, a paragraph with quotes in it — mechanical is better than careful.

  1. Paste the raw text into the escape tool, in Escape mode.

    Raw means exactly as it appears in its natural form: real line breaks, real quotes, no escaping applied yet.

  2. Copy the escaped result.

    Quotes and backslashes are now prefixed, and line breaks and tabs have become their two-character escapes.

  3. Paste it between the quotes of your JSON string value.

    The tool escapes the contents; it does not add the surrounding quotes, so those are yours to supply.

  4. Parse the finished document to confirm.

    A round trip through a parser is the only real proof — the eye is not reliable past about two backslashes.

  5. To go the other way, switch to Unescape.

    That converts an escaped string back to its raw contents, which is how you read a value that arrived over-escaped.

JSON inside JSON: the case everyone gets wrong

Storing a JSON document inside a JSON string field is common — a webhook payload kept in a log, a config blob in a database column, a message body inside an envelope. It is also where the backslashes multiply.

Start with the inner document:

{"name":"Ada"}

To put that inside a string field, every double quote in it needs escaping:

{"payload":"{\"name\":\"Ada\"}"}

The inner quotes are now backslash-quote. Nest it once more — an envelope containing the envelope — and each of those escapes gets escaped in turn, so a single quote becomes backslash-backslash-quote and the document becomes genuinely hard to read:

{"outer":"{\\"payload\\":\\"...\\"}"}

Two rules make this manageable.

Never build it by hand. Serialise the inner value, then treat the result as an ordinary string and let the serialiser escape it when you serialise the outer object. In JavaScript that is JSON.stringify applied twice, and the doubling happens correctly without you counting anything.

Unwrap one layer at a time. Given a mystery string full of backslashes, parse it once and look at what you get. If the result is still a string full of quotes, parse that. Each parse peels exactly one layer, and counting the parses tells you how deep the nesting went. The number of backslashes doubles per layer — one, two, four — so a run of four backslashes means somewhere upstream a value was serialised three times.

And a design note worth more than the technique: do not do this if you can avoid it. A nested JSON string is opaque to every query, index and validator that would otherwise help you. If your database supports a JSON column type, use it. If the nesting exists because a service serialises before enqueuing, consider whether the envelope needs to be JSON at all.

Getting a payload through a shell

A failing curl request is usually a shell problem rather than a JSON problem, and the error blames the JSON.

The reliable pattern in Bash is single quotes around the whole payload, because single quotes stop the shell interpreting anything inside them:

curl -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -d '{"name":"Ada","role":"engineer"}'

Use double quotes around the payload instead and the shell starts working on your JSON before curl sees it: $ begins a variable expansion, backticks execute, and the double quotes in your JSON collide with the shell's. That is where the "unexpected end of input" comes from — you sent something other than what you typed.

The awkward case is a payload that itself contains a single quote — a name like O'Brien. The shell has no escape inside single quotes, so you have to close and reopen:

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

Which nobody enjoys. The better answers, in order:

Put the payload in a file. curl -d @payload.json reads it verbatim and the shell never touches the contents. This is the right default for anything longer than one line.

Use a heredoc. A quoted heredoc passes the body through literally, which avoids both quoting layers.

Watch out for PowerShell, where the rules differ again: it parses double-quoted strings itself, and its own Invoke-RestMethod takes an object rather than a JSON string, so JSON pasted from a Bash example frequently needs rework.

And when a value fights you at every layer — binary, unpredictable punctuation, something arriving from a user — Base64-encode it, put the encoded text in the JSON, and decode at the far end. One escape-free layer beats three careful ones.

Embedding JSON in a web page

Putting JSON inside a <script> tag has a hazard that has nothing to do with JSON's rules and everything to do with HTML's.

If any string in your data contains the text </script>, the browser ends the script element there — inside your data — and the rest of the page breaks or, worse, becomes executable. The parser doing this is the HTML parser, which has no idea it is looking at a JSON string.

This is what JSON's optional forward-slash escape is for. \/ means exactly the same as /, so writing <\/script> is identical data that the HTML parser cannot see as a closing tag. Most serialisers offer this, and any templating layer that emits JSON into a page should have it on.

Two related habits:

  • Prefer <script type="application/json"> with the data as its content, read via textContent and parsed. Data in a data island cannot execute.
  • Escape <, > and & as \u003c, \u003e and \u0026 when embedding. All three are valid JSON escapes, all three are invisible to the HTML parser, and the combination removes the whole class of problem.

For structured data specifically — the JSON-LD in a page's head — the same rule applies, which is why serialisers used for that purpose escape these characters by default.

When the backslashes stop making sense

Debugging escaping is really counting layers. Three questions settle almost every case.

Which layer am I looking at? A string displayed in a terminal, a log viewer, a browser console and a database client may each show a different number of backslashes for the same value, because each one applies its own display escaping. The value has not changed; the view has. Never count backslashes in a log viewer and conclude anything.

Does it parse? The only authoritative test. Paste the outer document into the formatter: if it parses, the escaping is correct, whatever it looks like. If it does not, the error position points at the layer that broke.

How many parses does it take? Parse repeatedly until you get something that is not a string. The count is your nesting depth, and the answer to "why does this have eight backslashes" is usually "because something serialised it three times".

The frequent culprit behind mysterious over-escaping is a value that was already a JSON string being serialised again — passing JSON.stringify(payload) to a client library that stringifies its input for you. The fix is to hand it the object, not the string.

The opposite failure, under-escaping, shows up as a parse error rather than as ugly text, and is covered under unescaped characters in the error guide.

JSON Escape / Unescape

Escape and unescape JSON strings. It runs in your browser, so the files never leave your machine, and there is nothing to install or sign up for.

Try the JSON Escape / Unescape

Frequently asked questions

Do I need to escape single quotes in JSON?

No. A single quote is an ordinary character inside a JSON string, so an apostrophe needs nothing done to it. Only the double quote and the backslash are structurally special, along with control characters like newline and tab.

Why does my string have four backslashes?

Because it has been escaped twice. Backslash counts double per layer of escaping — one, two, four, eight — so four means two rounds. Parse it twice and you should reach the real value; if not, something is serialising a string that was already serialised.

Should I escape forward slashes in JSON?

It is permitted and never required. The one place it earns its keep is embedding JSON in an HTML page, where writing <\/script> stops the HTML parser from ending your script tag early. Otherwise a plain slash is fine.

How do I put a newline in a JSON string?

Write the two characters backslash and n. A real line break inside a quoted string is a syntax error, which is why multi-line text has to be escaped before it can be embedded — and why the value looks like one long line when you inspect the JSON.

Is escaping a security measure?

It prevents malformed documents, not attacks. Correct escaping stops a value from breaking out of its string and corrupting the structure around it, which does matter — but it is no substitute for validating input, and it is not related to SQL or HTML injection defences, which need their own handling at their own boundaries.

The short version

One layer of quoting means one round of escaping: quotes, backslashes, and real line breaks. The trouble is always layers — JSON inside JSON, or a shell in the path. Let a serialiser do the escaping, single-quote your curl payloads or put them in a file, escape the angle brackets when embedding in a page, and when the backslashes stop making sense, parse repeatedly and count. If a value resists at every layer, Base64 is not a defeat.

Tools that go with this

Each one is here for a specific reason rather than because it is in the same category.

Popular

JSON Formatter

Format, validate, and beautify JSON online

Open Tool

The check that an escaped payload is still valid once it is embedded — paste the outer document and see whether it parses.

JSON Stringify Tool

Convert JavaScript objects to JSON strings

Open Tool

Serialises a whole value rather than escaping one string, which is the right tool when you are building the document rather than patching it.

JSON Parse Tool

Parse JSON strings into JavaScript objects

Open Tool

Unwraps one layer at a time, which is how you count how many layers of escaping a mystery string actually has.

Base64 Encoder / Decoder

Encode and decode text, files, and images to Base64

Open Tool

The alternative when a value is fighting the escaping at every layer: encode it once and decode at the far end.

Sources

  1. RFC 8259 (STD 90) — The JavaScript Object Notation (JSON) Data Interchange Format

    IETF · Standards organisation · published 1 December 2017 · accessed 7 September 2026

    Cited for: Which characters must be escaped inside a string, and that the forward-slash escape is permitted but optional

  2. JSON.parse() — JavaScript reference

    MDN Web Docs · Technical documentation · accessed 7 September 2026

    Cited for: That parsing removes one layer of escaping, which is the basis of the layer-counting technique

About the author

toolforge.website

Builder and maintainer, ToolForge

Started ToolForge in May 2026 and has built and maintained it since, writing every tool on the site and the documentation that goes with each one.

How we research and check this content · About ToolForge

Part of

JSON

What JSON is, the syntax rules that actually trip people up, why a parser rejected your file, and how JSON compares with XML and YAML.

Browse all developer tools
Buy Me a Coffee