bytes.replace()

Bytes are immutable, so this always allocates. When you are patching a large buffer repeatedly, that is the cost to watch — bytearray exists for exactly that case.

Bytes methodPython 3.0+Live demo
Common call
data.replace(b'\r\n', b'\n')
Returns
a new bytes object; the original is untouched
Replaces
manual slicing and concatenation around each match
Watch out
both arguments must be bytes, and the result must be assigned
bytes.replace(oldold — Sequence to look for. An empty value inserts new at every gap.type: bytes · required, new[, count])
→ bytes

Demo

Live evaluation
Try:
Inputs
sstrdata (encoded as utf-8)
oldstrsequence to replace
newstrreplacement
Output
bytes('abcabc', 'utf-8').replace(bytes('a', 'utf-8'), bytes('X', 'utf-8'))
b'XbcXbc'

Every occurrence is replaced unless you pass a count. A sequence that is not present gives the original back unchanged — no error. Replacing with an empty value deletes. The empty-old case is the surprising one: an empty sequence matches at every gap, so the replacement is inserted before each byte and after the last. The multi-byte case works because both arguments were encoded the same way, which is exactly why replacing bytes across mismatched encodings goes wrong.

Parameters

NameTypeRequiredDescription
oldbytesyesSequence to look for. An empty value inserts new at every gap.
newbytesyesReplacement. May be a different length, or empty to delete.
countintno (-1)Maximum replacements. Negative or omitted means replace every occurrence.

Return value

bytes — A NEW bytes object with occurrences of old replaced by new. The original is never modified.

Common patterns

Normalise line endings
The most common real use, on data read in binary mode.
unix = data.replace(b'\r\n', b'\n')
Strip a byte you do not want
An empty replacement deletes.
clean = data.replace(b'\x00', b'')
Patch just the first occurrence
count limits how many are changed.
patched = data.replace(old, new, 1)

Examples

1. Replace all
b'abcabc'.replace(b'a', b'X')
Returns
b'XbcXbc'
2. Absent is a no-op
b'abc'.replace(b'z', b'X')
Returns
b'abc'
3. Delete
b'abcabc'.replace(b'a', b'')
Returns
b'bcbc'
4. Limit with count
b'aaa'.replace(b'a', b'X', 1)
Returns
b'Xaa'
5. Empty old inserts
b'abc'.replace(b'', b'-')
Returns
b'-a-b-c-'
6. str rejected
b'abc'.replace('a', 'X')
Returns
TypeError

Pitfalls

1. It returns a new object — assign the result
Bytes are immutable, so replace cannot modify in place. Calling it and discarding the return value is a no-op that looks like it worked.
Result thrown away
data.replace(b'a', b'X')
data
unchanged
Assign it
data = data.replace(b'a', b'X')
updated
2. Repeated replaces on a big buffer are expensive
Every call copies the whole buffer. Chaining several on a large payload is quietly O(n) per call — bytearray supports in-place edits when that matters.
Copies each time
for old, new in rules:
    data = data.replace(old, new)
a full copy per rule
Mutable buffer
buf = bytearray(data)
# edit slices in place
no repeated copying
3. An empty old inserts everywhere
Rarely what anyone intends. The empty sequence matches at every gap, so you get the replacement woven through the entire buffer.
Woven through
b'abc'.replace(b'', b'-')
b'-a-b-c-'
Guard it
if old:
    data = data.replace(old, new)
no surprise
4. Both arguments must be bytes
Mixing a str into either position is a TypeError. Since the two look similar in source, this often survives review and fails at runtime.
str rejected
b'abc'.replace('a', b'X')
TypeError: a bytes-like object is required, not 'str'
Encode both
b'abc'.replace(b'a', b'X')
b'Xbc'

When to use

Use it
  • Normalising line endings in binary-mode data
  • Stripping or swapping a marker in a payload
  • Small, one-off patches to a buffer
Reach for something else
  • Many edits to a large buffer → bytearray, edited in place
  • The data is text → decode first and use str.replace
  • Pattern matching rather than a literal → the re module works on bytes too

Notes

Complexity
O(n) — the whole buffer is copied into the result
Return
A new bytes object; CPython may return the original when nothing matched
CPython impl
Objects/bytesobject.c :: bytes_replace
Memory
Allocates a new buffer sized for the result
Thread-safe
Yes — bytes are immutable

FAQ

Because bytes are immutable — replace builds a new object and returns it. If you did not assign the result, the original is still exactly as it was.

data = data.replace(b'a', b'X')

History

3.0
bytes.replace arrived with the bytes type in the text/binary split.