bytes.removeprefix()

Added in 3.9 precisely because everyone kept misusing lstrip for this. Matches the exact sequence, once, and does nothing when it is absent.

Bytes methodPython 3.9+Live demo
Common call
path.removeprefix(b'/api')
Returns
a new bytes object, or the original when the prefix is absent
Replaces
data[len(p):] if data.startswith(p) else data
Watch out
removes ONCE — a doubled prefix leaves one copy behind
bytes.removeprefix(prefixprefix — The exact byte sequence to remove from the start. An empty prefix is a harmless no-op.type: bytes · required)
→ bytes

Demo

Live evaluation
Try:
Inputs
sstrdata (encoded as utf-8)
prefixstrprefix to remove
Output
bytes('prefix_name', 'utf-8').removeprefix(bytes('prefix_', 'utf-8'))
b'name'

When the data begins with the exact prefix it is removed; when it does not, the data comes back untouched with no error. A partial match is no match — pre_name does not start with prefix_, so nothing happens. The doubled case shows the "once" rule: xxname with prefix x loses one x and keeps the other. Removing a prefix equal to the whole data leaves empty bytes.

Parameters

NameTypeRequiredDescription
prefixbytesyesThe exact byte sequence to remove from the start. An empty prefix is a harmless no-op.

Return value

bytes — The data with prefix removed from the start if it is there — otherwise the data unchanged. Never raises for a missing prefix.

Common patterns

Strip a URL scheme or path root
Exact-match removal that lstrip cannot do safely.
rest = url.removeprefix(b'https://')
Normalise a header value
Bearer tokens and similar tagged values.
token = value.removeprefix(b'Bearer ')
Pre-3.9 equivalent
The idiom removeprefix replaced.
rest = data[len(p):] if data.startswith(p) else data

Examples

1. Present
b'prefix_name'.removeprefix(b'prefix_')
Returns
b'name'
2. Absent
b'name'.removeprefix(b'prefix_')
Returns
b'name'
3. Partial
b'pre_name'.removeprefix(b'prefix_')
Returns
b'pre_name'
4. Once only
b'xxname'.removeprefix(b'x')
Returns
b'xname'
5. Whole
b'abc'.removeprefix(b'abc')
Returns
b''
6. lstrip differs
b'https://x'.lstrip(b'http://')
Returns
b's://x' # mangled — set semantics

Pitfalls

1. It removes the prefix once, not repeatedly
Unlike lstrip, which keeps going, removeprefix takes off exactly one copy. A repeated prefix needs a loop.
One copy left
b'xxname'.removeprefix(b'x')
b'xname'
Loop for all
while d.startswith(b'x'):
    d = d.removeprefix(b'x')
b'name'
2. No error when the prefix is missing
Silence is the design, but it means a typo in the prefix goes unnoticed — the data just comes back unchanged.
Typo hidden
b'Bearer abc'.removeprefix(b'Bearer:')
b'Bearer abc' # unchanged, no error
Check first
if not v.startswith(b'Bearer '):
    raise ValueError('bad header')
explicit
3. Python 3.9 and newer only
Older interpreters raise AttributeError. Code supporting 3.8 still needs the startswith-and-slice idiom.
Fails on 3.8
b'ab'.removeprefix(b'a')
AttributeError: 'bytes' object has no attribute 'removeprefix'
Portable form
d[len(p):] if d.startswith(p) else d
works everywhere

When to use

Use it
  • Removing a known scheme, root or tag from the start
  • Anywhere lstrip was being misused for an exact prefix
  • Optional prefixes where absence is normal
Reach for something else
  • Removing a SET of leading bytes → lstrip
  • A prefix that must be present → check with startswith and raise
  • Supporting Python 3.8 or older without a fallback

Notes

Complexity
O(len(prefix)) to check, then a slice
Return
A new bytes object; the original when the prefix is absent
CPython impl
Objects/bytesobject.c :: bytes_removeprefix
Memory
Allocates the shortened result
Thread-safe
Yes — bytes are immutable

FAQ

Because lstrip strips a SET of bytes, not a sequence, and people misused it for prefixes constantly. b"https://x".lstrip(b"http://") gives b"s://x" — it strips h, t, t, p and stops at the s, which is not in the set. removeprefix matches the exact sequence, which is what everyone meant.

b'https://x'.removeprefix(b'http://')
# b'https://x' — correctly unchanged

History

3.9
removeprefix and removesuffix added to str, bytes and bytearray by PEP 616.