bytearray.insert()

Places a byte BEFORE the given position, shifting the rest right. Like list.insert, an impossible index clamps silently rather than raising.

Bytearray methodPython 3.0+Live demo
Common call
buf.insert(0, 0x02)
Returns
None — the buffer grows by one
Replaces
buf[i:i] = bytes([byte])
Watch out
an out-of-range index does NOT raise — it clamps to an end
bytearray.insert(indexindex — Position to insert BEFORE. Negative counts from the end. Out-of-range values clamp to 0 or to the length.type: int · required, bytebyte — An integer from 0 to 255. A bytes object raises TypeError.type: int · required)
→ None

Demo

Live evaluation
Try:
Inputs
sstrstarting buffer (as text)
indexintposition to insert before
byteintbyte value 0-255
Output
[b := bytearray(bytes('abc', 'utf-8')), b.insert(0, 122), b][2]
bytearray(b'zabc')

The byte goes BEFORE the given position, so inserting at 0 puts it first and inserting at the length puts it last. The clamping cases are the ones to note: an index of 99 on a three-byte buffer does not raise — it simply appends. A negative index counts from the end, so -1 inserts before the LAST byte rather than after it, which is a persistent off-by-one.

Parameters

NameTypeRequiredDescription
indexintyesPosition to insert BEFORE. Negative counts from the end. Out-of-range values clamp to 0 or to the length.
byteintyesAn integer from 0 to 255. A bytes object raises TypeError.

Return value

None — Returns None — the buffer is mutated. The demo wraps the call so the resulting buffer is visible.

Common patterns

Prepend a framing byte
Adding a length or type marker at the front of a record.
buf.insert(0, len(payload))
Splice into a fixed offset
Useful when patching a header field in place.
buf.insert(HEADER_END, flag_byte)
Prefer append for the end
insert at the length works but says less about intent.
buf.append(byte)   # clearer than insert(len(buf), byte)

Examples

1. At the front
b = bytearray(b'abc') b.insert(0, 122) b
Returns
bytearray(b'zabc')
2. In the middle
b = bytearray(b'abc') b.insert(1, 122) b
Returns
bytearray(b'azbc')
3. Past the end clamps
b = bytearray(b'abc') b.insert(99, 122) b
Returns
bytearray(b'abcz')
4. Negative index
b = bytearray(b'abc') b.insert(-1, 122) b
Returns
bytearray(b'abzc')
5. Out of range value
bytearray(b'abc').insert(0, 256)
Returns
ValueError: byte must be in range(0, 256)
6. Returns None
bytearray(b'abc').insert(0, 122)
Returns
None

Pitfalls

1. Out-of-range indexes clamp silently
Unlike indexing or deleting, insert never raises IndexError. A huge index appends and a very negative one prepends, so a bad offset produces a plausible buffer instead of an error.
No error
b = bytearray(b'abc')
b.insert(999, 122)
b
bytearray(b'abcz')
Validate first
if 0 <= i <= len(b):
    b.insert(i, byte)
else:
    raise IndexError(i)
explicit
2. insert(-1, x) goes before the last byte
People read -1 as "at the end". It means "before the final byte", so the inserted value ends up second from last.
Not last
b = bytearray(b'abc')
b.insert(-1, 122)
b
bytearray(b'abzc')
Append instead
b.append(122)
bytearray(b'abcz')
3. It takes an int, not bytes
Same rule as append — one byte means one integer. A one-byte bytes object is still a TypeError.
bytes rejected
buf.insert(0, b'z')
TypeError: 'bytes' object cannot be interpreted as an integer
Pass the value
buf.insert(0, ord('z'))
inserted
4. Inserting at the front is O(n)
Every following byte shifts right by one. Repeatedly prepending to a large buffer is quadratic — build in reverse and reverse once, or use a deque.
Quadratic
for v in values:
    buf.insert(0, v)
shifts everything each time
Append then reverse
for v in values:
    buf.append(v)
buf.reverse()
linear

When to use

Use it
  • Prepending a framing or length byte
  • Splicing a value into a known offset
  • Small buffers where the shift cost is irrelevant
Reach for something else
  • Adding at the end → append says what you mean
  • Repeated prepending on a large buffer → build reversed, or use a deque
  • Adding several bytes → extend, or slice assignment

Notes

Complexity
O(n) — every byte from the index onward shifts right
Return
None; the bytearray is mutated in place
CPython impl
Objects/bytearrayobject.c :: bytearray_insert
Memory
May reallocate the internal buffer; the shift itself is in place
Thread-safe
Not safe under concurrent mutation of the same buffer

FAQ

Because insert is defined to clamp, matching list.insert. It is convenient when the index comes from arithmetic that might overshoot, and a nuisance when you wanted validation — so validate explicitly if a bad index is a bug.

if not 0 <= i <= len(buf):
    raise IndexError(i)

History

3.0
bytearray introduced as the mutable counterpart to bytes.