Remove a Character From a String in Python (by Index or Value)

To remove a character from a string in Python, you build a new string without it. Which method you want depends on whether you know the position or the character:

text[:i] + text[i+1:]     # remove the character at index i
text.replace("x", "")     # remove every "x"
text.replace("x", "", 1)  # remove only the first "x"

There is no del and no item assignment. Both raise a TypeError, which is the first thing to understand here.

Every result below is a real run on Python 3.12.5.

Removing a character by index

Slice around the position: everything before it, plus everything after it:

text = "Hello World"
i = 5                       # the space

# take everything before the index, then everything after it
result = text[:i] + text[i + 1:]

print("original:", repr(text))
print("index   :", i, "which is", repr(text[i]))
print("result  :", repr(result))

Output:

original: 'Hello World'
index   : 5 which is ' '
result  : 'HelloWorld'
Command Prompt showing a Python string with the character at index 5 removed by slicing
text[:5] is 'Hello' and text[6:] is 'World'.

The + 1 is what skips the unwanted character. Leave it out and you get the original string back.

Remember that indexes start at zero, so text[:0] + text[1:] removes the first character.

Why does del on a Python string raise a TypeError?

Python strings are immutable, so the two things you would try first both fail:

text = "Hello"

# neither of these works, because strings cannot be modified
try:
    del text[0]
except TypeError as err:
    print("del text[0]   ->", type(err).__name__ + ":", err)

try:
    text[0] = "J"
except TypeError as err:
    print("text[0] = 'J' ->", type(err).__name__ + ":", err)

print()
print("every removal below builds a NEW string, so assign the result:")
text = text[1:]
print("text is now:", repr(text))

Output:

del text[0]   -> TypeError: 'str' object doesn't support item deletion
text[0] = 'J' -> TypeError: 'str' object does not support item assignment

every removal below builds a NEW string, so assign the result:
text is now: 'ello'
Command Prompt showing TypeErrors for deleting and assigning to a character in a Python string
doesn't support item deletion and does not support item assignment.
You triedErrorUse instead
del text[0]doesn't support item deletiontext[1:]
text[0] = "J"does not support item assignment"J" + text[1:]
text.pop(0)AttributeErrorConvert to a list first

The consequence is that you must assign the result. text[1:] on its own computes a new string and throws it away. It’s the same rule that applies when you reverse a string.

Why an out-of-range index removes nothing

Slicing clamps to the string’s length rather than raising, so a bad index fails quietly:

text = "Hello"

def remove_at(s, i):
    return s[:i] + s[i + 1:]

print("index 1  :", repr(remove_at(text, 1)))
print("index 99 :", repr(remove_at(text, 99)), "  <- unchanged, and no error")

print()
# slicing clamps, so nothing warns you that the index was wrong
print("a real check first:")
i = 99
if 0 <= i < len(text):
    print("  removed:", repr(remove_at(text, i)))
else:
    print(f"  index {i} is outside 0..{len(text) - 1}")

Output:

index 1  : 'Hllo'
index 99 : 'Hello'   <- unchanged, and no error

a real check first:
  index 99 is outside 0..4
Command Prompt showing that removing a character at an out of range index returns the string unchanged with no error
Index 99 on a five-character string. No error, no change.

That silence is the problem. A loop with an off-by-one bug produces a string that looks fine and is missing nothing.

If the index comes from a calculation or user input, check it against len(text) before you slice.

Removing a character by value with replace

When you know the character rather than its position, replace is the tool:

text = "Hello World"

print("original      :", repr(text))
print("first 'l' only:", repr(text.replace("l", "", 1)))
print("every 'l'     :", repr(text.replace("l", "")))
print("the word      :", repr(text.replace("World", "")))

print()
# several different characters in one pass
table = str.maketrans("", "", "lo")
print("remove l and o:", repr(text.translate(table)))

Output:

original      : 'Hello World'
first 'l' only: 'Helo World'
every 'l'     : 'Heo Word'
the word      : 'Hello '

remove l and o: 'He Wrd'
Command Prompt showing Python replace and translate removing characters from a string
replace for one character, translate for several.

The third argument is a count. replace("l", "", 1) removes only the first match, which is what you want for stripping a single leading symbol.

str.translate with maketrans deletes several different characters in one pass. It is the fastest option when you have a list of characters to strip.

Removing characters with a regular expression

For patterns rather than fixed characters, re.sub replaces anything that matches:

import re

