bytes.zfill()
Zero-padding that knows about signs. The sign-aware rule is what separates it from rjust with a zero fill — and also what makes it do odd things to non-numeric data.
Demo
Zeros are inserted on the left until the buffer reaches the width. The sign cases show the rule that matters: a leading minus or plus stays in FRONT, with the zeros after it, so -42 becomes -0042 rather than 00-42. Data already at or beyond the width is returned untouched — it never truncates. And it pads anything at all, not just digits, which is how ab becomes 00ab.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| width | int | yes | Minimum total length. If the data is already this long or longer it is returned unchanged. |
Return value
bytes — A new bytes object left-padded with 0x30 bytes to at least width. A leading + or - stays at the front, ahead of the zeros. Never truncates.
Common patterns
field = str(n).encode().zfill(8)
field = f'{n:08d}'.encode()
digest_hex = value.hex().encode().zfill(64)
Examples
Pitfalls
b'ab'.zfill(4)
if data.lstrip(b'+-').isdigit(): data = data.zfill(4)
b'-42'.rjust(5, b'0')
b'-42'.zfill(5)
b'4-2'.zfill(5)
b'-42'.zfill(5)
When to use
- Fixed-width numeric fields in legacy binary or text formats
- Zero-padding hex where leading zeros are significant
- Data that is already bytes and already numeric
- Formatting a number you hold as an int → an f-string with :0Nd
- Arbitrary data — it will pad anything
- Padding with a byte other than zero → rjust
Notes
FAQ
Because zfill is designed for numbers, and -0042 is a valid zero-padded number while 00-42 is not. It checks the first byte for + or - and inserts the zeros after it.
b'-42'.zfill(5) # b'-0042'