JSON Escaping
JSON escaping rewrites characters that would otherwise terminate or corrupt a string. RFC 8259 makes two escapes mandatory — " and \ — then adds five named control escapes, one optional slash escape, and the universal \uXXXX form. This guide covers every escape, the surrogate pairs behind emoji, and when escaping helps or hurts.
La guía de abajo solo está disponible en inglés.
JSON Escaping explained
Every JSON string lives between two double quotes, so the format needs a way to put a double quote inside a string without ending it — and a way to put a backslash inside a string without starting an escape it never intended. The answer is escaping: a backslash placed before a character changes that character's meaning for the parser, turning a structural mark into ordinary data.
The scheme is small and closed. RFC 8259 defines exactly nine two-character escapes plus one extensible form, \uXXXX, and nothing else: a backslash followed by any other character is a syntax error, not a lenient pass-through. That closedness is a feature — escaping bugs are always reproducible, because a conforming parser either recognises the sequence or rejects the document.
This guide walks the full escape table, then the two parts people find hardest: \uXXXX and the surrogate pairs it needs for emoji, and the size trade-off of escaping non-ASCII text. Every example is copyable, and the linked tools run in your browser, so you can round-trip your own strings locally without installing anything.
The quickest way to see escaping work is to watch a parser resolve it — the JSON Formatter renders the unescaped result beside your input as it re-indents a document.
Escaping is one chapter of the grammar; the JSON syntax cheat sheet compresses the rest of the rules — structure, whitespace, numbers — onto a single reference page.
The two escapes you can never skip
Inside a string, a literal double quote must be written as " and a literal backslash as \\. These two are mandatory for every producer, because without them a parser cannot tell where a string ends or where an escape begins — there is no alternative spelling available. Every other escape in the grammar is optional in the sense that its character could have been written literally; these two have no literal form inside a string at all.
The forward slash is the special case: \/ is legal and means /, but the literal slash never needs escaping. The shorthand exists for one historical reason — embedding JSON inside HTML <script> blocks, where the sequence </script> inside a string could close the surrounding tag early. Some generators still escape every slash defensively; the cost is a slightly larger, slightly noisier document.
Mandatory and optional escapes in one document
{
"path": "C:\\temp\\notes.txt",
"line": "she said \"ship it\"",
"html": "<\\/script>"
}What a parser delivers
path: C:\temp\notes.txt line: she said "ship it" html: </script>
The five named control characters
Text may legally contain control characters below U+0020 — tab, newline, carriage return and friends — but a raw control character inside a JSON string is not interoperable: it breaks line-based tooling and some parsers outright. The standard therefore requires control characters to be escaped, and names five of them: \b backspace (U+0008), \f form feed (U+000C), \n line feed (U+000A), \r carriage return (U+000D) and \t horizontal tab (U+0009). Any other control character must take the \u00XX form, such as \u0001.
Note what this means for newlines specifically: a pretty-printed document has real line breaks between tokens, but a line break inside a string value is always the two characters \n. A string value occupies a single line in the file even when its content is multi-line — one of the most common points of confusion when reading formatted JSON.
| Escape | Code point | Character |
|---|---|---|
| \b | U+0008 | backspace |
| \t | U+0009 | horizontal tab |
| \n | U+000A | line feed (newline) |
| \f | U+000C | form feed |
| \r | U+000D | carriage return |
| \u00XX | U+0000–U+001F | any other control character |
A three-line note stored in one JSON string
{
"note": "first line\nsecond line\ttabbed"
}Its content after parsing
first line second line tabbed
\uXXXX: any code point, exactly four hex digits
The \u escape writes a code point as exactly four hexadecimal digits: \u00e9 is é, \u4f60 is 你, \u0041 is the same A you could have typed literally. Parsers treat the escaped and literal forms as identical — a document that escapes every non-ASCII character and one that escapes nothing but the mandatory two decode to the very same strings. Escaping is a transport decision, not a data difference.
The four digits cap the form at code points up to U+FFFF, the Basic Multilingual Plane. Everything above that — emoji, historic scripts, most symbols — cannot fit in one \u escape, and that limitation is exactly where surrogate pairs enter the story.
Two spellings of the same value
{
"city": "\u5317\u4eac",
"note": "escaped form"
}
{
"city": "北京",
"note": "literal UTF-8"
}Both parse to the same string
city: 北京 (the escaped file is ASCII-only; the literal file is smaller but multi-byte)
Astral plane: surrogate pairs and lone surrogates
Internally, JavaScript and the \u notation work in UTF-16 code units. Characters above U+FFFF are written as a pair: a high surrogate from U+D800–U+DBFF followed by a low surrogate from U+DC00–U+DFFF. The grinning face U+1F600 therefore becomes \ud83d\ude00 — twelve source characters for one emoji. Escape one half without the other and you have a lone surrogate: RFC 8259 §8.2 flags such strings as unpredictable to interpret, and interoperable producers simply never emit them.
Surrogate pairs are also why string length lies. JavaScript reports the length of "😀" as 2, because it counts UTF-16 code units rather than characters — a detail that matters when you slice, truncate or validate escaped text, and the reason grapheme-aware libraries exist.
One emoji, two code units, twelve escaped characters
{
"mood": "\ud83d\ude00"
}
{
"mood": "😀"
}Both parse to the same single character
mood: 😀 (U+1F600 — length 2 in UTF-16 units)
The cost of escaping: readability and size
Escaping trades readability for safety. A document that escapes every non-ASCII character survives any 7-bit channel — gateways that strip the eighth bit of every byte, legacy mail systems, logs configured as pure ASCII — at the price of being nearly unreadable to humans. That was the default posture of many early JSON libraries; modern defaults prefer literal UTF-8 and escape only what the grammar requires.
The size cost is predictable from the code point, because every \uXXXX escape costs exactly 6 bytes regardless of what it encodes. Unescaping a CJK-heavy document roughly halves it; Arabic and Cyrillic text shrinks by about two-thirds; and escaping plain ASCII grows it sixfold — which is why ASCII-escaped payloads from older systems look so much fatter than their actual content.
| Text | Code point | Literal UTF-8 | Escaped form | Escaped size |
|---|---|---|---|---|
| a | U+0061 | 1 byte | \u0061 | 6 bytes |
| ب | U+0628 | 2 bytes | \u0628 | 6 bytes |
| а | U+0430 | 2 bytes | \u0430 | 6 bytes |
| 你 | U+4F60 | 3 bytes | \u4f60 | 6 bytes |
| 😀 | U+1F600 | 4 bytes | \ud83d\ude00 | 12 bytes |
Unescaping, round-trips and when to keep escapes
Unescaping is not a separate operation you must write: every conforming parser performs it during decoding, so parsing "\u0041" and parsing "A" produce identical strings. The reverse direction — choosing what to escape when producing JSON — is where libraries differ in taste, and where the only hard rules are the two mandatory escapes plus the control-character requirement.
Keep aggressive escaping for its two honest use cases: surviving channels that cannot be trusted with UTF-8, and diffs where every invisible encoding difference should be visible. Everywhere else, literal UTF-8 with minimal escapes is smaller, faster to scan and easier to review. If a received document looks over-escaped, parse it and re-serialise once — the output sheds every optional escape while remaining exactly the same data.
Frequently asked questions
Is it safe to paste sensitive strings into this site's JSON tools?
Yes — the formatter, validator and minifier linked from this guide all run locally in your browser. There is no upload step: parsing and re-serialising happen in JavaScript inside the tab, the Network panel shows no requests carrying your text, and the site's Content-Security-Policy blocks outbound connections as a second line of defence. Your strings never leave the machine you typed them on.
How do I put an emoji in a JSON string?
Two ways: paste the emoji literally — 😀 is valid UTF-8 JSON — or write its surrogate pair, \ud83d\ude00. Both decode to the same character. The escaped form is worth knowing because some channels and older tooling mangle literal emoji, and because error messages, logs and diffs often show you the pair instead of the face.
What is a lone surrogate and why does it break parsers?
A high surrogate (\ud800–\udbff) or low surrogate (\udc00–\udfff) written without its partner. Alone it encodes nothing: RFC 8259 §8.2 calls strings containing them unpredictable to interpret. Implementations vary — some accept them, some replace them with U+FFFD, some throw — so never emit half a pair, and treat a lone surrogate in incoming data as corruption.
Why is \/ a valid escape when / needs no escaping?
It exists for embedding JSON in HTML: inside a <script> block, the literal sequence </script> in a string would end the block early, so generators escape each slash as \/ to break up the pattern. The grammar accepts the unescaped form equally. Unless you are embedding JSON in HTML, \/ is pure noise — and minifiers remove it happily.
Does escaping change the data my API receives?
No. Escapes are spellings, not values: "\u00e9" and "é" decode to the identical string, so any conforming parser delivers the same Unicode text either way. Escaping changes only what the file looks like and how large it is — which is why an over-escaped response is ugly but harmless, and why you can normalise it by parsing and re-serialising.
How much smaller is JSON without the \u escapes?
It depends on the script, because each \uXXXX costs 6 bytes while literal UTF-8 costs 1 byte for ASCII, 2 for Arabic or Cyrillic letters, 3 for CJK and 4 for emoji. Unescaping a Chinese document roughly halves it; Arabic or Cyrillic shrinks by about two-thirds; escaping ASCII grows sixfold. The escaped form is always equal or larger.
Which related tools should I use next?
- JSON FormatterIndent, sort keys and strip comments with configurable output.Open
- JSON Syntax Cheat SheetPlain-English guideOpen
- What Is JSONPlain-English guideOpen
- JSON MinifierStrip whitespace and measure the real gzip wire size.Open
- JSON ValidatorValidate syntax with exact line and column, and repair it in one click.Open
- Encoding ToolsBase64, URL encoding, hashing and token inspection.Open