This error means json.loads (or a library call hiding it, like response.json()) received text that is not valid JSON, and the decoder failed at the stated line and column. The near-universal cause is that the text is not what the code assumed: an API returned an HTML error page or an empty body, or the data was a Python representation (single quotes, True, None) rather than real JSON.
import json
data = json.loads(response.text) # the API actually sent an
# HTML error page
Traceback (most recent call last):
File "main.py", line 1, in <module>
json.decoder.JSONDecodeError: Expecting value:
line 1 column 1 (char 0)
# fixed: look at what actually arrived before parsing it
print(response.status_code, response.text[:200])
response.text[:200] (or the file's first bytes) settles everything: an HTML page, an empty string, a login redirect, or JSON with a visible defect. Never debug JSON blind..json() call on a failed response produces this error, which sends debugging toward the parser when the real problem is the request. Branch on status first.True/False/None, and trailing commas are Python syntax, not JSON. Data produced by print(dict) or str(dict) needs json.dumps at the source, or ast.literal_eval to recover, never json.loads.If the text prints as valid JSON but still fails, suspect invisible contamination: a byte-order mark at the start (decode with utf-8-sig) or log lines and warnings mixed into the stream before the JSON begins (common when a script's output is piped). The decoder fails at char 0 precisely because the JSON does not start at char 0.
Is JSONDecodeError a ValueError? Yes; it subclasses ValueError, which is why older code and documentation describe the same failure as a ValueError. Catching JSONDecodeError specifically is clearer, and catching ValueError catches both it and plain value errors.
The API worked yesterday and returns this today. What changed? Usually the response changed, not the JSON rules: an expired key turning success into an HTML 401 page is the classic. Step one (print the raw response and status) reveals it in seconds.