UUID Studio

JSON Unicode Escape

Emit ASCII-safe JSON with \u escapes.

  • 🔒 No data stored or uploaded
  • ⚡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Create or edit JSON here (syntax colors), then format, validate, or convert - same as MongoDB $binary UUID blobs on the Convert tab once detected.

New document

About JSON Unicode Escape

JSON strings can write any character as a \uXXXX escape, and this tool converts between the escaped and literal forms. Both are the same data - a parser produces identical strings from "caf\u00e9" and "café" - but which one you emit has real consequences for size, readability and interoperability.

Escaping exists because JSON must survive transports that are not reliably UTF-8 clean. Python's json.dumps escapes all non-ASCII by default (ensure_ascii=True), which is why so much JSON in the wild is full of \uXXXX sequences. That default makes documents with CJK or accented text substantially larger, since one character becomes six.

Two escapes are genuinely mandatory and worth knowing: \u2028 (line separator) and \u2029 (paragraph separator) are valid in JSON strings but are line terminators in JavaScript, so an unescaped one inside a <script> block or a JSONP response is a syntax error. Any serialiser producing JSON for embedding in HTML should escape them.

Characters outside the Basic Multilingual Plane - emoji, rarer CJK, historic scripts - cannot fit a single \uXXXX escape and are written as a surrogate pair: two escapes together, high surrogate D800-DBFF followed by low DC00-DFFF. Splitting or truncating a string between them produces an unpaired surrogate, which is not valid UTF-8 and is what tends to make a database reject the value.

Conversion happens in your browser and nothing is transmitted.

How to use the JSON Unicode Escape

  1. Paste the JSON or string, in either form.
  2. Convert to escaped output when you need pure ASCII for a strict or legacy transport.
  3. Convert to literal output to read what \uXXXX sequences actually say.
  4. Watch for surrogate pairs - emoji arrive as two escapes, and cutting between them corrupts the character.

Examples

  • Unicode text
    {"greeting":"Hello 世界"}

JSON Unicode Escape in code

The same operation this tool performs, in the languages you are most likely to need it.

JavaScript
// Escape all non-ASCII (and the two JS line terminators)
const escapeNonAscii = (s) =>
  s.replace(/[^\x20-\x7E]/g, (c) =>
    "\\u" + c.charCodeAt(0).toString(16).padStart(4, "0")
  );

// Unescaping is just parsing
JSON.parse('"caf\\u00e9"');   // "café"

// Minimum safe escaping for JSON embedded in HTML
const forHtml = (obj) =>
  JSON.stringify(obj)
    .replace(/\u2028/g, "\\u2028")   // JS line terminator
    .replace(/\u2029/g, "\\u2029")
    .replace(/</g, "\\u003c");        // prevents </script> breakout

// Emoji are surrogate pairs - [...str] iterates code points,
// str.length counts UTF-16 units:
"👍".length;        // 2
[..."👍"].length;   // 1
Python
import json

data = {"name": "café", "emoji": "👍"}

# Default: escapes everything non-ASCII
json.dumps(data)                    # '{"name": "caf\\u00e9", ...}'

# Readable UTF-8 output, and smaller
json.dumps(data, ensure_ascii=False)  # '{"name": "café", ...}'

# Unescape
json.loads('{"name": "caf\\u00e9"}')  # {'name': 'café'}

# Python strings are code points, so surrogate pairs are not a
# concern the way they are in UTF-16 languages:
len("👍")   # 1
Command line
# jq outputs literal UTF-8 by default
echo '{"n":"caf\u00e9"}' | jq .

# Force ASCII-only output
echo '{"n":"café"}' | jq -a .

# Find unescaped U+2028/U+2029, which break JSON embedded in <script>
grep -P '[\x{2028}\x{2029}]' file.json

When you need this

  • Reading what a \uXXXX-heavy document from a Python service actually says.
  • Producing ASCII-only JSON for a transport that mangles UTF-8.
  • Shrinking a document full of escapes by re-emitting it as literal UTF-8.
  • Finding an unpaired surrogate that is causing a database insert to fail.
  • Escaping U+2028 and U+2029 before embedding JSON in a <script> block.

Common problems and what causes them

Unpaired surrogates
Characters outside the BMP are two escapes - a high surrogate D800-DBFF then a low DC00-DFFF. Truncating a string to a fixed length can cut between them, producing a lone surrogate that is not valid UTF-8. Databases and strict parsers reject it. Truncate by code point, not by UTF-16 unit.
U+2028 and U+2029 breaking a page
These are valid in JSON strings but are line terminators in JavaScript, so an unescaped one inside a <script> block or JSONP response is a syntax error. Escape them whenever JSON is embedded in HTML.
ensure_ascii inflating a document
Python escapes all non-ASCII by default, so one CJK character becomes six ASCII characters. On a document that is mostly non-Latin text this multiplies the size. Pass ensure_ascii=False when the transport is UTF-8 safe.
Emoji counted as two characters
In UTF-16 languages - JavaScript, Java, C# - "👍".length is 2, because it is a surrogate pair. Length limits, substring operations and reversal all break on it. Iterate code points ([...str], or codePointAt) instead.
Double-escaped output
\\u00e9 with two backslashes is the literal text backslash-u-0-0-e-9, not é. It means a string was escaped twice, or a JSON string containing JSON was serialised without being parsed first.
Mistaking \uXXXX for a different encoding
JSON escapes are UTF-16 code units, not UTF-8 bytes. \u00e9 is one character, whereas the UTF-8 bytes for é are c3 a9. Converting between the two requires decoding, not text substitution.

FAQ

Do I need to escape non-ASCII characters in JSON?
No. JSON is defined as UTF-8 and literal characters are perfectly valid. Escaping is a compatibility measure for transports that are not UTF-8 clean, and it makes documents with non-Latin text considerably larger.
Why is my JSON full of \u00e9-style escapes?
Almost certainly Python: json.dumps has ensure_ascii=True by default and escapes every non-ASCII character. Pass ensure_ascii=False for literal UTF-8 output.
Why is an emoji two escapes?
It is outside the Basic Multilingual Plane, so it does not fit one \uXXXX escape and is written as a UTF-16 surrogate pair - a high surrogate followed by a low one. They must stay together; splitting them corrupts the character.
What are U+2028 and U+2029 and why do they matter?
Line separator and paragraph separator. They are legal in JSON strings but count as line terminators in JavaScript, so an unescaped one inside a <script> tag or a JSONP response causes a syntax error. Escape them when embedding JSON in HTML.
Which characters must always be escaped in JSON?
The double quote, the backslash, and control characters below U+0020 - the last as \n, \t, \r, \b, \f or \u00XX. Everything else may be literal, though the forward slash is often escaped by convention when embedding in HTML.
Is the output still valid JSON?
Yes - escaped output remains valid JSON.parse input.

Related reading