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
- Pick Escape to make text safe for embedding in JSON, or Unescape to decode a string copied out of a JSON document.
- Paste your text — conversion is live, and detected control characters are listed with visible symbols (␊ ␉) before escaping.
- Toggle options as needed: surrounding quotes, \uXXXX for all non-ASCII (for ASCII-only pipelines), or escaped forward slashes for legacy HTML embedding.
- 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
| Character | Escape | Required? |
|---|---|---|
| Double quote " | \" | Always |
| Backslash \ | \\ | Always |
| Line feed, tab, CR, FF, BS | \n \t \r \f \b | Always (short forms) |
| Other controls U+0000–U+001F | \u0000 \u0001 … \u001f | Always |
| 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
- JSON Formatter & ValidatorFormat, validate, and beautify JSON in your browser — instant error messages with line numbers, 2 or 4-space indent, minify mode, and copy.
- YAML Validator / LinterValidate YAML in your browser with line-numbered errors — catch indentation mistakes, tabs, and duplicate keys in Kubernetes and CI configs.
- .htpasswd GeneratorGenerate .htpasswd lines for Apache and nginx basic auth — bcrypt or MD5-crypt hashes computed locally, your password never touches a server.
- Hash Generator (MD5/SHA-1/SHA-256/SHA-512)Generate MD5, SHA-1, SHA-256, and SHA-512 hashes from text or files instantly — computed in your browser, nothing is ever uploaded.
- Aspect Ratio CalculatorCalculate aspect ratios and missing dimensions — lock 16:9 or any ratio and solve width or height for video, images, and responsive design.
- Base64 ⇄ Image ConverterConvert Base64 to an image and images to Base64 data URIs in your browser — instant preview, PNG, JPG, WebP and SVG support, nothing uploaded.