Skip to content

JavaScript · browsers and Node.js

Bad control character in string literal in JSON at position N

JSON.parse reports Bad control character in string literal when a string holds a raw line break, tab or other control character that should have been escaped.

Updated · 2 min read

console
Chrome, Edge, Node.jsSyntaxError: Bad control character in string literal in JSON at position 65 (line 4 column 15)
Node.js 20SyntaxError: Bad control character in string literal in JSON at position 65
FirefoxSyntaxError: JSON.parse: bad control character in string literal at line 4 column 15 of the JSON data
SafariSyntaxError: JSON Parse error: Unterminated string

Find it in your JSON

Paste the text that failed. The checker points at the exact spot, and Repair fixes most syntax mistakes.

Input · JSON

Invalid JSON

Line 4, column 15

Raw line break inside a string.

2  "ticket": 4471,3  "subject": "Refund request",4  "body": "Hi,               ^5I was charged twice for order A-2203."

Fix: Strings must stay on one line. Write the line break as \n, or the closing quote is missing.

Also see line 4, column 11: string starts here.

Why this happens
Invalid JSONRuns in your browser

Load from a URL

Your browser fetches it directly, so the server must allow cross-origin requests (CORS).

Why it happens

Inside quotes, JSON accepts every character except the 32 control characters U+0000 to U+001F, which must be escaped: a line break as \n, a tab as \t, the rest as \u plus four hex digits. The sample breaks this rule on line 4. Most common sources first:

1. Multi-line text dropped into a JSON template. Text from a textarea, an email or a commit message, inserted with a template literal or +:

const json = `{"ticket": 4471, "body": "${form.body.value}"}`;   // breaks on Enter, quotes, backslashes

Language models also sometimes write real line breaks inside long string values.

2. JSON inside a string literal in your code. JavaScript and Python turn \n into a real line break before JSON.parse sees it:

JSON.parse('{"status":"paid\nshipped"}');   // SyntaxError: the \n became a real line break

3. Tabs from spreadsheets. Cells copied from Excel or Google Sheets carry tabs into the value. The checker names them: Raw tab inside a string.

4. Invisible control characters. Terminal color codes (ESC, U+001B) captured from command output, or NUL bytes from binary data. The checker reports the code point, for example Raw control character U+001B inside a string.

Node.js 18 and older Chrome reported this as Unexpected token, then the raw character itself, then in JSON at position 65, so a line break split the message in two.

How to fix a bad control character in a string literal

Build JSON with a serializer

const ticket = { ticket: 4471, subject: 'Refund request', body: form.body.value };
const json = JSON.stringify(ticket);   // the line break becomes \n

json.dumps(ticket) does the same in Python.

Keep the backslash in string literals

JSON.parse('{"status":"paid\\nshipped"}');
JSON.parse(String.raw`{"status":"paid\nshipped"}`);

In Python, use a raw string: json.loads(r'{"status": "paid\nshipped"}').

Clean text you do not control

In Python, json.loads(text, strict=False) accepts raw control characters in strings, and json.dumps writes them back escaped. In JavaScript, first remove the ones that are never valid anywhere in JSON (all but tab, line feed and carriage return):

const cleaned = text.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g, '');

Raw line breaks and tabs are only wrong inside strings, which search and replace cannot tell apart. JSON Repair escapes them there, along with carriage returns, form feeds and backspaces; it stops at other control characters, so run the cleanup first. For a single value, the JSON escape tool turns raw text into a valid JSON string.

Color codes from command output

Turn colors off at the source (many tools honor NO_COLOR=1 or a --no-color flag), or strip captured codes with text.replace(/\u001b\[[0-9;]*m/g, '').

Same error in other languages

  • Python: json.decoder.JSONDecodeError: Invalid control character at: line 4 column 15 (char 65)
  • Go: invalid character '\n' in string literal
  • PHP: json_decode() returns null, and json_last_error_msg() says Control character error, possibly incorrectly encoded.
  • A missing closing quote is a different problem: Unterminated string in JSON.

Paste failing text into the JSON validator to find the character; common JSON errors covers related problems.

Questions

Which characters count as control characters?

NUL, tab, line feed, carriage return, escape and the other code points below U+0020. DEL (U+007F) and the non-breaking space may appear inside strings as they are.

Are line breaks between properties a problem?

No. Outside strings, line breaks, tabs and spaces are whitespace and can sit between any two tokens. The rule only applies inside quotes.

Can JSON.stringify produce this error?

No. It escapes every control character, as \n, \t or \u001b, so its output always parses.

Related errors

All common JSON errors

Esc