TypeError: string indices must be integers
Exception: TypeErrorCategory: runtimeRaised at: the moment a string is subscripted with anything but an integer or slice
What this error means
You wrote something["key"] and something turned out to be a string, not a dictionary. Strings can only be indexed by position — s[0], s[-1], s[2:5] — so a string key is rejected outright. Python 3.11+ appends the offending type: string indices must be integers, not 'str'.
The message is a gift: it names both the container (str) and the key type ('str'). Ninety percent of the time the real bug is that a variable you believed held a dict actually holds a key or an unparsed JSON string.
Cause 1 — looping a dict and using the key as the value
student = {"name": "Asha", "marks": 91}
for key in student:
print(key["name"]) # key is the string "name", not the dict
Traceback (most recent call last):
File "demo.py", line 4, in <module>
print(key["name"])
~~~^^^^^^^^
TypeError: string indices must be integers, not 'str'
Iterating a dict yields its keys, which are strings. On the first pass key is literally "name", so key["name"] asks a string for a named position. The fixes:
for key, value in student.items(): # both at once
print(key, value)
for key in student: # key only, then look up
print(key, student[key])
for value in student.values(): # values only
print(value)
Cause 2 — JSON that was never parsed
A response body, a file's contents and a database column all arrive as str. Indexing them as if they were already structured data gives this exact error, because data[0] returns the single character [ and you then index that with a key:
import json
data = '[{"id": 1, "name": "Asha"}]' # still a string!
print(data[0]["name"]) # data[0] == "["
parsed = json.loads(data) # now it is a list of dicts
print(parsed[0]["name"]) # Asha
Rule of thumb: if the data came from requests.get(...).text, f.read() or a TEXT column, it is a string until you call json.loads() on it. (requests.get(...).json() does the parsing for you.)
Cause 3 — one level too deep or too shallow
Nested structures fail the same way when the nesting you assume is not the nesting you have. users below is a list of dicts, so users["name"] indexes the list with a string — that raises TypeError: list indices must be integers or slices, not str, the sibling of this error. Going one level deeper than the data does raises this one:
users = [{"name": "Asha"}, {"name": "Ravi"}]
users[0]["name"] # 'Asha' — correct
users[0]["name"][0] # 'A' — a string, still valid
users[0]["name"]["x"] # TypeError: string indices must be integers
Print type(variable) immediately before the failing line. If it says str where you expected dict or list, you are one level off — or the data was never parsed.
How to debug it
- Put
print(type(x), repr(x))on the line before the crash.reprshows quotes, so a string'91'is instantly distinguishable from the number91. - If the value is a string that looks like JSON, you forgot
json.loads(). - If the value is a short word like
nameorid, you are iterating a dict's keys — switch to.items()or.values(). - If the data came from an API, log the raw response body once. Most 'my JSON is broken' reports are an HTML error page returned with status 200.
- Guard the lookup while you investigate:
value = row.get("name") if isinstance(row, dict) else row.
Fix it interactively
Practice the indexing and dict-loop rules on these free problems — they run in your browser:
Practice more Python bugs →Related messages worth knowing
- TypeError: list indices must be integers — the same mistake on a list instead of a string.
- KeyError — the container really was a dict — the key was just absent.
- TypeError: 'int' object is not subscriptable — the mirror case: a plain number where a container belongs.
- TypeError: the parent guide — the famous wordings decoded together.
🇮🇳 Hindi में समझें
TypeError: string indices must be integers ka matlab hai: aapne kisi string ko dictionary ki tarah ["key"] se access kiya. String sirf position se index hoti hai (s[0], s[-1]), naam se nahi. Do sabse common wajah: (1) dict par for key in student: chalaya aur phir key["name"] likh diya — key khud ek string hai, dict nahi; fix hai for key, value in student.items():. (2) JSON abhi bhi string hai — json.loads() lagana bhool gaye, isliye data[0] ek character deta hai. Failing line se ek line pehle print(type(x), repr(x)) lagao: '91' quotes ke saath dikhe to wo string hai, number nahi.