What Are the Differences Between json.load() and json.loads() in Python
Python's json module provides two functions for converting JSON data into Python objects: json.load() and json.loads(). The distinction is straightforward: the "s" in loads stands for "string." One reads JSON from a file, the other parses JSON from a string already in memory. Mixing them up is one of the most common mistakes when working with JSON in Python.
This guide explains when to use each function, shows the errors you get when you confuse them, and covers practical patterns for handling JSON from different sources.
json.loads(): Parse JSON from a String
json.loads() takes a JSON-formatted string and converts it into a Python object. This is the function you use when working with API responses, data received over a network, or any JSON that is already stored in a variable:
import json
api_response = '{"id": 1, "status": "ok", "data": [1, 2, 3]}'
data = json.loads(api_response)
print(data["status"])
print(data["data"])
print(type(data))
Output:
ok
[1, 2, 3]
<class 'dict'>
The JSON string is parsed into a native Python dictionary that you can work with directly.
json.load(): Read and Parse JSON from a File
json.load() reads JSON directly from a file object opened with open(). It handles both reading the file content and parsing the JSON in a single step:
import json
with open("config.json", "r") as f:
config = json.load(f)
print(config)
print(type(config))
If config.json contains {"database": {"host": "localhost", "port": 5432}}, the output is:
{'database': {'host': 'localhost', 'port': 5432}}
<class 'dict'>
The rule is simple: if you used open(), use load(). If you have a string variable, use loads().
Common Mistake: Mixing Up the Two Functions
Passing the wrong type of argument to each function produces clear but different errors. Recognizing these error messages helps you quickly identify the problem:
import json
# Wrong: passing a file object to loads()
with open("data.json") as f:
try:
data = json.loads(f)
except TypeError as e:
print(f"Error: {e}")
Output:
Error: the JSON object must be str, bytes or bytearray, not TextIOWrapper
import json
# Wrong: passing a string to load()
json_str = '{"key": "value"}'
try:
data = json.load(json_str)
except AttributeError as e:
print(f"Error: {e}")
Output:
Error: 'str' object has no attribute 'read'
The fix in both cases is to use the correct function:
import json
# Correct: load() for file objects
with open("data.json") as f:
data = json.load(f)
# Correct: loads() for strings
json_str = '{"key": "value"}'
data = json.loads(json_str)
Reading a File as a String, Then Parsing
Sometimes you need to read the file content first for inspection, validation, or logging before parsing it. In that case, you read the file into a string with .read() and then use json.loads():
import json
# Two-step approach: read, then parse
with open("data.json", "r") as f:
content = f.read() # content is now a string
print(f"Raw JSON ({len(content)} characters):")
print(content[:100])
data = json.loads(content) # parse the string
print(f"\nParsed type: {type(data)}")
This is functionally equivalent to using json.load(f) directly, but gives you access to the raw JSON string before parsing.
Handling Character Encoding
JSON files sometimes contain non-ASCII characters. Specifying the encoding when opening the file prevents decoding errors:
import json
# Specify encoding for files with non-ASCII content
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
# For JSON received as bytes (e.g., from a network socket)
json_bytes = b'{"name": "Alice"}'
# Option 1: Decode explicitly
data = json.loads(json_bytes.decode("utf-8"))
# Option 2: Pass bytes directly (Python 3.6+)
data = json.loads(json_bytes)
print(data)
Output:
{'name': 'Alice'}
Since Python 3.6, json.loads() accepts bytes and bytearray objects directly, so explicit decoding is optional in most cases. However, specifying the encoding explicitly is still good practice when you know the source encoding differs from the default.
Parsing JSON Lines Format
Some data files use the JSON Lines format (.jsonl), where each line is a separate, independent JSON object. Since the file as a whole is not valid JSON, you cannot use json.load() on the entire file. Instead, read each line and parse it individually with json.loads():
import json
# Each line in events.jsonl is a separate JSON object:
# {"event": "login", "user": "alice"}
# {"event": "purchase", "user": "bob"}
# {"event": "logout", "user": "alice"}
with open("events.jsonl", "r") as f:
events = [json.loads(line) for line in f if line.strip()]
for event in events:
print(f"{event['user']}: {event['event']}")
Output:
alice: login
bob: purchase
alice: logout
Common Errors and How to Fix Them
| Error Message | Cause | Fix |
|---|---|---|
TypeError: must be str, not TextIOWrapper | Passed a file object to loads() | Use load() instead |
AttributeError: 'str' has no attribute 'read' | Passed a string to load() | Use loads() instead |
JSONDecodeError: Expecting property name | Single quotes in JSON string | Replace with double quotes |
JSONDecodeError: Extra data | Multiple JSON objects in one string | Parse line by line with loads() |
The Complete json Module Pattern
The "s" suffix convention applies consistently across all four primary functions in the json module:
| Function | Source/Target | Direction | Typical Use Case |
|---|---|---|---|
json.load() | File object | JSON to Python | Reading configuration files, loading saved data |
json.loads() | String | JSON to Python | Parsing API responses, processing received data |
json.dump() | File object | Python to JSON | Saving configuration, exporting data |
json.dumps() | String | Python to JSON | Building API responses, logging |
Summary
- Use
json.load()when reading JSON from a file object opened withopen(). - Use
json.loads()when parsing a JSON string from an API response, a database field, or any variable already in memory.
The "s" suffix consistently means "string" across the entire json module, applying equally to dump()/dumps() for serialization.
Mixing up the two functions produces clear error messages (TypeError for loads() with a file, AttributeError for load() with a string), so if you see either of these errors, check which function you are using and switch to the correct one.