How to Resolve Python "TypeError: 'Response' object is not subscriptable"
When working with HTTP requests in Python using the popular requests
library, you might encounter the TypeError: 'Response' object is not subscriptable
. This error arises when you attempt to access data within the response using dictionary-style square brackets (response['key']
) directly on the Response
object returned by requests.get()
, requests.post()
, etc.
This guide explains why the Response
object isn't directly subscriptable and shows the correct way to access JSON response data using the .json()
method.
Understanding the Error: Response
Object vs. Response Body
When you make a request using requests.get(...)
or requests.post(...)
, the library returns a requests.Response
object. This object is a container for the entire HTTP response, including:
- Status code (
response.status_code
) - Headers (
response.headers
) - Raw content/body (
response.content
for bytes,response.text
for decoded string) - Methods to decode common formats (like
response.json()
) - And more...
The Response
object itself is not the data payload (like a dictionary or list) returned by the server. It's the wrapper around that data and other response metadata. Therefore, you cannot directly access potential dictionary keys using square brackets on the Response
object itself.
The Cause: Trying to Index the Response
Object Directly
The TypeError
occurs because you are treating the Response
object as if it were a dictionary or list by using square brackets [...]
(the subscription operator).
import requests
# Assume this URL returns JSON like: {"userId": 1, "id": 1, "title": "..."}
url = 'https://jsonplaceholder.typicode.com/todos/1'
try:
print(f"Making GET request to {url}...")
response = requests.get(url, timeout=10)
response.raise_for_status() # Check for HTTP errors
print(f"Response object type: {type(response)}")
# Output: Response object type: <class 'requests.models.Response'>
# Error Scenario: Trying to access 'userId' directly on the Response object
# ⛔️ TypeError: 'Response' object is not subscriptable
user_id = response['userId'] # Incorrect: Response object is not a dictionary
print(f"User ID: {user_id}")
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
except TypeError as e:
print(f"Caught Error: {e}") # This is where the error occurs
Python correctly tells you that the Response
object doesn't support item access via []
.
The Solution: Parse the JSON Body with .json()
If the API you are calling returns data in JSON format (which is very common), the requests
library provides a convenient .json()
method on the Response
object. This method:
- Reads the response body.
- Attempts to parse the body as JSON.
- Returns the parsed data as a standard Python object (usually a
dict
orlist
).
Once you have the Python dictionary or list returned by .json()
, that object is subscriptable.
import requests
url = 'https://jsonplaceholder.typicode.com/todos/1'
try:
print(f"Making GET request to {url}...")
response = requests.get(url, timeout=10)
response.raise_for_status()
# 1. Call .json() to parse the response body
parsed_data = response.json()
print(f"Parsed data type: {type(parsed_data)}")
# Output: Parsed data type: <class 'dict'>
print(f"Parsed data: {parsed_data}")
# Output: Parsed data: {'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
# 2. Now access keys using square brackets on the PARSED data (the dictionary)
user_id = parsed_data['userId']
title = parsed_data['title']
print(f"\nUser ID: {user_id}") # Output: User ID: 1
print(f"Title: {title}") # Output: Title: delectus aut autem
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
except requests.exceptions.JSONDecodeError as e:
# Handle cases where the response body isn't valid JSON
print(f"JSON Decode Error: Response body could not be parsed as JSON - {e}")
print(f"Response text: {response.text[:100]}...") # Show beginning of text
except KeyError as e:
# Handle cases where the expected key is missing in the parsed JSON
print(f"KeyError: Key '{e}' not found in the JSON response.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Call response.json()
first, then use ['key']
on the resulting dictionary. Always consider adding try...except
blocks for potential JSONDecodeError
(if the response isn't valid JSON) and KeyError
(if the expected key isn't in the response).
Example: POST Request
The principle is identical for POST requests that return a JSON response.
import requests
url = 'https://jsonplaceholder.typicode.com/posts'
payload = {'title': 'My Post', 'body': 'This is the content.', 'userId': 5}
try:
print(f"\nMaking POST request to {url}...")
response = requests.post(url, json=payload, timeout=10) # Using json= automatically sets headers
response.raise_for_status()
# 1. Parse the JSON response
parsed_response_data = response.json()
print(f"Parsed POST response: {parsed_response_data}")
# Output: Parsed POST response: {'title': 'My Post', 'body': 'This is the content.', 'userId': 5, 'id': 101}
# 2. Access data from the parsed dictionary
new_post_id = parsed_response_data['id']
print(f"New Post ID: {new_post_id}")
# Output: New Post ID: 101
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
except requests.exceptions.JSONDecodeError as e:
print(f"JSON Decode Error: {e}\nResponse text: {response.text[:100]}...")
except KeyError as e:
print(f"KeyError: Key '{e}' not found.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
Why the Error Occurs: Subscriptable Objects
As mentioned, the TypeError: 'X' object is not subscriptable
means the object X
doesn't support access via []
. This requires the object to implement a special method called __getitem__
.
- Subscriptable built-in types:
list
,tuple
,dict
,str
(they all have__getitem__
). - Non-subscriptable: Standard objects (like
requests.Response
), numbers, booleans,None
, etc., generally do not implement__getitem__
in a way that allows arbitrary indexing or key lookup.
The response.json()
method returns a standard Python dict
or list
, which are subscriptable.
Conclusion
The TypeError: 'Response' object is not subscriptable
arises when using the requests
library because you are incorrectly trying to access data using dictionary-style square brackets ([]
) directly on the Response
object itself.
The correct solution is to first parse the JSON response body into a Python dictionary or list using the response.json()
method. You can then use square brackets (parsed_data['key']
or parsed_data[index]
) on the resulting Python object.
import requests
response = requests.get("some_api_url")
response.raise_for_status() # Check for errors
# INCORRECT: data = response['some_key']
# CORRECT:
try:
parsed_data = response.json() # Parse first
value = parsed_data['some_key'] # Access the dictionary/list
print(value)
except requests.exceptions.JSONDecodeError:
print("Response was not valid JSON")
except KeyError:
print("Key 'some_key' not found in JSON response")
Remember to handle potential JSONDecodeError
and KeyError
exceptions for robust code.