The complete list of JSON escapes
Inside a JSON string, exactly three characters must be escaped: the double quote, the backslash, and any character below U+0020. Everything else may appear literally, although two more have optional escapes.
| Escape | Character | Required? | Notes |
|---|---|---|---|
| \" | Double quote, U+0022 | Yes | Otherwise it ends the string. |
| \\ | Backslash, U+005C | Yes | Otherwise it starts an escape. |
| \/ | Forward slash, U+002F | No | Legal but never necessary. Exists so that </script> can be written <\/script> inside an HTML page. |
| \b | Backspace, U+0008 | Yes | Control character. |
| \f | Form feed, U+000C | Yes | Control character. |
| \n | Line feed, U+000A | Yes | The one you will meet daily. |
| \r | Carriage return, U+000D | Yes | Windows line endings are \r\n. |
| \t | Tab, U+0009 | Yes | Control character. |
| \uXXXX | Any code unit | Only for other controls | Exactly four hex digits. Case-insensitive. |
Every other control character below U+0020 — U+0000 through U+001F, minus the five
with named escapes — must be written in the \u form:
\u0000 for NUL, \u001b for the escape character that begins an
ANSI colour code in a captured terminal log.
Sequences that do not exist in JSON, however familiar they look from other languages:
| Not JSON | Where it is from | Write instead |
|---|---|---|
| \x41 | C, JavaScript, Python | A |
| \0 | C, JavaScript | \u0000 |
| \' | C, JavaScript, Python | ' — no escape needed |
| \v | C vertical tab | \u000b |
| \a | C bell | \u0007 |
| \u{1F600} | ES6 code-point escape | 😀 or \ud83d\ude00 |
| \N{…} | Python named escape | \uXXXX |
Characters above the basic plane
JSON strings are sequences of UTF-16 code units, so a character outside the Basic Multilingual Plane — every emoji, many CJK extension characters, historic scripts — needs a surrogate pair when written in escaped form.
"😀" // literal, perfectly valid
"\ud83d\ude00" // the same character, as a surrogate pair
"\u{1F600}" // NOT valid JSON — that is JavaScript syntax
You will almost never write these by hand. Serialise with your language’s JSON library and it handles the pairing; the escaper above does the same. It matters when you are reading someone else’s output and wondering why a single emoji appears as two escapes, or why a string with a “length” of 2 displays as one character.
One consequence worth knowing: a lone surrogate — "\ud800"
with no low partner — is accepted by the JSON grammar and by
JSON.parse, even though the resulting string cannot be encoded as valid UTF-8.
If such a value reaches a strict consumer, or a database with a UTF-8 column, it will be
rejected there instead. Validate at the boundary if you accept untrusted text.
Worked examples
1. A Windows path
{"path": "C:\Users\new\test.txt"}
{"path": "C:\\Users\\new\\test.txt"}
The invalid version has two separate problems. \U is not a legal escape,
so the parser rejects it outright — that one you find immediately. But
\new begins with \n, which is legal, so if the path had
been C:\new\file the document would parse cleanly and give you a string
containing a newline character followed by ew. A path that silently becomes
wrong is far more expensive than one that fails loudly.
Forward slashes work on Windows in almost every API, and need no escaping at all. Where you cannot use them, double every backslash — or paste the raw path into the escaper above and let it do the counting.
2. A multi-line value
JSON has no triple-quoted or multi-line string. A note, a log excerpt, a PEM-encoded
certificate or an SSH key must be collapsed into one line with \n escapes:
{"key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADAN...\n-----END PRIVATE KEY-----\n"}
Paste the raw multi-line text into the escaper above, press Escape only,
and you get exactly that, with the trailing newline preserved. Note that a certificate
pasted from a Windows file will contain \r\n; some parsers of the resulting
PEM care, so check which line endings you actually escaped.
3. Double-encoded JSON
{"payload": "{\"id\":1,\"name\":\"Ada\"}"}
The value of payload is a string that happens to contain JSON.
Parsing the outer document gives you the text {"id":1,"name":"Ada"}, not an
object; you have to parse again.
This is produced by calling json.dumps or JSON.stringify
twice, by storing a JSON document in a string column and re-serialising it on the way out,
or by a message queue that wraps every payload. Copy the inner value into the escaper
above and press Unescape to see what is really inside, then fix the
producer — double encoding roughly doubles the byte cost of the nested part, defeats
schema validation on it, and forces every consumer to know about the extra layer.
4. A quoted quote
{"quote": "She said "hello" loudly"}
{"quote": "She said \"hello\" loudly"}
The invalid version parses as the string "She said " followed by the bare
word hello, at which point the parser gives up. The error is reported at
hello, not at the quote that caused it — another case where the fault
lies before the caret.
Escaping in your own code
The correct answer, in every language, is: do not do it by hand.
// JavaScript — JSON.stringify on a string produces a complete literal
JSON.stringify('C:\\Users\\new') // "\"C:\\\\Users\\\\new\""
JSON.stringify(text).slice(1, -1) // the same, without the outer quotes
# Python
import json
json.dumps(text) # complete literal, with quotes
json.dumps(text, ensure_ascii=False) # keep é and 😀 literal instead of \u-escaping
# Shell, using jq — -R reads raw text, -s slurps all lines into one string
printf 'line one\nline two' | jq -Rs .
Python’s ensure_ascii deserves a moment. It defaults to
True, which escapes every non-ASCII character as \uXXXX. The output
is valid, transport-safe over any 7-bit channel, and considerably larger — a document
of Japanese text can grow by a factor of three. Setting it to False writes the
characters literally, which is smaller and readable, and is safe as long as everything
downstream agrees the encoding is UTF-8.
What you should never do is build a JSON string with string concatenation or a template, replacing quotes with a regular expression as you go. Every escaping bug on this page comes from exactly that. Build a value; serialise it.
JSON escaping is not HTML escaping
They solve different problems and do not substitute for one another. JSON escaping makes
text survive a JSON parser. HTML escaping makes text survive an HTML parser. A string that
is correctly JSON-escaped can still carry <script> tags, because
< means nothing special to JSON.
If you take a value out of a JSON document and put it into a page, you must escape it for
HTML at that point — or better, avoid the question entirely by assigning to
textContent rather than innerHTML. That is what this page does
with everything you paste, which is why a value containing
<img src=x onerror=alert(1)> shows up here as those literal characters
and nothing happens.
The one place the two do interact: </script> inside a JSON string
embedded in an inline <script> block will end the block early, because
the HTML tokenizer runs first and does not know it is inside a string. That is exactly what
the optional \/ escape exists for. Writing <\/script> keeps
the JSON identical and stops the HTML parser closing your tag.
Frequently asked questions
Do I have to escape forward slashes?
No. \/ is legal but never required, and
"https://example.com" is perfectly valid unescaped. Some serialisers —
notably PHP’s json_encode by default — escape it anyway, which is
why you see https:\/\/example.com in the wild. Both parse to the same string.
PHP’s JSON_UNESCAPED_SLASHES flag turns it off.
Do I have to escape single quotes?
No, and you must not try: \' is not a valid JSON
escape and will be rejected. Inside a JSON string an apostrophe is an ordinary character.
The confusion comes from JavaScript and Python, where \' is meaningful
because those languages allow single-quoted strings. JSON does not.
Why does my string contain \u00e9 instead of é?
Because the producer escaped non-ASCII characters. Python’s
json.dumps does this by default (ensure_ascii=True), and several
Java and PHP configurations do too. It is entirely valid — \u00e9 and
é parse to the identical string — just larger and harder to read. Paste
it into the escaper above and press Unescape to see the text.
How do I put a newline in a JSON string?
Write the two characters backslash and n. A real
line break inside a JSON string is a syntax error, because JSON has no multi-line string
form. If you are writing the document by hand in an editor, paste the multi-line text into
the escaper above and use the escaped result.
What is the maximum length of a JSON string?
The specification sets no limit. In practice you hit the implementation first: JavaScript engines cap a single string at roughly 229 characters in V8, and your available memory well before that. Any single JSON value in the hundreds of megabytes is a sign the data belongs somewhere other than a JSON string.
Can I use JSON escaping to make user input safe?
Only against JSON parsing problems. It does nothing about SQL
injection, HTML injection, shell injection, or path traversal — each of those needs
its own contextual handling at the point where the value is used. Escaping is per-context,
never global. The correct habit is to keep data as data all the way through and let the
API you are calling do the quoting: parameterised SQL statements,
textContent rather than innerHTML, argument arrays rather than
shell strings.
Is the text I paste here sent anywhere?
No. Escaping calls JSON.stringify and unescaping calls
JSON.parse, both in your browser. There is no upload endpoint and nothing is
stored. Neither operation uses eval or the Function constructor
— unescaping runs through the JSON parser, so a hostile input is read as data and
never executed.
Related pages
- JSON formatterPretty-print, tree view and statistics
- “Unexpected token” explainedIncluding every escaping error
- “Unexpected token < … position 0”Your API returned HTML, not JSON
- “Unexpected end of JSON input”Empty bodies, truncation and double-reads
- “JSON.parse: unexpected character”The Firefox and Safari wording, decoded
- JSON validatorExact line and column for every error
- JSON minifierStrip whitespace and measure the saving