Unexpected Token in JSON: How to Fix This Error
The "Unexpected token" error is one of the most common JSON parsing errors. It means the parser encountered a character it wasn't expecting at a specific position. This guide explains what causes it and how to fix it quickly.
What Does "Unexpected Token" Mean?
When you see an error like:
SyntaxError: Unexpected token < in JSON at position 0
It's telling you three things:
- Unexpected token — The parser found a character that doesn't belong
<— The specific character that caused the problem- at position 0 — Where in the string it occurred (0 = the very first character)
The most important clue is which token was unexpected. Different tokens indicate different problems.
Common Causes by Token
Unexpected Token < (Most Common)
Cause: You're receiving HTML instead of JSON. This typically happens when:
- An API returns an error page instead of JSON
- You're hitting the wrong URL
- The server is down and returning a default error page
- Authentication failed and you got a login page
// You expected JSON but got HTML
fetch('/api/data')
.then(r => r.json()) // Fails: response is "<html>..."
How to debug:
fetch('/api/data')
.then(response => {
// Check content type
const contentType = response.headers.get('content-type');
console.log('Content-Type:', contentType);
// Look at raw response
return response.text();
})
.then(text => {
console.log('Raw response:', text.substring(0, 200));
// Now try to parse
return JSON.parse(text);
});
Fix: Check that:
- The URL is correct
- The server is returning JSON (Content-Type: application/json)
- You're authenticated if required
- The API endpoint exists
Unexpected Token u
Cause: Trying to parse the string "undefined":
let data;
JSON.parse(data); // Error: data is undefined
// Parser sees: undefined → starts with 'u' → unexpected
Fix: Check for undefined before parsing:
function safeParse(data) {
if (data === undefined || data === null) {
console.error('No data to parse');
return null;
}
return JSON.parse(data);
}
Unexpected Token ' (Single Quote)
Cause: JSON requires double quotes, not single quotes:
{'name': 'Alice'} // Wrong: single quotes
Fix: Replace single quotes with double quotes:
{"name": "Alice"}
If you're receiving data with single quotes, you may need to transform it:
// Risky but sometimes necessary for malformed data
const fixed = badJson.replace(/'/g, '"');
const data = JSON.parse(fixed);
Unexpected Token } or ]
Cause: Extra closing bracket or trailing comma:
{"name": "Alice",} // Trailing comma before }
["a", "b", "c",] // Trailing comma before ]
{"data": {}}}} // Extra closing braces
Fix: Remove trailing commas and check bracket matching. Use the JSON Validator to find the exact location.
Unexpected Token at Position 0
When the error is at position 0, the entire response is wrong:
SyntaxError: Unexpected token X in JSON at position 0
Common causes:
- Empty response — Server returned nothing
- BOM character — Invisible bytes at start of file
- HTML/XML response — Wrong content type
- Plain text error — Server returned "Error" or "Not found"
Debug with:
fetch('/api/data')
.then(r => r.text())
.then(text => {
console.log('Length:', text.length);
console.log('First 10 chars:', JSON.stringify(text.substring(0, 10)));
console.log('Char codes:', [...text.substring(0, 5)].map(c => c.charCodeAt(0)));
});
Fixing BOM Characters
A Byte Order Mark (BOM) is an invisible character at the start of some files. It looks like this in hex: EF BB BF (UTF-8 BOM).
Symptoms:
- JSON looks correct but won't parse
- Error at position 0
- File works in some editors but not others
Fix in JavaScript:
function stripBOM(text) {
// Remove UTF-8 BOM if present
if (text.charCodeAt(0) === 0xFEFF) {
return text.slice(1);
}
return text;
}
const cleanJson = stripBOM(rawText);
const data = JSON.parse(cleanJson);
Fix in Python:
import codecs
# Method 1: Use utf-8-sig encoding
with open('data.json', 'r', encoding='utf-8-sig') as f:
data = json.load(f)
# Method 2: Strip manually
text = raw_text.lstrip('\ufeff')
data = json.loads(text)
Language-Specific Solutions
JavaScript
async function fetchJSON(url) {
const response = await fetch(url);
// Check if response is OK
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
// Check content type
const contentType = response.headers.get('content-type');
if (!contentType?.includes('application/json')) {
const text = await response.text();
throw new Error(`Expected JSON but got ${contentType}: ${text.substring(0, 100)}`);
}
return response.json();
}
Python
import requests
import json
def fetch_json(url):
response = requests.get(url)
# Check content type
content_type = response.headers.get('Content-Type', '')
if 'application/json' not in content_type:
raise ValueError(f"Expected JSON, got {content_type}: {response.text[:100]}")
try:
return response.json()
except json.JSONDecodeError as e:
print(f"Failed to parse: {response.text[:200]}")
raise
Node.js with Axios
const axios = require('axios');
async function fetchJSON(url) {
try {
const response = await axios.get(url, {
headers: { 'Accept': 'application/json' },
transformResponse: [(data) => {
// Log raw response for debugging
if (typeof data === 'string' && data.startsWith('<')) {
console.error('Received HTML instead of JSON');
throw new Error('Server returned HTML');
}
return JSON.parse(data);
}]
});
return response.data;
} catch (error) {
if (error.response) {
console.error('Response data:', error.response.data);
}
throw error;
}
}
Debugging Checklist
When you get an unexpected token error, check these in order:
1. Is the response actually JSON?
console.log('Raw:', await response.text());
2. What's the Content-Type header?
console.log('Type:', response.headers.get('content-type'));
3. Is the response empty?
const text = await response.text();
console.log('Length:', text.length);
console.log('Empty?', text.trim() === '');
4. Are there hidden characters?
console.log('Char codes:', [...text.slice(0, 10)].map(c => c.charCodeAt(0)));
// BOM would show: [65279, ...] or [239, 187, 191, ...]
5. Is the URL correct?
console.log('URL:', response.url); // Check for redirects
console.log('Status:', response.status);
Common Scenarios
API Returns Login Page
// Problem: Not authenticated, API returns HTML login page
fetch('/api/private-data')
.then(r => r.json()) // Error: Unexpected token <
// Solution: Check authentication first
fetch('/api/private-data', {
headers: { 'Authorization': `Bearer ${token}` }
})
CORS Proxy Issues
// Problem: CORS proxy returns error as text
fetch('https://cors-proxy.example.com/api')
.then(r => r.json()) // Error: Unexpected token
// Solution: Check proxy response
fetch('https://cors-proxy.example.com/api')
.then(r => r.text())
.then(text => {
if (text.includes('error') || text.startsWith('<')) {
console.error('Proxy error:', text);
return null;
}
return JSON.parse(text);
});
Local File with BOM
// Problem: JSON file saved with BOM from Windows editor
const fs = require('fs');
const text = fs.readFileSync('data.json', 'utf8');
JSON.parse(text); // Error: Unexpected token
// Solution: Strip BOM
const cleanText = text.replace(/^\uFEFF/, '');
JSON.parse(cleanText);
Prevention Tips
- Always check response status before parsing
- Verify Content-Type header is application/json
- Log raw responses during development
- Use try-catch around all JSON.parse calls
- Validate JSON with the JSON Validator before using in code
- Save files without BOM — Use UTF-8 encoding, not UTF-8 with BOM
Related Tools & Resources
Tools
- JSON Validator — Validate and find errors in JSON
- JSON Unescape — Fix escape sequence issues
- JSON Stringify — Properly format strings as JSON
Learn More
- JSON Syntax Error Guide — All syntax error types
- JSON Parse Error Guide — Comprehensive parsing errors
- Fix Unexpected End of JSON — Incomplete JSON errors
- JSON Comments Guide — Why comments cause errors
- Common JSON Mistakes — Avoid common pitfalls
Related Articles
Understanding the Benefits of Using a JSON Beautifier
Learn why formatting and beautifying JSON improves code readability, debugging, and collaboration.
Common JSON Mistakes and How to Avoid Them
The 20 most common JSON syntax errors developers make, organized by category with examples and fixes.
How to Fix 'Unexpected End of JSON Input' Error
Learn what causes the 'Unexpected end of JSON input' error and how to fix it with practical solutions for JavaScript, Python, and other languages.
How to Open JSON Files
A complete guide to opening and viewing JSON files on any operating system using various methods and tools.