← Back

Home › Errors › TypeError

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

  1. Put print(type(x), repr(x)) on the line before the crash. repr shows quotes, so a string '91' is instantly distinguishable from the number 91.
  2. If the value is a string that looks like JSON, you forgot json.loads().
  3. If the value is a short word like name or id, you are iterating a dict's keys — switch to .items() or .values().
  4. 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.
  5. 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

🇮🇳 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.

Python dictionary Hindi में पढ़ें →