Page & Bell
inside a string would end the script element early. Escaping the slash turns it into <\\/script>, which is harmless. Enable the option only for that embedding case; APIs and files do not need it."}},{"@type":"Question","name":"Why is the unescape error position slightly different from my editor's column?","acceptedAnswer":{"@type":"Answer","text":"The decoder validates by parsing your input as a JSON string literal and reports the zero-based character offset where parsing failed, adjusted for the wrapping quotes it adds internally. Editors usually show one-based columns, and a tab counts as one character here regardless of your tab width. The error message includes twenty characters of context either side of the failure, which is usually faster than counting columns at all."}}]}

JSON Escape / Unescape

A JSON string may contain almost any character — but exactly three things must be escaped: the double quote, the backslash, and every control character from U+0000 to U+001F. Get one wrong and the parser on the other end throws, often with an error position that points somewhere unhelpful. This tool escapes plain text into a valid JSON string body (using the same rules as JSON.stringify) and decodes escaped strings back, surfacing the exact position of any invalid escape. It runs as a single pass with no backtracking, so multi-megabyte single-line strings convert instantly.

Type or paste above — conversion is live.

How to use the json escape / unescape

  1. Pick Escape to make text safe for embedding in JSON, or Unescape to decode a string copied out of a JSON document.
  2. Paste your text — conversion is live, and detected control characters are listed with visible symbols (␊ ␉) before escaping.
  3. Toggle options as needed: surrounding quotes, \uXXXX for all non-ASCII (for ASCII-only pipelines), or escaped forward slashes for legacy HTML embedding.
  4. Use Swap direction to feed the output back as input — a quick round-trip check that escaping and unescaping are symmetric.

The complete escape table

CharacterEscapeRequired?
Double quote "\"Always
Backslash \\\Always
Line feed, tab, CR, FF, BS\n \t \r \f \bAlways (short forms)
Other controls U+0000–U+001F\u0000 \u0001 … \u001fAlways
Forward slash /\/Optional (HTML embedding)
Non-ASCII (é, €, emoji)\u00e9 \u20ac 🔥Optional (ASCII-only pipelines)

Worked example: JSON inside JSON

Webhook payloads, message queues, and audit logs routinely carry a JSON document as a string field of another JSON document. Start with {"event":"signup","name":"O'Brien “OB”"} — note it already contains quotes. Escaped for embedding, the quotes gain backslashes and the document becomes one long string body; embed it again (a log of a log) and every backslash doubles: \" becomes \\\", \n becomes \\n. The reliable way out is mechanical: unescape once per layer of wrapping, never by hand-deleting backslashes. The Swap direction button here exists for exactly this — paste, unescape, swap, and confirm the round-trip reproduces the original.

How \u escapes and surrogate pairs work

A \uXXXX sequence is four hexadecimal digits naming a UTF-16 code unit. For characters up to U+FFFF one unit suffices: \u20ac decodes to €, the euro sign. Characters beyond the BMP are expressed as two consecutive escapes forming a surrogate pair: the code point minus 0x10000 is split into two 10-bit halves, the high half added to 0xD800 and the low half to 0xDC00. U+1F600 (grinning face) therefore becomes 😀. Order matters — a low surrogate before a high one, or either alone, is not valid Unicode text, which is why this tool counts and warns about lone surrogates rather than letting them flow silently into your data.

Frequently asked questions

Which characters must be escaped in a JSON string?

Exactly these: the double quote (\") because it would terminate the string, the backslash (\\) because it introduces escapes, and all 32 control characters U+0000–U+001F. Five controls have short forms — \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return) — the rest need \u00XX. Everything else, including emoji, accented letters, and the forward slash, is legal unescaped. Single quotes never need escaping; that is a JavaScript-string rule, not a JSON rule.

What is double escaping and why does my string end up with \\n?

It happens when JSON is embedded inside a JSON string. Take the object {"msg":"line1\nline2"} and stuff it into another document's string field: the inner quotes become \" and the existing backslash doubles, giving "payload":"{\"msg\":\"line1\\nline2\"}". Each unwrap removes one layer. If you see \\n rendered literally in your UI, you escaped twice but unescaped once — run it through Unescape here and the layers peel off one pass at a time.

When should I escape non-ASCII characters to \uXXXX?

When some hop in your pipeline is not reliably UTF-8: legacy databases with Latin-1 columns, log shippers that mangle bytes, email systems, or config files read with a platform-default charset. \u00e9 survives any ASCII-safe channel, while a raw é depends on every reader honouring the encoding. The cost is size — each non-ASCII character becomes 6 (or 12) bytes — so leave it off when everything speaks UTF-8, which JSON (RFC 8259) requires for interchange anyway.

Why does the escaped output show two \u sequences for one emoji?

JSON \u escapes encode UTF-16 code units, not code points, and characters outside the Basic Multilingual Plane (above U+FFFF) take two units — a surrogate pair. The fire emoji U+1F525 encodes as 🔥: a high surrogate (D800–DBFF) followed by a low one (DC00–DFFF). Parsers recombine the pair on decode. A surrogate appearing alone is malformed Unicode — this tool flags lone surrogates in your input, because some parsers reject them and others silently substitute U+FFFD.

Do forward slashes need escaping in JSON?

No — \/ is permitted but never required by the spec. The convention exists for one historical reason: when JSON is inlined into an HTML <script> block, the byte sequence </script> inside a string would end the script element early. Escaping the slash turns it into <\/script>, which is harmless. Enable the option only for that embedding case; APIs and files do not need it.

Why is the unescape error position slightly different from my editor's column?

The decoder validates by parsing your input as a JSON string literal and reports the zero-based character offset where parsing failed, adjusted for the wrapping quotes it adds internally. Editors usually show one-based columns, and a tab counts as one character here regardless of your tab width. The error message includes twenty characters of context either side of the failure, which is usually faster than counting columns at all.

Related tools

Learn more