← All articles

Bad Escaped Character in JSON: Causes, Examples, and Fixes

Fix "bad escaped character in JSON" errors from \x escapes, Windows paths, regex strings, malformed \u values, and double-encoded JSON.

SyntaxError: Bad escaped character in JSON at position N means the parser found a backslash (\) inside a JSON string, then the next character was not one of the escape characters JSON allows. Per RFC 8259 section 7, JSON strings can escape a double quote, backslash, forward slash, the control escapes b, f, n, r, t, or a Unicode escape written as u plus exactly four hex digits.

In real debugging, this error usually comes from one copied value: a Windows path (C:\Users\Ada), a JavaScript or shell escape (\x1b), a regex pattern (\d+), a Python-style Unicode escape (\U0001F600), or a string that was half-unescaped from a log. The fix is not "delete backslashes." The fix is to decide what the final string value should be, then write the JSON text that represents that value.

This guide focuses on JavaScript JSON.parse() wording, but the same rule applies to Python json.loads(), Go encoding/json, Ruby JSON.parse, PHP json_decode, jq, Postgres jsonb, and most strict JSON parsers.

Which string error is this?

The 30-Second Fix

  1. Go to the reported position, line, or column.
  2. Look one character before it for a backslash.
  3. Check the character after the backslash.
  4. If the backslash is part of the data, write it as \\.
  5. If the escape belongs to another language (\x, \d, \U), translate it into JSON syntax.
  6. If the backslash was only copied from a quoted log line, parse one layer instead of stripping it with regex.

Example:

{"path":"C:\Users\Ada\file.json"}
           ^
           U is not valid after a JSON backslash

Correct JSON text:

{
  "path": "C:\\Users\\Ada\\file.json"
}

After parsing, the actual application value is still:

C:\Users\Ada\file.json

The doubled backslashes only exist in the JSON text.

What the Error Looks Like

Different engines use slightly different wording:

// V8: Chrome, Node.js, Edge
SyntaxError: Bad escaped character in JSON at position 12

// Firefox
SyntaxError: JSON.parse: bad escaped character at line 1 column 13 of the JSON data

// Safari
SyntaxError: JSON Parse error: Invalid escape character \x

V8's position usually points at the character after the backslash, not the backslash itself. In this broken JSON, the reported character is the U in \Users:

{"path":"C:\Users\Ada\file.json"}
           ^^
           \U is the bad escape

So when the message says position 12, inspect a small window before and after position 12. The bad character is useful, but the backslash before it explains the bug.

The Only Escapes JSON Allows

Inside a JSON string, a backslash can only introduce these escapes:

JSON escape Parsed character Notes
\" " Required for a double quote inside a JSON string
\\ \ Required for a literal backslash
\/ / Optional; / is also valid unescaped
\b Backspace U+0008
\f Form feed U+000C; this is why \file is dangerous in Windows paths
\n Line feed U+000A
\r Carriage return U+000D
\t Tab U+0009
\uXXXX Unicode code unit Exactly four hex digits after lowercase u

Everything else is invalid JSON: \x, \', \d, \s, \w, \0, \v, \e, \U, \u{1F600}, \N{...}, \cA, and short Unicode escapes like \u12.

Quick Fix Table

Use this table when you already know what the final value should be.

