Fix TypeError: String Indices Must Be Integers

Quick answer: A string can be indexed only by an integer or slice, so text[‘name’] raises this TypeError. If the data should have named fields, parse or construct a dictionary or object first; if it is truly text, use numeric positions or a substring operation.

Python Pool infographic showing string integer indexing JSON parsing dictionary keys and loop value types
Strings use integer positions; dictionary keys require a mapping object, so inspect and parse the value before using bracket access.

TypeError: string indices must be integers means Python is treating a value as a string, but your code is indexing it as if it were a dictionary, list of dictionaries, or another keyed object. Strings are sequences of characters. They accept integer positions and slices, not string keys.

The fix is to check what type the variable really has at the failing line. If it is a string, use an integer index such as text[0] or parse the string into the data structure you expected. If it is supposed to be a dictionary, make sure your code is working with the dictionary object, not a JSON string or a dictionary key.

Why the Error Happens

The simplest way to reproduce the error is to use a string key on a string value. Python cannot look up a character by the key "p"; it can only look up characters by numeric positions.

message = "python"

print(message["p"])

The variable message is a string. To read from a string, use an integer index or a slice. Index 0 means the first character, index 1 means the second character, and so on. When the traceback says not 'str' at the end, it is giving the same clue: your index value is a string, but Python expected an integer position.

Use Integer Indexes and Slices for Strings

Use this form when your value really is text and you want characters from it. A slice can return more than one character while still using integer boundaries.

message = "python"

print(message[0])
print(message[1:4])

This prints the first character and then a substring. If you are validating user input, PythonPool’s guide to checking whether a string is an integer may also be useful. Keep string indexing for character work; do not use it as a substitute for parsing structured data.

Python Pool infographic showing string value, non-integer index, bracket access, and TypeError traceback
String indexing accepts integer positions or slices, not arbitrary keys such as words.

Parse JSON Before Using Dictionary Keys

A very common cause is API or file data that looks like a dictionary but is still a JSON string. String data must be parsed before you can access keys such as "user" or "score".

payload = '{"user": "Ada", "score": 91}'

print(payload["user"])

The code above fails because payload is text. Parse it with json.loads() first, then access dictionary keys.

import json

payload = '{"user": "Ada", "score": 91}'
data = json.loads(payload)

print(data["user"])
print(data["score"])

This works because data is now a dictionary. The string key belongs on the dictionary, not on the raw JSON string. This pattern appears often after reading from files, receiving HTTP responses, or loading values from environment variables.

Watch Dictionary Loops

Another common bug appears when looping over a dictionary. Iterating over a dictionary directly gives you its keys. Those keys are often strings, so indexing the key as if it were a nested dictionary produces this TypeError.

person = {"name": "Ada", "language": "Python"}

for key in person:
    print(key["name"])

Here key is first "name" and then "language". Each key is a string, not a dictionary. Use .items() when you need both keys and values.

person = {"name": "Ada", "language": "Python"}

for key, value in person.items():
    print(key, value)

If your data is a list of dictionaries, loop through the list and then index each dictionary: user["name"]. PythonPool’s guides to iterating through lists and finding strings in lists cover the related list patterns.

How to Debug the Failing Line

At the line that raises the error, print or inspect the variable before indexing it. If type(value) is str, use integer indexes, parse it, or follow the code path backward to find where the wrong type was assigned. If the value should be a dictionary, confirm that the parser ran successfully and that the variable was not overwritten later.

Do not patch this error by blindly changing the index to 0. That may hide the crash while returning the wrong character from a string. The correct fix should match the data model: character access for strings, key lookup for dictionaries, and row-by-row access for lists of dictionaries.

This error is different from trying to subscript a number. If your traceback says an integer is not subscriptable, see PythonPool’s TypeError: int object is not subscriptable guide. If the traceback is related to NumPy scalar conversion, the only size-1 arrays can be converted to Python scalars guide covers that separate issue.

Python Pool infographic showing string, for loop, integer position, character access, and output
Use integer positions while iterating a string or iterate its characters directly.

Checklist

  • Use text[0] or text[start:end] for strings.
  • Use json.loads() before accessing keys from JSON text.
  • Use dict.items() when looping through dictionary keys and values.
  • Check type(value) at the failing line if the data shape is unclear.

References

Distinguish Text From Mappings

The same bracket syntax means different things for different types. text[0] selects a character, while record[‘name’] selects a mapping value. Print type(value) at the failing line and trace where it was created instead of changing the index blindly.

Python Pool infographic comparing string indexing with dictionary key lookup and structured record access
Use a dictionary or parsed record when the access pattern uses named keys rather than character positions.

Use Integer Positions And Slices

Strings support zero-based integer indexes and slices such as text[1:4]. Validate bounds when a missing position is an input error, and remember that a slice returns a string while an integer index returns a one-character string.

Parse JSON Before Named Access

Reading a JSON file or HTTP response often produces a string first. Call json.loads() after validating the content and then access dictionary keys. Keep parse errors, missing keys, and wrong JSON types separate so the error message identifies the real boundary failure.

Watch Dictionary Loops

Iterating a dictionary yields keys, which may be strings. If the loop needs values, use values(); if it needs both, use items(). When a list contains records, validate each element before indexing it with a field name.

Python Pool infographic testing integer index, slice, Unicode code points, nested data, and validation
Check the actual value type, index bounds, slice semantics, Unicode characters, and whether JSON data needs parsing.

Do Not Hide Mixed-Type Data

A list containing strings and dictionaries can make a bug appear intermittent. Normalize records at ingestion, reject unexpected types, and use typed or schema validation when the data comes from an external source.

Test The Failing Shape

Test a character string, a dictionary, parsed JSON, a list of records, missing keys, numeric indexes, slices, empty input, and malformed data. Assert the intended output or controlled exception rather than relying on a generic TypeError.

The official str sequence documentation defines integer indexing and slicing. The json module reference covers parsing. Related guidance includes mapping access and type tests.

For related data parsing, compare JSON responses, structured JSON, and mapping access when separating strings from records.

Frequently Asked Questions

Why does string indices must be integers happen?

Code indexes a string with a non-integer such as a key name, even though string positions must be integers or slices.

How do I access a character in a string?

Use an integer index such as text[0] or a slice such as text[1:4].

Why does JSON data cause this error?

A JSON object may still be a string after reading it; parse it with json.loads() before accessing dictionary keys.

How do I fix the error in a loop?

Inspect whether the loop variable is a dictionary or a string, then iterate items or parse the value before using a named key.

Subscribe
Notify of
guest
2 Comments
Oldest
Newest Most Voted
Daniel
Daniel
4 years ago

Hi,
Thanks for the article, very informative. However you didn’t show how you’d solve this issue for the JSON example.

How would you get “26.96” from

for i in data['main']:
print(i['temp'])

without running into this error? I’m testing it on VS Code and while the first ‘for’ works because it’s an array, the 2nd one throws the error.

Thanks in advance,
Daniel

Last edited 4 years ago by Pratik Kinage
Pratik Kinage
Admin
4 years ago
Reply to  Daniel

Check your data[‘main’]. It probably contains string.