Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The usual cause is that JavaScript processes the backslash before JSON.parse() sees the string. In '{"name":"rJohn"}', r becomes an actual carriage-return character while JavaScript creates the string. That leaves invalid JSON. Write \r in the JavaScript source, or—when receiving JSON from an API—parse the raw response with response.json().
The failing and working versions
// Fails: JavaScript consumes r first
const bad = '{"name":"rJohn", "age":30}';
JSON.parse(bad); // SyntaxError
// Works: the JSON text receives the characters backslash + r
const good = '{"name":"\rJohn", "age":30}';
const object = JSON.parse(good);
console.log(object.name.charCodeAt(0)); // 13
The corrected version has two parsing stages. JavaScript turns \r in the source into r in the string value. Then the JSON parser interprets that JSON escape as one carriage-return character.
Why this happens: two languages process the backslash
A backslash does not have one universal meaning. Its meaning depends on the language or format currently reading it. In this example, there are potentially four layers:
Free tools Windows power users keep installed
One-click scans. No signup required.
- JavaScript source code
- The JavaScript string value created from that source
- JSON syntax contained in that string
- The JavaScript value returned by
JSON.parse()
These two JavaScript values look similar but are different:
#1 Best Overall
const actualCarriageReturn = "r";
const literalBackslashR = "\r";
console.log(actualCarriageReturn.length); // 1
console.log(literalBackslashR.length); // 2
The first value contains one character, U+000D. The second contains two characters: a backslash and the letter r. JSON.parse() needs the second form when the JSON text is embedded in JavaScript source.
Valid JSON escapes
JSON permits these escapes inside quoted strings:
| Escape | Meaning |
|---|---|
" |
Quotation mark |
\ |
Backslash |
/ |
Slash |
b |
Backspace |
f |
Form feed |
n |
Line feed |
r |
Carriage return |
t |
Horizontal tab |
uXXXX |
Unicode escape |
JSON does not allow a literal control character from U+0000 through U+001F directly inside a quoted string. It must use an escape sequence such as n or r. See the JSON specification in RFC 8259 and MDN’s documentation for JSON.parse().
How to embed JSON safely in JavaScript
If JSON must be written in a JavaScript string literal, escape the JavaScript layer:
Recommended Free Tools
const text = '{"name":"\rJohn", "age":30}';
const value = JSON.parse(text);
A raw template literal can make this intent clearer:
Rank #2
const text = String.raw`{"name":"rJohn", "age":30}`;
const value = JSON.parse(text);
String.raw preserves the backslash in the resulting string. This is useful when hand-writing a test fixture, but it is usually better not to hand-construct JSON at all.
When the JSON comes from fetch()
Do not manually add backslashes to a valid network response. Let the Fetch API parse it:
const response = await fetch("/data.json");
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
response.json() returns the parsed JavaScript value. It does not return JSON text, so this is wrong:
const data = JSON.parse(await response.json()); // wrong
If parsing fails, inspect the response as text:
const response = await fetch("/data.json");
const raw = await response.text();
try {
const data = JSON.parse(raw);
console.log(data);
} catch (error) {
console.error("Invalid JSON:", error);
console.error(raw);
}
A response containing the two characters backslash and r is valid JSON. A response containing an actual carriage return inside a quoted value is malformed and should normally be fixed by the producing system.
How to identify the characters before parsing
Rendered output can be misleading. Inspect the actual JavaScript string:
const text = '{"name":"rJohn", "age":30}';
console.log(JSON.stringify(text));
console.log([...text].map((character) => character.charCodeAt(0)));
// The array contains 13 for the actual carriage return
For a valid embedded JSON escape, use two backslashes in the source:
const text = '{"name":"\rJohn", "age":30}';
console.log(JSON.stringify(text));
// The JSON text contains the escape sequence r
For a parse error with a known position, this helper displays nearby characters and code points. Error-position formats vary between JavaScript engines, so do not depend on one exact error message.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsfunction inspectAround(text, index, radius = 20) {
const start = Math.max(0, index - radius);
const end = Math.min(text.length, index + radius);
return [...text.slice(start, end)].map((character, offset) => ({
index: start + offset,
character: JSON.stringify(character),
codePoint: `U+${character.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}`
}));
}
Use JSON.stringify() when producing JSON
When an object contains quotes, newlines, tabs, paths, or other special characters, serialize the object instead of assembling JSON with string concatenation:
Rank #4
const payload = {
text: "Line onenLine two",
quote: 'She said "yes"',
path: String.raw`C:tempfile.txt`
};
const body = JSON.stringify(payload);
fetch("/api/example", {
method: "POST",
headers: { "Content-Type": "application/json" },
body
});
JSON.stringify() applies JSON escaping automatically. It is designed for JSON-compatible values, but it does not serialize every JavaScript value unchanged: circular structures throw, ordinary BigInt values throw, and some unsupported values are omitted or converted.
Do not blindly replace backslashes or newlines
This is not a general JSON fix:
raw = raw.replaceAll("\", "\\");
It changes valid escapes. For example, valid JSON containing n is supposed to produce a newline after parsing. Doubling every backslash changes its meaning to a literal backslash followed by n.
This is also risky:
raw = raw.replaceAll("r", "\r");
It can modify carriage returns outside strings, line-delimited data, formatting, or values that should have been rejected. A replacement may be justified as a narrowly scoped workaround for a known malformed payload, but it does not validate the rest of the document and will not repair invalid quotes, bad backslashes, truncated Unicode escapes, trailing commas, or structural errors.
If you must repair legacy input, the repair needs to understand JSON lexical context—whether it is inside a quoted string, whether a quote is escaped, and whether a backslash starts a valid escape. Fixing the producer or using a parser designed for the actual format is safer.
Best Value
Common related cases
Windows paths
Backslashes in paths can be consumed by JavaScript too:
// Risky: t can become a tab
const bad = '{"path":"C:tempfile.txt"}';
// If writing JSON text by hand, escape the backslashes
const good = '{"path":"C:\temp\file.txt"}';
// Prefer serializing a value
const json = JSON.stringify({
path: String.raw`C:tempfile.txt`
});
Quotes inside values
const json = '{"message":"He said \"hello\""}';
const value = JSON.parse(json);
console.log(value.message); // He said "hello"
When serializing an object, let JSON.stringify() add the required quote escapes.
Unicode escapes
Sequences such as u003C and u003E are valid JSON Unicode escapes. After parsing, they become < and >. Similarly, u2019 represents a right single quotation mark. Such sequences are not inherently errors; a failure involving them may instead indicate a server encoding, database code-page, or non-conforming parser problem. JSON syntax and transport encoding are separate concerns.
Carriage return versus line feed
r is carriage return, U+000D; n is line feed, U+000A. Windows-style line endings commonly use the pair rn. Do not normalize them casually if the application needs to preserve exact formatting.
Double-encoded JSON
Sometimes a JSON object has been serialized into a JSON string and then serialized again:
const outer = '"{\"name\":\"John\"}"';
const innerText = JSON.parse(outer);
const object = JSON.parse(innerText);
Do not call JSON.parse() twice merely because a payload contains backslashes. Confirm that the data contract explicitly says the object is JSON stored inside a string.
Practical checklist
- Determine whether the input is raw JSON, a JavaScript source literal, or JSON embedded inside another JSON value.
- Inspect the value immediately before
JSON.parse(). - Check whether
ris two characters or whether the value contains U+000D. - Use
response.json()for a normal JSON response. - Use
JSON.stringify()to produce JSON from JavaScript values. - Check whether the data is double-encoded before parsing more than once.
- Fix the producer when the network response contains literal control characters.
- Avoid global replacement or manual unescaping, which can corrupt valid data.
The original SitePoint discussion, posted on April 5, 2024, demonstrates the JavaScript-string layer clearly, but a displayed payload alone does not prove whether a server response is valid. Inspect the exact text passed to the parser. For the original example and discussion, see SitePoint’s forum thread.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