text = "Hello, World! 123"

print("original        :", repr(text))
print("digits gone     :", repr(re.sub(r"\d", "", text)))
print("punctuation gone:", repr(re.sub(r"[^\w\s]", "", text)))
print("letters only    :", repr(re.sub(r"[^a-zA-Z]", "", text)))

print()
# keeping what you want is often clearer than removing what you do not
print("comprehension   :", repr("".join(ch for ch in text if ch.isalpha())))

Output:

original        : 'Hello, World! 123'
digits gone     : 'Hello, World! '
punctuation gone: 'Hello World 123'
letters only    : 'HelloWorld'

comprehension   : 'HelloWorld'
  • re.sub(r"\d", "", text) — removes every digit.
  • re.sub(r"[^\w\s]", "", text) — removes punctuation, keeps letters, digits and spaces.
  • re.sub(r"[^a-zA-Z]", "", text) — keeps letters only.
  • A comprehension with isalpha() does the same thing without importing re.

Describing what to keep is usually clearer than listing everything to remove. The same applies when you remove special characters.

Removing a range of characters from a string

The slice approach extends naturally to more than one character:

text = "Python Programming"

# a single index
i = 6
print("remove one  :", repr(text[:i] + text[i + 1:]))

# a range of indexes
start, end = 6, 10
print("remove range:", repr(text[:start] + text[end:]))

# several scattered positions, removed at once
drop = {0, 6, 12}
print("remove set  :", repr("".join(ch for n, ch in enumerate(text) if n not in drop)))

print()
# via a list, when you find that easier to read
chars = list(text)
chars.pop(6)
print("list.pop    :", repr("".join(chars)))

Output:

remove one  : 'PythonProgramming'
remove range: 'Pythongramming'
remove set  : 'ythonProgrmming'

list.pop    : 'PythonProgramming'

Removing a range is text[:start] + text[end:], where end is excluded just as it is in any slice.

For scattered positions, enumerate with a set of indexes to drop is the clearest way. Deleting them one at a time shifts every later index, which is a classic source of bugs.

A list is the other option. list(text), then pop, then "".join() gives you mutability when the logic is easier to write that way.

Which character removal method is fastest in Python?

On a 20,000-character string the difference is large:

import timeit

text = "abcdefghij" * 2000     # 20,000 characters

slice_way = timeit.timeit(lambda: text[:5000] + text[5001:], number=20_000)
list_way = timeit.timeit(lambda: "".join(ch for ch in text if ch != "a"), number=200)

print(f"slice removal, 20,000 runs : {slice_way * 1000:>7.0f} ms")
print(f"comprehension, 200 runs    : {list_way * 1000:>7.0f} ms")

print()
print("the slice copies two blocks of memory and stops")
print("the comprehension tests every single character")

Output:

slice removal, 20,000 runs :      17 ms
comprehension, 200 runs    :     122 ms

the slice copies two blocks of memory and stops
the comprehension tests every single character

The slice copies two blocks of memory and stops. The comprehension inspects every character and reassembles the string one piece at a time.

For a single known position, always slice. Save the comprehension for when you genuinely need to test each character.

Common character removal mistakes

SymptomCauseFix
TypeError on delStrings are immutableSlice around the index
Nothing changedResult not assignedtext = text[:i] + text[i+1:]
Wrong character removedOff-by-one on the indexThe slice needs i + 1
Too many removedreplace with no countPass 1 as the third argument
Silent no-opIndex beyond the stringCheck against len(text)

Other Python string editing guides:

Frequently asked questions

How do I remove a character from a string in Python?

Slice around it with text[:i] + text[i+1:] for a position, or text.replace(ch, "") for a character. String methods are listed in the Python string methods reference.

Why can’t I use del on a string character?

Strings are immutable, so del text[0] raises TypeError: 'str' object doesn't support item deletion. Build a new string instead.

How do I remove a character at a specific index?

text[:i] + text[i+1:]. The + 1 is what skips the character at position i.

How do I remove only the first occurrence of a character?

Pass a count: text.replace("x", "", 1). Without it, every occurrence is removed.

How do I remove several different characters at once?

text.translate(str.maketrans("", "", "abc")) removes a, b and c in a single pass.

Why does removing at an out-of-range index do nothing?

Slicing clamps to the string length instead of raising. Check the index against len(text) first.

What is the fastest way to remove a character?

Slicing, when you know the position. It copies two blocks of memory rather than testing every character.