Fix "Unexpected token in JSON at position 0" Error in JavaScript
This is one of the most common errors in JavaScript, and the message is honestly a little misleading. "Unexpected token in JSON at position 0" almost never means your JSON has a typo near the start — it usually means the string you're passing to JSON.parse() isn't JSON at all.
The single most frequent cause is calling JSON.parse() on a response that's actually HTML. This happens constantly when a fetch() call hits a broken API endpoint, a 404 page, or a server error page — the server returns an HTML error page instead of JSON, and your code tries to parse it as JSON anyway. If you log the raw response text before parsing and see something starting with <!DOCTYPE html> or <html>, that's your answer immediately.
The second common cause is parsing an empty string. If a request returns no body at all, JSON.parse("") throws exactly this error, because an empty string is not valid JSON — even though it might feel like it should just return null or undefined.
A third cause, more subtle, is a response that's already an object being parsed again. Some HTTP client libraries automatically parse JSON responses for you. If your code then calls JSON.parse() on the result a second time, and the result is already an object (not a string), JavaScript coerces it to the string "[object Object]" before parsing, which obviously fails at position 0.
To actually debug this, the fix is always the same: stop guessing and log the raw value right before the JSON.parse() call. Wrap it like this: console.log(typeof rawValue, JSON.stringify(rawValue).slice(0, 200)) so you can see both the type and the first characters of what you're actually trying to parse.
Once you can see the raw response, the fix usually falls into one of three buckets. If it's an HTML error page, the real bug is upstream — your API call is hitting the wrong URL, or the server is returning an error status you're not checking for. Check response.ok (in fetch) or the status code before attempting to parse anything.
If it's an empty string, guard for it explicitly: only call JSON.parse() when the string has content, and decide what an empty response should mean for your application logic instead of letting it throw.
If it's already an object, simply remove the redundant JSON.parse() call — check whether your HTTP client (axios, ky, or similar) already parses JSON responses automatically, which most modern ones do by default. You can also paste any suspicious string into our JSON Validator to instantly confirm whether it's actually valid JSON before you spend more time debugging the code around it.
Found this helpful?
SyncTonight's tools and guides are free and always will be. If this post saved you some debugging time, a coffee goes a long way — no pressure, just appreciated.
☕ Buy me a coffee