Encoding / Decoding

JSON String Escape

Escape or unescape strings for JSON (\n \" \uXXXX).

Original string
JSON Escape Result

What is JSON Escape?

JSON escape handles special characters in JSON strings, ensuring they can be safely included in JSON data. This tool escapes and unescapes JSON string content.

Escaped Characters

  • Backslash (\) → \\
  • Double quote (") → \"
  • Newline → \n
  • Tab → \t
  • Carriage return → \r

Use Cases

  • Embedding strings with special characters in JSON
  • API request/response handling
  • Configuration file editing

Turns plain text into the escape sequences a JSON string literal needs, covering the quote, the reverse solidus and the control characters, and turns those sequences back into the characters they stand for. Useful before pasting text into a JSON field value, when reading escaped log lines, or when a payload was escaped twice and stops parsing.

What RFC 8259 actually forces you to escape

Inside a JSON string, RFC 8259 section 7 makes exactly three things illegal: the quotation mark ", the reverse solidus \, and the 32 control characters U+0000 through U+001F. Five of those controls have short aliases, \b for U+0008, \t U+0009, \n U+000A, \f U+000C and \r U+000D, while the other 27 must be written as \u00XX with four hex digits. Everything else may appear raw: CJK text, emoji, the forward slash. The surplus is where failures start. JavaScript accepts escapes that JSON rejects, so \x41 or \0 make Node answer Bad escaped character in JSON, and a real tab left inside a quoted string answers Bad control character in string literal.

Escape the backslash first, or you escape twice

Order decides correctness. Rewrite newlines before doubling backslashes and each \ just inserted is escaped again, so \n degrades into \\n, which JSON reads as a literal backslash followed by the letter n. The backslash pass has to run first, then quotes, then the remaining control characters. Unescaping needs the same single-pass discipline: \\n and \n must stay distinguishable, and a chain of replaces cannot promise that. Nesting is the other common shape. A JSON document stored as a string value has every quote and backslash doubled, so {"a":"x\ny"} becomes "{\"a\":\"x\\ny\"}"; escape it a second time and the payload still parses, but it now holds the two characters backslash and n instead of a line break.

Unescaping: one pass, four hex digits, lone surrogates

The decoder is one regular expression: a backslash followed by one of " \ / b f n r t, or by u and exactly four hex digits. Anything else is copied through untouched, so \x41 or a dangling final backslash survives silently; unlike JSON.parse, the tool never reports that its input was not valid JSON. The u branch maps each four-digit value through String.fromCharCode, one UTF-16 code unit at a time. A surrogate pair such as \ud83d\ude00 therefore reassembles into 😀, but a lone \ud83d stays unpaired in the string and becomes U+FFFD, the three UTF-8 bytes EF BF BD, the moment the text is written out.

Worked example

Unescaping a Windows path that carries a tab and two Chinese escapes

Input
C:\\Users\\dev\\app\t\u4e2d\u6587
Output
C:\Users\dev\app	中文

The input is string content, not a document: the four doubled backslashes collapse to single ones, \t becomes one real tab byte (U+0009) rather than two literal characters, and \u4e2d\u6587 becomes 中文. That is 33 characters in and 19 out. Because the scan finishes in one pass, a backslash produced by unescaping is never reinterpreted, which is exactly why \\t and \t end up different.

Limits and pitfalls

  • Escape mode returns the inner content only, with no surrounding quotes, so pasting it into a document as a value fails until you add the " pair yourself.
  • The encode direction never rewrites non-ASCII characters into \uXXXX sequences; CJK output stays raw, so a transport that mishandles UTF-8 needs a separate unicode-escaping pass.
  • The component applies no input-size cap and recomputes synchronously on every keystroke, so a multi-megabyte single-line log will stall the panel.
  • Unescape mode copies unrecognised escapes such as \x41 or a dangling \ through unchanged and reports nothing, so a half-decoded string looks like a success.
  • U+0008 is the one control character whose short form \b collides with the regex word-boundary token, so a backspace must be matched as the literal code point and the round trip checked with JSON.parse before the output is trusted.

Related tools

Six things people call "escape this string", and which side of the trade each one wants

What you need to end up withJSON string escape (this page)Where the job is actually easier
A value you can paste into a .json file as-isEncode returns the inner content only. Typing Hello gives back escape text with no surrounding quotation marks, and the copy button copies exactly that, so a paste between two quotes is still your job — forget the pair and the file fails to parse.In a browser console or Node, JSON.stringify("Hello") hands back the finished literal with its quotation marks attached. Take stringify when the output has to be a complete value; stay here when you are assembling the body by hand and only need the escape text.
Proof that what you escaped still parsesThere is no error channel. Unescape copies anything it does not recognise — \x41, a trailing \ — straight through, and encode cannot fail on any input, so a populated output pane is not a validity check.Read it back through a parser and let it complain: JSON.parse('"' + escaped + '"') throws with the offending position, and the JSON formatter page shows the same text with surrounding context. Validate on the parse side, rewrite on this side.
Making \u4e2d\u6587 and \n readable inside a log lineUnescape is one regex pass over the whole line, so \n, \" and four-digit \uXXXX resolve together in a single click — and the sequences it cannot resolve stay silent.When only \uXXXX should be decoded and a literal \n must stay two visible characters, the Unicode escape page is the narrower instrument: it touches \u and \U and nothing else. The decision is simply whether backslash-n ought to become a real line break.
Output that has to survive a 7-bit-only link (LDAP DN, an old mail gateway)Non-ASCII passes through raw: 中文 stays 中文, an emoji stays an emoji. Only the quote, the reverse solidus and the 32 control characters are rewritten, so this page cannot produce an all-ASCII payload.The Unicode escape page in UTF-16 mode writes every code unit as \uXXXX, and Python gets the same shape from json.dumps(s, ensure_ascii=True). Switch tools the moment the transport is known to mangle UTF-8.
A whole document stored as one string valueOne paste, one direction, one copy: a .json document goes in, escape text comes out, and the outer quotation marks are still missing. Any slip only surfaces later, as a parse error in the consumer.jq -Rs . < payload.json reads the file as raw text and prints a complete JSON string literal — quotes included, newlines already escaped. For anything that is already a file, the shell is one step instead of three.
Forty field values at once, exported from a spreadsheetOne input box, no file picker, no batch list, no column mode. Forty values means forty paste-and-copy rounds, each recomputed synchronously on every keystroke.Ten lines of Node or Python over the export — rows.map(r => JSON.stringify(r)), or json.dumps(row) — finishes the batch in one run and keeps results aligned with their source rows. Repetition belongs in a script.

Every escape this tool writes and reads, character by character

Character (code point)What encode writesWhat unescape turns it into
Double quote " (U+0022)\"The quote itself, U+0022
Reverse solidus \ (U+005C)\\One backslash, U+005C
Line feed LF (U+000A)\nA real 0x0A byte — an actual line break in the pane
Carriage return CR (U+000D)\rA real 0x0D byte
Tab TAB (U+0009)\tA real 0x09 byte
Form feed FF (U+000C)\fA real 0x0C byte
Backspace BS (U+0008)\u0008, four lowercase hex digitsU+0008; on the way back \b is accepted too
Vertical tab VT (U+000B)\u000bU+000B; \v is not accepted
Forward slash / (U+002F)Left alone: //; an incoming \/ also resolves to /
Every other C0 control (U+0000–U+001F)\u00xx, lowercase hexThat code point; uppercase hex such as \u001F is accepted as input
Any non-ASCII character (中, 😀)Written raw, never escapedReturned unchanged
\x41, \u41, \U0041Never produced by encodeLeft exactly as typed, with no warning

The first six rows are all two-for-one: one character in, two characters out, one back. U+0008 is the exception, because the backspace step in encode is written as /\b/g — in a regular expression that is the zero-width word-boundary assertion, not the U+0008 code point. Each boundary between a letter, digit or underscore and anything else therefore gains a literal \b: Hello encodes to \bHello\b, while a genuine backspace falls through to the control-character branch and becomes \u0008. Text with no Latin letters, such as 中文, passes through untouched. Hex is always four lowercase digits — \u000b, not \u000B.

Frequently Asked Questions

How is JSON escaping different from URL encoding?
JSON escaping defines how characters are written inside a JSON string literal: quotes become \", newlines \n, control characters \uXXXX. URL encoding defines how characters travel inside a URL (%20 form). When a JSON payload goes into a query parameter, apply both: JSON-escape first, then URL-encode.
Why is Chinese sometimes escaped as \uXXXX and sometimes left as-is?
Both forms are valid JSON with identical meaning. Raw UTF-8 output is smaller and readable; \uXXXX survives transport chains with broken encoding assumptions. If an older API garbles Chinese, try enabling unicode escaping.
Which characters must be escaped in JSON?
The mandatory set: \" and \\, plus every control character U+0000–U+001F (\n, \r, \t have short forms; the rest must be \u00XX). Forward slashes never need escaping, though escaping them is legal.

Content reviewed: