TypeError: list indices must be integers or slices, not str (tested fix)

TypeError: list indices must be integers or slices, not str means you used a key like ["name"] on a list. Usually it's a JSON list of objects. We reproduced it in Python 3.13 along with the not float and not dict variants.

1. Indexing a list with a key

Lists are indexed by position (0, 1, ...), not by name. The classic case is JSON: the top level is a list of dicts, and the code indexes it as if it were one dict:

import json
users = json.loads('[{"name": "ann"}, {"name": "bob"}]')   # a list of dicts
for expr in ['users["name"]', 'users["0"]', 'users[1.0]', 'users[0]["name"]']:
    try:
        print(f"{expr:18} OK -> {eval(expr)!r}")
    except TypeError as e:
        print(f"{expr:18} TypeError: {e}")

Output:

users["name"]      TypeError: list indices must be integers or slices, not str
users["0"]         TypeError: list indices must be integers or slices, not str
users[1.0]         TypeError: list indices must be integers or slices, not float
users[0]["name"]   OK -> 'ann'

A numeric string ("0") fails too. A float fails with not float.

2. The fix: pick an item first, or loop

import json
users = json.loads('[{"name": "ann"}, {"name": "bob"}]')
print([u["name"] for u in users])          # loop over the list, index each dict
for i, u in enumerate(users):              # 'for i in users' gives the items, not indexes
    print(i, u["name"])
row = ["ann", "31"]
idx = "1"                                  # e.g. from input()
print(row[int(idx)])

Output:

['ann', 'bob']
0 ann
1 bob
31

Index the list by position (users[0]["name"]) or loop over it and index each dict. If you need positions, use enumerate(). Convert index strings from input() or URLs with int().

3. The loop variable is the item, not the index

for item in data gives the items themselves, so data[item] indexes the list with a dict:

data = [{"id": 7}]
for item in data:
    print(data[item])          # bug: item is already the dict

Output:

Traceback (most recent call last):
  File "/tmp/li/b3.py", line 3, in <module>
    print(data[item])          # bug: item is already the dict
          ~~~~^^^^^^
TypeError: list indices must be integers or slices, not dict

Use item directly. If the message ends in not tuple, you likely wrote x[i, j] on a nested list; use x[i][j]. For slices (x[a:b]) the message is different. See slice indices must be integers or None.

Frequently asked questions

How do I fix list indices must be integers or slices, not str?

The value is a list, not a dict. Pick an item first (data[0]['name']) or loop: [u['name'] for u in data].

Why does my JSON give a list instead of a dict?

The JSON's top level is [...]. json.loads returns a list of dicts; index by position, then by key.

What does list indices must be integers or slices, not dict mean?

You looped with for item in data and then wrote data[item]. item is already the element; use it directly.

Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5: a JSON list of dicts indexed with a key, a numeric string and a float, the loop, enumerate and int() fixes, and a loop item used as an index. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.