JSON String Escaping Rules: The Complete Guide (RFC 8259)
Dev Tools

JSON String Escaping Rules: The Complete Guide (RFC 8259)

Introduction: A JSON String Is Simpler Than It Looks — Until You Hit a Quote or a Newline

A JSON string looks like the most trivial part of the format: some text between two double quotes. In practice, strings are where most hand-written JSON breaks. A stray quote inside the text, a real newline pasted from a spreadsheet, a tab character copied from a terminal, or an emoji that a library encoded wrong — any of these produces a parser error or, worse, silently corrupted data. This guide covers the complete rules for JSON strings exactly as defined by RFC 8259, the current Internet Standard for the JSON data interchange format.

RFC 8259 (published December 2017, and designated STD 90) is short and precise about strings. Once you understand its handful of rules, string escaping stops being guesswork. This article is the strings-only companion to our guide on RFC 8259 object syntax, which covers objects, keys, and members. If you also want conventions for building real APIs on top of these primitives, read JSON best practices for API development. To check any example here, paste it into our JSON formatter — it validates and pretty-prints entirely in your browser.

The Basic Shape: Strings Are Delimited by Double Quotes

Every JSON string begins and ends with a double quote character (", U+0022). Single quotes are never valid string delimiters in JSON, no matter how common they are in JavaScript or Python source code. This is one of the most frequent mistakes when people assume JSON is "just JavaScript object literals" — it is not. 'hello' is invalid; "hello" is valid.

Between the opening and closing quotes, a string is a sequence of Unicode characters. Most characters may appear literally and unescaped. Three categories of characters, however, either must be escaped or may optionally be escaped:

  • The double quote (") must be escaped, otherwise it would terminate the string early.
  • The backslash (\\) must be escaped, because it is the escape-introducing character itself.
  • Control characters in the range U+0000 through U+001F must be escaped — a literal control character inside a string is not allowed.

Everything else — letters, digits, punctuation, spaces, accented characters, CJK ideographs, emoji — may be written literally as long as the document is valid UTF-8. You do not have to escape an accented é or a Chinese character; you only must escape the three categories above.

The Backslash Escapes: The Two-Character Sequences

RFC 8259 defines a fixed set of short escape sequences. Each begins with a backslash followed by exactly one character. There are exactly eight of these two-character escapes, plus the six-character \\u escape covered later. The full set of two-character escapes is:

  • \\" — quotation mark (U+0022)
  • \\\\ — reverse solidus, i.e. the backslash itself (U+005C)
  • \\/ — solidus, i.e. the forward slash (U+002F)
  • \\b — backspace (U+0008)
  • \\f — form feed (U+000C)
  • \\n — line feed / newline (U+000A)
  • \\r — carriage return (U+000D)
  • \\t — character tabulation / tab (U+0009)

A backslash may only be followed by one of these characters (", \\, /, b, f, n, r, t) or by a u introducing a Unicode escape. Any other sequence — for example \\x41, \\a, or \\' — is not valid JSON. Notably, \\' (an escaped single quote) is invalid in JSON even though it is common in other languages, because the single quote never needs escaping in the first place.

The Curious Case of the Forward Slash

The forward slash escape, \\/, surprises many developers. The forward slash does not need to be escaped — a literal / is a perfectly valid character inside a JSON string. RFC 8259 simply permits it to be escaped as \\/ as an option. Why allow an optional escape for a character that never requires one? The historical reason is HTML embedding: escaping the slash lets you write the sequence <\\/script> so that a JSON string embedded inside an HTML script element cannot accidentally close that element. So "http://example.com" and "http:\\/\\/example.com" are both valid and represent the identical string. Most encoders leave the slash unescaped; some, for HTML-safety, escape it.

Control Characters: U+0000 Through U+001F Must Be Escaped

This is the rule that trips up copy-paste the most. Any character in the range U+0000 to U+001F — the C0 control characters — cannot appear literally inside a JSON string. They must be escaped, either using one of the named short escapes above (for the ones that have them) or using a \\u escape.

The most common offenders are invisible whitespace-like control characters that get pasted in from other tools:

  • A real newline (line feed, U+000A) pasted from a multi-line text field must become \\n. A raw newline inside the quotes is a parse error.
  • A real tab (U+0009), often copied from spreadsheets or terminal output, must become \\t.
  • A carriage return (U+000D), common in text that originated on Windows, must become \\r.

Control characters that have no named escape must be written with the six-character Unicode form. For example, the NUL character (U+0000) is written \\u0000, the escape character (U+001B, used in ANSI terminal color codes) is written \\u001b, and the unit separator (U+001F) is written \\u001f. There is no \\0 shorthand in JSON — that is a C and JavaScript convention, not a JSON one. Always use \\u0000 for a null character.

Note the boundary: the rule covers U+0000 through U+001F inclusive. The space character U+0020 is not a control character and needs no escaping. The DEL character (U+007F) is, perhaps surprisingly, not required to be escaped by RFC 8259 — it sits above the control range the grammar restricts — though many encoders escape it anyway for safety.

JSON String Escaping Rules: The Complete Guide (RFC 8259)

Unicode Escapes: The \\uXXXX Form

Any character can be represented by a Unicode escape: a backslash, a lowercase u, and exactly four hexadecimal digits giving the character's code point. For example, \\u0041 is the letter A (U+0041), and \\u00e9 is é (U+00E9). The hexadecimal digits may be uppercase or lowercase — \\u00E9 and \\u00e9 are equivalent — but there must always be exactly four of them. \\uE9 (two digits) is invalid; you must pad to \\u00e9.

Unicode escapes are optional for most characters. You can write the letter A literally, or as \\u0041; both are valid and identical. Encoders that want to guarantee pure-ASCII output often escape every non-ASCII character this way, which is why you sometimes see "caf\\u00e9" instead of "café" in API responses — both decode to the same string. This ASCII-only escaping is a safe transport choice and never changes the meaning of the data.

Surrogate Pairs: Characters Above U+FFFF

The four-hex-digit \\u form can only directly encode code points up to U+FFFF, the top of the Basic Multilingual Plane. Characters beyond that — most emoji, many historic scripts, mathematical alphanumeric symbols — have code points above U+FFFF and cannot fit in four hex digits. JSON solves this using UTF-16 surrogate pairs, exactly as UTF-16 does internally.

A character above U+FFFF is represented as two consecutive \\u escapes: a high surrogate in the range \\uD800 to \\uDBFF, immediately followed by a low surrogate in the range \\uDC00 to \\uDFFF. Together the pair encodes one character. For example, the musical symbol G clef (U+1D11E) is written \\uD834\\uDD1E, and the "grinning face" emoji (U+1F600) is written \\uD83D\\uDE00.

Two things follow from this. First, a lone surrogate — a high surrogate not followed by a low one, or a low surrogate with no preceding high one — is technically ill-formed. RFC 8259 notes that such characters are permitted by the grammar but warns that they may not interoperate; robust software treats an unpaired surrogate as a red flag. Second, of course, you can also just write the emoji literally in a UTF-8 document. "😀" and "\\uD83D\\uDE00" are the same string; the escaped form only exists for when you need a pure-ASCII representation.

Common Escaping Mistakes

Nearly every JSON string error falls into one of a few recurring patterns. Recognizing them saves hours of debugging.

1. An Unescaped Quote Ends the String Early

Writing "She said "hi"" is invalid — the second quote closes the string, and the parser then chokes on the unexpected hi. The fix is to escape the inner quotes: "She said \\"hi\\"". This is by far the most common JSON string bug.

2. Windows Paths and Single Backslashes

A Windows path like C:\\Users\\Ana written naively as "C:\\Users\\Ana" in a source string is a trap: each \\U and \\A is an invalid escape. In JSON every literal backslash must be doubled: the correct JSON string is "C:\\\\Users\\\\Ana". Similarly, a regular expression like \\d+ must be written "\\\\d+" inside JSON.

3. Pasting Real Newlines and Tabs

Multi-line text pasted directly between quotes leaves literal line feeds and tabs in the string, which are forbidden control characters. Every real newline must become \\n and every real tab \\t. Serialization libraries do this automatically; the problem only appears in hand-edited JSON.

4. Using Single Quotes as Delimiters

JSON strings must use double quotes. {'name': 'Ana'} is not JSON, even though it is a valid JavaScript object literal. Change every string delimiter to a double quote.

5. Wrong Escape Letters or Bad \\u Length

Invented escapes such as \\x41, \\0, or \\a do not exist in JSON, and a \\u escape with fewer than four hex digits (\\u1F) is invalid. Only the eight named escapes and the four-digit \\u form are legal, plus properly formed surrogate pairs for astral characters.

6. Double Encoding

Serializing an already-serialized JSON string produces a string full of \\" where you expected real structure, for example "{\\"name\\":\\"Ana\\"}" — a JSON string whose contents happen to be JSON, not a JSON object. This usually means a value was JSON.stringify-ed twice. Decode once and inspect whether you have a string or an object.

Escaping Keys Follows the Same Rules

An object member name (a key) is itself a JSON string, so every rule above applies identically to keys. A key containing a quote, a backslash, or a control character must escape it, and keys use double quotes just like values. For the full grammar of objects, members, and how keys relate to values, see the companion article on RFC 8259 object syntax. In practice, well-designed keys avoid special characters entirely, but the format permits them as long as they are escaped correctly.

Verifying Strings with Our JSON Formatter

The fastest way to confirm a string is escaped correctly is to run it through a validator that implements the RFC 8259 grammar. Our JSON formatter and validator parses your input against the standard and reports the exact position of any illegal character — an unescaped quote, a raw control character, a malformed \\u escape, or a broken surrogate pair. Because it runs entirely in your browser, you can safely paste strings that contain credentials, tokens, or user data without transmitting anything to a server.

When you need to enforce string content beyond mere syntax — a minimum length, a pattern, an enumerated set of allowed values — pair the formatter with our tooling and a schema. For the broader set of conventions that keep JSON payloads consistent across an API, the JSON best practices guide picks up where the raw string rules leave off. Master the escape set here — the eight backslash escapes, the \\u form, surrogate pairs, and the control-character rule — and the string-level bugs that plague hand-written JSON simply stop happening.

← Back to Blog