Broken JSON text Why it fails Valid JSON text
{ "path": "C:\Users\Ada\file.json" } \U and \A are invalid; \f is valid but becomes form feed, not a path separator. { "path": "C:\\Users\\Ada\\file.json" }
{ "path": "C:/Users/Ada/file.json" } This does not fail. Forward slashes do not need escaping. Keep it if the consumer accepts forward slashes.
{ "color": "\x1b[32mOK\x1b[0m" } JSON has no \xNN escape. { "color": "\u001b[32mOK\u001b[0m" }
{ "name": "O\'Brien" } Apostrophes do not need escaping in JSON strings. { "name": "O'Brien" }
{ "pattern": "^\d{4}-\d{2}-\d{2}$" } \d is a regex escape, not a JSON escape. { "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }
{ "char": "\u12" } \u must be followed by exactly 4 hex digits. { "char": "\u0012" }
{ "emoji": "\u{1F600}" } JavaScript supports this in source strings; JSON does not. { "emoji": "😀" } or { "emoji": "\uD83D\uDE00" }

One awkward detail deserves its own warning: \f is a valid JSON escape. If a Windows path contains \file, a parser can turn that into a form-feed character followed by ile. The parse may succeed while the path value is corrupted. That is why blindly "repairing" path strings is risky.

Cause 1: Windows Paths Copied Into JSON

Windows paths look harmless because humans read the backslash as a path separator:

{ "downloadDir": "C:\Users\Ada\Downloads" }

JSON reads backslash as the start of an escape sequence. It sees \U, then stops because uppercase U is not a JSON escape.

Write doubled backslashes in JSON:

{
  "downloadDir": "C:\\Users\\Ada\\Downloads"
}

Or use forward slashes if the receiving program accepts them:

{
  "downloadDir": "C:/Users/Ada/Downloads"
}

For config files, forward slashes often make fewer mistakes. For exact Windows-only values, doubled backslashes are the portable JSON representation.

Cause 2: Mixing JavaScript Source Strings With JSON Text

This is where many examples on the web accidentally confuse people. There are two layers:

  • JavaScript source string syntax
  • JSON text syntax inside that JavaScript string

This JavaScript source code is valid:

const raw = '{"path":"C:\\Users\\Ada"}';
JSON.parse(raw);

But the JSON text that reaches the parser is:

{"path":"C:\\Users\\Ada"}

If you want to test a broken JSON sample in JavaScript without JavaScript itself consuming backslashes first, use String.raw:

const broken = String.raw`{"path":"C:\Users\Ada"}`;
JSON.parse(broken);

That throws Bad escaped character because JSON.parse() receives the real broken JSON text.

Use this mental model when reading stack traces: if the JSON came from a .json file, HTTP body, localStorage value, or database string, fix the JSON text. If the JSON is inside a JavaScript source string, you may need one level of escaping for JavaScript and another level for JSON.

Cause 3: Borrowing Escapes From Other Languages

JSON accepts \n and \t, but it does not accept many escapes that are normal in programming languages:

{ "code": "\x1b[0m", "name": "O\'Brien" }

Valid JSON:

{
  "code": "\u001b[0m",
  "name": "O'Brien"
}

Common false friends:

Escape Valid in JSON fix
\x1b JavaScript, Python, many shells \u001b
\' JavaScript/Python single-quoted strings Use ' with no backslash
\0 JavaScript/Python NUL shorthand \u0000
\v JavaScript vertical tab \u000b
\U0001F600 Python Unicode escape Literal UTF-8 emoji or surrogate pair
\u{1F600} JavaScript Unicode code point escape Literal UTF-8 emoji or surrogate pair

If the producer is your code, do not translate every case by hand. Build a normal object and let the language's JSON serializer write valid JSON.

Cause 4: Regex Patterns Stored In JSON Config

Regexes have their own escape language. JSON strings have a separate escape language. The regex backslash has to survive JSON parsing before it can reach the regex engine.

Broken JSON config:

{ "datePattern": "^\d{4}-\d{2}-\d{2}$" }

Valid JSON config:

{
  "datePattern": "^\\d{4}-\\d{2}-\\d{2}$"
}

After JSON parsing, the application sees this string:

^\d{4}-\d{2}-\d{2}$

Only then should it become a regular expression:

const config = JSON.parse('{"datePattern":"^\\\\d{4}-\\\\d{2}-\\\\d{2}$"}');
const re = new RegExp(config.datePattern);

The same rule applies to \s, \w, \b, named groups, lookbehind examples, and replacement strings. If the backslash is meant for a later parser, double it in JSON.

Cause 5: Malformed Unicode Escapes

JSON's Unicode escape is fixed width:

{ "char": "\u12" }

Valid JSON:

{
  "char": "\u0012"
}

The u must be lowercase and followed by exactly four hex digits: 0-9, a-f, or A-F.

These are not JSON Unicode escapes:

"\u{2028}"   // JavaScript source style, not JSON
"\U00002028" // Python style, not JSON
"\u20G0"     // G is not a hex digit

Characters outside the Basic Multilingual Plane, such as many emoji and some mathematical symbols, can be stored literally in UTF-8 JSON:

{
  "emoji": "😀"
}

When escaped, they are represented as a UTF-16 surrogate pair:

{
  "emoji": "\uD83D\uDE00"
}

Avoid lone surrogates such as \uD83D without the matching low surrogate. Some parsers accept them as code units, but downstream systems that require well-formed Unicode may reject them.

Cause 6: Hand-Built JSON Strings

This is the production version of the bug:

// Unsafe: userInput may contain backslashes, quotes, or newlines.
const payload = '{"message":"' + userInput + '"}';

If userInput is C:\Users\Ada, the emitted text is invalid JSON. If it contains ", the JSON can break in a different way. If it contains a raw newline, you may get a bad control character instead.

Use a serializer:

const payload = JSON.stringify({
  message: userInput,
  path: 'C:\\Users\\Ada\\file.json',
  code: '\x1b[32mOK\x1b[0m',
});

JSON.stringify() handles the JSON-specific escaping. The result is valid JSON text:

{
  "message": "...",
  "path": "C:\\Users\\Ada\\file.json",
  "code": "\u001b[32mOK\u001b[0m"
}

The same principle applies in other languages:

import json

payload = json.dumps({
    "path": r"C:\Users\Ada\file.json",
    "pattern": r"^\d+$",
})
body, err := json.Marshal(map[string]string{
    "path": `C:\Users\Ada\file.json`,
    "pattern": `^\d+$`,
})

If you are fixing a producer, this is the real fix. Patching invalid JSON downstream only hides the place where the bad text was created.

How To Locate The Bad Escape

For pasted JSON, this small helper makes the area around V8's position easier to see:

function showJsonParseContext(raw) {
  try {
    JSON.parse(raw);
    console.log('Valid JSON');
  } catch (error) {
    const message = String(error.message);
    const match = message.match(/position (\d+)/);

    if (!match) {
      console.log(message);
      return;
    }

    const pos = Number(match[1]);
    const start = Math.max(0, pos - 24);
    const end = Math.min(raw.length, pos + 24);
    const excerpt = raw.slice(start, end);

    console.log(message);
    console.log(JSON.stringify(excerpt));
    console.log(' '.repeat(pos - start) + '^');
  }
}

const raw = String.raw`{"path":"C:\Users\Ada\file.json"}`;
showJsonParseContext(raw);

JSON.stringify(excerpt) is intentional. It shows backslashes and control characters as visible escapes, which is exactly what you need when the bug is invisible whitespace or an over-eager escape.

For Firefox-style line and column errors, jump to that line first, then inspect the string literal on that line. If the exact column lands after a backslash, read the previous character too.

Repair Tool Or Reject The Payload?

Use a repair tool when:

  • You are cleaning a pasted snippet.
  • You are debugging a log line.
  • You are reviewing LLM output.
  • You can visually confirm the repaired value.
  • The value is not driving money movement, permissions, deletion, or irreversible state changes.

Reject the payload and fix the producer when:

  • The JSON came from an API contract.
  • The value affects billing, permissions, security, or data deletion.
  • The parser had to guess between multiple possible meanings.
  • A path, regex, or escape sequence could be valid but semantically wrong.

For example, repairing C:\Users\Ada\file.json is not just a syntax operation. \f in \file is a valid escape, so a tool may parse a form-feed character instead of preserving the backslash. A human or the producer code needs to decide the intended path.

The JSON Fix tool on this site is best used as a browser-local debugging assistant: paste the text, inspect the output, then validate the repaired JSON. It should not be the silent ingestion layer for malformed production payloads.

How To Unescape JSON Safely

Sometimes the backslashes are not bad; the JSON is double-encoded. You might see this in logs:

{\"name\":\"Ada\",\"path\":\"C:\\\\Users\\\\Ada\"}

Do not run a blanket replace(/\\/g, ''). That destroys real escapes.

Parse one valid JSON layer at a time:

// The outer value is a JSON string that contains JSON text.
const wrapped = '"{\\"name\\":\\"Ada\\",\\"path\\":\\"C:\\\\\\\\Users\\\\\\\\Ada\\"}"';

const once = JSON.parse(wrapped);
// once is: {"name":"Ada","path":"C:\\Users\\Ada"}

const data = JSON.parse(once);
// data is: { name: "Ada", path: "C:\\Users\\Ada" }

If the first parse fails with Bad escaped character, the input is not merely encoded. It is invalid JSON text and needs a targeted repair.

Prevention Checklist

  • Never concatenate user strings into JSON.
  • Use JSON.stringify(), json.dumps(), json.Marshal(), or your platform's JSON serializer.
  • Store regex patterns in JSON with doubled backslashes.
  • Prefer forward slashes for paths when the consumer accepts them.
  • Quote and test examples copied from logs, shells, and docs.
  • Validate generated .json files in CI with a real parser.
  • Log a safe preview around the parser position instead of logging the whole payload.
  • Treat automatic repair as a developer workflow, not a production contract.

Frequently Asked Questions

What does "Bad escaped character in JSON" mean?

A backslash inside a JSON string is followed by a character JSON does not allow after \. Valid escapes are ", \, /, b, f, n, r, t, and uXXXX.

How do I fix a Windows path in JSON?

Write every path backslash as \\, for example C:\\Users\\Ada\\file.json. If the receiving program accepts forward slashes, C:/Users/Ada/file.json is valid JSON and easier to read.

Why does my regex work in JavaScript but fail in JSON?

The JSON parser sees the string before the regex engine does. A regex escape like \d must be written as \\d in JSON so the parsed string still contains \d.

Is \x1b valid JSON?

No. \xNN is common in JavaScript, Python, and shell examples, but JSON does not support it. Use \u001b for the ANSI ESC character, or remove ANSI color codes before serializing logs.

Is this the same as "Bad control character"?

No. "Bad escaped character" means the character after a backslash is invalid. "Bad control character" means a raw control byte, such as a literal newline, tab, NUL, or ESC byte, appears inside a JSON string.

Can JSON repair tools fix bad escapes automatically?

Sometimes, for pasted snippets where the intended value is obvious. Do not silently auto-repair API payloads, security-sensitive data, payments, permissions, deletes, or values where \f, \n, or \t might be valid but unintended.

How do I unescape JSON?

Parse one layer at a time with JSON.parse(). A double-encoded value becomes a normal JSON string after the first parse and a real object or array after the second. Avoid regex backslash-stripping because it corrupts valid escapes.

How do I prevent this error in source code?

Build native values and serialize them with JSON.stringify() or the equivalent serializer in your language. Do not assemble JSON with string concatenation.

Fix It Now

Sources

Last reviewed July 2026.