Fix: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Python's json module found nothing it could parse at the very first character. The input is usually empty, HTML, or already consumed. Print the raw text first, then fix the source.
Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?
Your Python program stops with:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
The parser expected a JSON value (an object, array, string, number, true, false or null) at the very first character and did not find one. The message describes the input, not your code, so the first step is always to look at the input.
Step 1: print what you actually received
print(repr(text[:200])) # repr shows empty strings, whitespace and hidden characters
Cause 1: the input is empty
json.loads("") raises exactly this error. Typical sources are an empty file, a file still being written by another process, or an HTTP response with no body, such as status 204 No Content.
Cause 2: you got HTML or plain text instead of JSON
If the output starts with < or <!doctype html>, the server sent a web page, often a login page, an error page or a rate-limit notice. Check the status code and the Content-Type header before parsing:
import json
import urllib.request
with urllib.request.urlopen("https://api.example.com/items") as resp:
body = resp.read().decode("utf-8")
ctype = resp.headers.get("Content-Type", "")
if "json" not in ctype:
raise RuntimeError(f"expected JSON, got {ctype!r}: {body[:200]!r}")
data = json.loads(body)
urllib raises HTTPError for 4xx and 5xx responses. With the third-party requests library, call response.raise_for_status() before response.json(), so an error page fails with a clear message instead of a parse error.
Cause 3: the file was already read
A file object has a read position. After f.read(), the position is at the end, and a following json.load(f) sees an empty string:
with open("data.json", encoding="utf-8") as f:
raw = f.read()
data = json.load(f) # fails: nothing left to read
with open("data.json", encoding="utf-8") as f:
raw = f.read()
data = json.loads(raw) # parse the string you already have
Related messages
Unexpected UTF-8 BOM (decode using utf-8-sig): the file starts with a byte order mark. Open it withencoding="utf-8-sig".Extra data: line 2 column 1: the file holds one JSON object per line (JSON Lines). Parse each line separately.Expecting property name enclosed in double quotes: single quotes (often a Python dict written withstr()), or a trailing comma. Write files withjson.dump().
A loader with useful errors
This helper handles the BOM, rejects empty files, and shows the text around the problem:
import json
from pathlib import Path
def load_json_file(path):
text = Path(path).read_text(encoding="utf-8-sig")
if not text.strip():
raise ValueError(f"{path} is empty")
try:
return json.loads(text)
except json.JSONDecodeError as err:
snippet = text[max(err.pos - 40, 0):err.pos + 40]
raise ValueError(f"{path}: {err.msg} at line {err.lineno}, column {err.colno}: {snippet!r}") from None
def load_json_lines(path):
with open(path, encoding="utf-8") as f:
return [json.loads(line) for line in f if line.strip()]
If you control the code that produces the data, the real fix is there: always write with json.dump, write UTF-8, and return a proper status code with a JSON body for errors.
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0007 Fix: ModuleNotFoundError: No module named ‘…’ Python cannot find a module you import. Usually the package was installed into a different interpreter or virtual environment than the one… Beginner · Fixes an error · Any system Article Common errors · Environments & packages 15 Oct 2026
- 0008 Fix: TypeError: ‘NoneType’ object is not subscriptable You used [ ] on a value that is None. Something you expected to return a list, dict or match returned nothing.… Beginner · Fixes an error · Any system Article Common errors 15 Oct 2026
- 0009 CSV to JSON converter A small command-line tool that turns a CSV file into a JSON array of objects, with optional number detection, custom delimiters and… Beginner · Step by step · Any system Script CSV & JSON · Files & automation 15 Oct 2026
- 0072 CSV vs JSON: choosing a format and avoiding the classic pitfalls CSV is a simple table of text; JSON holds nested, typed data. Both break in predictable ways: quoting, delimiters, encodings, numbers and… Beginner · Explains an idea · Any system Article CSV & JSON 15 Oct 2026
- 0075 CSV to JSON converter (Python, standard library) Convert any CSV file with a header row into a JSON array or JSON Lines. Handles quoted fields, a byte order mark,… Beginner · Step by step · Any system Script CSV & JSON · Files & automation 15 Oct 2026
- 0076 jq recipes: 23 one-liners for JSON on the command line A runnable collection of jq filters for everyday JSON work: pick fields, filter with select, reshape, sort, count, group, pass shell variables,… Intermediate · Cheat sheet · Linux, macOS, Windows Script Command-line tools · jq & JSON on the command line 15 Oct 2026
Repos in the wild
- Ruff: Python linter and formatter astral-sh/ruff Ruff is a fast Python linter and code formatter written in Rust. It catches bugs such as undefined names and unused imports before you run your code. GitHub
- jq: command-line JSON processor jqlang/jq jq is a small command-line tool for reading, filtering and transforming JSON, like sed and awk for structured data. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Dominik +3,373 chars