Unexpected token значит, что JSON.parse встретил символ, с которого JSON не может начинаться или продолжаться. Если этот символ — < в позиции 0, вместо JSON пришла HTML-страница: ошибка сервера, страница входа или index.html. Проверьте статус и тело ответа во вкладке «Сеть» — сам JSON здесь ни при чём.
Как выглядит ошибка в разных браузерах
Одна и та же поломка в разных движках описана по-разному. Для ответа, который начинается с <!DOCTYPE html>, сообщения такие:
- Chrome, Edge и Node.js 20 и новее:
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON; - Chrome до середины 2022 года и Node.js 18 и старше:
SyntaxError: Unexpected token < in JSON at position 0; - Firefox:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data; - Safari:
SyntaxError: JSON Parse error: Unrecognized token '<'.
Во всех четырёх случаях сказано одно: первый же символ — не начало JSON. В новых Chrome и Node.js в кавычках после «Unexpected token» — сам символ, а дальше начало текста, который пытались разобрать. Это первая подсказка: если там <!DOCTYPE или <html>, разбирали HTML.
Unexpected token < в позиции 0: сервер вернул HTML
Код ждал JSON и вызвал response.json() или JSON.parse, а пришла веб-страница. Типичные причины:
- страница ошибки 404 или 500: неверный адрес API, опечатка в пути, упал бэкенд, и веб-сервер или прокси ответил своей HTML-заглушкой;
- редирект на страницу входа: истекла сессия или не передан токен, и вместо данных пришла форма логина;
- фоллбэк одностраничного приложения: сервер на любой неизвестный адрес отдаёт index.html, в том числе на
/api/…, если запрос не дошёл до бэкенда — например, не настроен прокси в режиме разработки; - заглушка балансировщика, CDN или защиты от ботов: страница «502 Bad Gateway» или проверка браузера.
Поэтому искать ошибку в JSON бесполезно: его в ответе нет. Нужно понять, почему сервер ответил страницей.
Как убедиться, что пришёл HTML
- Откройте инструменты разработчика (F12), вкладку «Сеть» (Network), повторите запрос и выберите его. Посмотрите статус: 401, 403, 404, 500, 502 или 302 с переходом на страницу входа сразу объясняют дело. Во вкладке ответа будет HTML.
- Посмотрите заголовок ответа
Content-Type: у JSON этоapplication/json, у страницы —text/html. - В коде прочитайте тело как текст и выведите начало:
const text = await response.text(); console.log(response.status, text.slice(0, 200));
Как правильно обработать ответ в fetch
fetch не считает статус 404 или 500 ошибкой: промис выполняется успешно, и код спокойно вызывает response.json() на HTML-странице. Проверяйте response.ok и тип содержимого до разбора:
const response = await fetch('/api/orders');
const type = response.headers.get('Content-Type') ?? '';
if (!response.ok || !type.includes('application/json')) {
const text = await response.text();
throw new Error(`Ждали JSON, получили ${response.status} ${type}: ${text.slice(0, 200)}`);
}
const data = await response.json();Так в логе будет видно, что сервер вернул на самом деле, а не загадочный «Unexpected token». Для запросов без тела, например со статусом 204, response.json() вызывать не нужно вовсе — получите «Unexpected end of JSON input».
Unexpected token u: разбирают undefined
Если в JSON.parse передать undefined, он превращается в строку "undefined" и падает на первой букве. Старые Chrome и Node.js пишут Unexpected token u in JSON at position 0, новые — "undefined" is not valid JSON. Обычно это опечатка в имени поля (data.reponse вместо data.response), переменная, которую забыли заполнить, или функция, которая ничего не вернула. Проверьте значение до разбора. Заметьте: JSON.parse(null) ошибки не даёт и возвращает null — поэтому отсутствующий ключ в localStorage эту ошибку не вызывает.
Unexpected token o: разбирают уже готовый объект
Объект, переданный в JSON.parse, приводится к строке "[object Object]". Первый символ [ подходит для начала массива, а следующий o — уже нет. Отсюда старое сообщение Unexpected token o in JSON at position 1 и новое "[object Object]" is not valid JSON. Значит, данные уже разобраны: response.json(), axios или jQuery сделали это за вас. Второй JSON.parse не нужен.
Другие неожиданные символы
- Невидимый символ в позиции 0 — скорее всего, BOM в начале файла. В новых Chrome и Node.js сообщение выглядит так, будто после «Unexpected token» в кавычках пусто: там стоит невидимый символ U+FEFF. Python в этом случае прямо пишет «Unexpected UTF-8 BOM». Сохраните файл в UTF-8 без BOM.
'— строка или ключ в одинарных кавычках. В новых Chrome и Node.js для ключа этоExpected property name or '}' in JSON, для значения —Unexpected token '''.}или]сразу после запятой — висячая запятая. Перед}новые версии пишутExpected double-quoted property name in JSON, перед]—Unexpected token ']'.T,N—True,NoneилиNaNиз Python. Сообщение:Unexpected token 'T', ... is not valid JSON.“или«— типографские кавычки, которые подставили Word или мессенджер.
Подробнее о каждой из этих ошибок — в статье «Ошибки в JSON и как их исправить».
{
"update_id": 815104223,
"message": {
"chat": { "id": 52017733, 'type': 'private' },
"text": "/start",
}
}Как перевести позицию в строку и колонку
Старые версии Chrome и Node.js сообщают только «position 214» — номер символа от начала текста. В большом файле с отступами найти 214-й символ вручную неудобно. Новые версии Chrome и Node.js дописывают строку и колонку, а Firefox указывает их всегда.
Проще вставить текст в проверку JSON на parsetools: она покажет все ошибки сразу, с номером строки и колонки, подчеркнёт место и объяснит причину по-русски. Если ошибки исправимы автоматически — кавычки, запятые, литералы Python, — починка исправит их и покажет список правок. Текст не уходит на сервер: всё работает в браузере.
Частые вопросы
Unexpected token < in JSON at position 0 что делать
Вместо JSON пришла HTML-страница. Откройте вкладку «Сеть» в инструментах разработчика, найдите запрос и посмотрите статус и тело ответа: чаще всего это 404, 500 или переход на страницу входа. Исправлять нужно адрес запроса или ошибку на сервере.
Что значит is not valid JSON
Так новые Chrome, Edge и Node.js сообщают, что текст не является JSON. Перед этими словами — неожиданный символ и начало разобранного текста: по нему видно, что пришло на самом деле.
Почему fetch не выдаёт ошибку при 404
fetch отклоняет промис только при сетевой ошибке (в том числе при блокировке CORS) или отмене запроса. Ответ с любым статусом считается успешным, поэтому проверяйте response.ok перед вызовом response.json().
Что значит Unexpected token u in JSON at position 0
В JSON.parse передали undefined. Проверьте, откуда берётся значение: поле с опечаткой, пустая переменная, отсутствующий ответ.
JSON.parse unexpected character at line 1 column 1 в Firefox
Первый же символ — не начало JSON. Обычно это HTML-страница вместо данных или BOM в начале файла. Проверьте ответ во вкладке «Сеть».
Инструменты по теме
- Проверка Найдёт все ошибки сразу и объяснит по-русски, как их исправить
- Починка Исправит запятые, кавычки, комментарии и обрезанный конец
- Форматирование Сделает JSON читаемым с отступами и подсветит ошибки
Ещё в справке
- Ошибки в JSON и как их исправить Висячая запятая, кавычки, комментарии, BOM и ещё десяток причин, почему JSON не разбирается. (откроется в новой вкладке)
- Unexpected end of JSON input: что значит и как исправить Текст кончился раньше, чем JSON: пустой ответ, обрезанный файл или незакрытая скобка. (откроется в новой вкладке)
- Что такое JSON: формат, синтаксис и примеры Формат простыми словами: типы значений, правила, примеры и где он встречается. (откроется в новой вкладке)