Skip to content
JSON Tidy
JSON errors

invalid character '<' looking for beginning of value

Go’s encoding/json errors are short, but they contain what you need. The quoted character is what the decoder actually found, and the words after it say what it was expecting instead. With '<', the response is an HTML page rather than JSON. That’s the version people hit most, and it means the request went wrong, not the decoding. Any other character points to a specific syntax mistake.

Quick fix

  1. Find your message in the table below.
  2. To see the bad spot, print the bytes around SyntaxError.Offset.
  3. To fix the JSON itself, paste it below.

Fix your JSON

Runs in your browser. Nothing is uploaded.

What each message means

invalid character '<' looking for beginning of valueThe body is an HTML page, usually an error or sign-in page. Fix
invalid character '}' looking for beginning of object key stringA trailing comma before } in an object. Fix
invalid character ']' looking for beginning of valueA trailing comma before ] in an array. Fix
invalid character '\'' looking for beginning of object key stringA property name in single quotes. Fix
invalid character 'a' looking for beginning of object key stringA property name without quotes. Fix
invalid character 'u' looking for beginning of valueThe body is the text undefined. Fix
invalid character 'N' looking for beginning of valueNaN, which JSON doesn’t support. Use null or a number.
invalid character '\ufeff' looking for beginning of valueA byte order mark at the start. Trim it with bytes.TrimPrefix.
invalid character '{' after top-level valueA second JSON value after the first. Fix
invalid character '1' after object keyA missing colon after a property name.
invalid character '2' after array elementA missing comma between array items.
invalid character '\n' in string literalA real line break inside a string. Fix
unexpected end of JSON inputThe body is empty or cut off (json.Unmarshal). Fix
unexpected EOFThe same thing, from json.Decoder. Fix

One error looks similar but means something different: json: cannot unmarshal string into Go value of type int. The JSON is valid, but a value’s type doesn’t match your struct. Change the field’s type, or, if the API sends numbers as strings, add ,string to its struct tag.

Finding the bad spot

Syntax errors come back as a *json.SyntaxError. Its Offset field is how many bytes the decoder had read when it gave up, so the culprit sits just before that point. Printing the bytes around it is usually enough to spot the problem:

var syntaxErr *json.SyntaxError
if errors.As(err, &syntaxErr) {
    start := max(0, int(syntaxErr.Offset)-30)
    end := min(len(body), int(syntaxErr.Offset)+30)
    log.Printf("bad JSON near %q", body[start:end])
}

Check the response before decoding it

If you’re seeing the '<' version, you’re most likely decoding an error page. Checking the status code first turns that into an error that tells you what the server actually said:

resp, err := http.Get(url)
if err != nil { return err }
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
    body, _ := io.ReadAll(io.LimitReader(resp.Body, 200))
    return fmt.Errorf("status %d: %s", resp.StatusCode, body)
}
err = json.NewDecoder(resp.Body).Decode(&result)

The same error elsewhere

JavaScript, '<' caseUnexpected token '<', "<!DOCTYPE "... is not valid JSON
Python, '<' caseJSONDecodeError: Expecting value: line 1 column 1 (char 0)
JavaScript, trailing commaExpected double-quoted property name in JSON at position 8
Python, trailing commaJSONDecodeError: Expecting property name enclosed in double quotes