Python — json.decoder.JSONDecodeError on parsing a response
Debug JSONDecodeError by inspecting the raw bytes actually received, since empty or HTML bodies parse as invalid JSON.
Symptoms
- json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
- The parse fails only for some responses or when the server errors
- response.json() raises while the status code is 200
- An empty body or an HTML error page is fed to the JSON parser
Possible causes
- The response body is empty, for example for a 204 or a failed request
- The server returned HTML or plain text instead of JSON, often an error page
- The response was already consumed or the encoding is wrong
- A BOM or leading whitespace confuses the parser
Diagnosis steps
Print the raw body before parsing
python -c "import requests; r=requests.get(url); print(r.status_code, r.headers.get('content-type'), repr(r.text[:200]))"Interpretation
Showing status, content type and the first bytes reveals whether the body is JSON, empty or HTML.
Check the content type header
curl -i https://api.example.com/resourceInterpretation
A content type of text/html for an API call usually means a proxy or auth page intercepted the request.
Guard the parse with a clear error
python -c "import json; json.loads(body)"Interpretation
Reproducing the exact exception on the captured bytes confirms which input caused it.
Root cause
The parser received bytes that are not valid JSON, because the body was empty, an error page, or otherwise non-JSON, not because the JSON library is faulty.
Fix
Validate the status and content type before parsing, handle empty bodies explicitly, and surface the raw snippet in the error so future failures are diagnosable.
Verify the fix
Re-request the endpoint and confirm parsing succeeds, or confirm the guard raises a descriptive error for the non-JSON case instead of a bare JSONDecodeError.
Symptom walkthrough
Calling response.json() raises JSONDecodeError, usually Expecting value at line 1 column 1, which means the parser saw no JSON at all. This frequently happens when the body is empty on a 204 response or when an error page or authentication redirect returns HTML. Because the exception is thrown by the JSON parser, it falsely looks like a serialization problem rather than a response content problem.
Fix in practice
Inspect the status code, content type and first bytes before parsing. Treat an empty body as a defined outcome, verify the content type is JSON, and include a snippet of the raw body in any error message you raise. This turns an opaque parser failure into a clear contract violation.
Verification
Repeat the request and confirm parsing succeeds, or confirm that the new guard produces a descriptive error naming the status and content type for the non-JSON case. Either outcome proves the diagnosis.
Diagnostic commands
Check the behavior with commands like these:
python -c "import requests; r=requests.get(url); print(r.status_code, r.headers.get('content-type'), repr(r.text[:200]))"
curl -i https://api.example.com/resource
python -c "import json; json.loads(body)"