TypeError: string indices must be integers (tested fix)

TypeError: string indices must be integers, not 'str' means the value you indexed with ["key"] is a string, not a dict. With JSON there are three usual causes, and we reproduced each in Python 3.13.

1. You have a string where you expected a dict

x["key"] on a str raises this error. With JSON it happens three ways: the text was never parsed, a loop over a dict gives you its keys (strings), or the JSON was encoded twice:

import json
raw = '{"user": {"name": "ann"}}'
for label, expr in [("json text, not parsed", 'raw["user"]'), ("loop over dict keys", '[k["name"] for k in json.loads(raw)]'), ("double-encoded JSON", 'json.loads(json.dumps(raw))["user"]')]:
    try:
        print(f"{label:22} OK -> {eval(expr)!r}")
    except TypeError as e:
        print(f"{label:22} TypeError: {e}")

Output:

json text, not parsed  TypeError: string indices must be integers, not 'str'
loop over dict keys    TypeError: string indices must be integers, not 'str'
double-encoded JSON    TypeError: string indices must be integers, not 'str'

2. The fix for each

import json
raw = '{"user": {"name": "ann"}}'
data = json.loads(raw)                    # parse first
print(data["user"]["name"])
for key, value in data.items():           # iterating a dict gives keys; use .items()
    print(key, value["name"])
twice = json.dumps(raw)                   # JSON text encoded again -> a JSON *string*
print(type(json.loads(twice)).__name__, json.loads(json.loads(twice))["user"])

Output:

ann
user ann
str {'name': 'ann'}

Parse with json.loads() (or response.json()) before indexing. Iterate a dict with .items() when you need values. If json.loads() returns a str, the data was JSON-encoded twice; the real fix is to stop calling json.dumps() on text that is already JSON. To find which case you have, print(type(x), repr(x)[:80]) just before the failing line. For the list version of this error, see list indices must be integers or slices, not str.

Frequently asked questions

How do I fix string indices must be integers with JSON?

Parse it first: data = json.loads(text) (or response.json()), then data['key'].

Why does looping over a dict give string indices must be integers?

for k in d gives the keys, which are strings. Use for k, v in d.items() and index v.

Why does json.loads return a string?

The JSON was encoded twice (json.dumps on text that was already JSON). Remove the extra dumps.

Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5: indexing unparsed JSON text, dict keys from a loop, and double-encoded JSON with a key, and the json.loads, .items() and decode-twice fixes. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.