int.to_bytes()

The serialization half of the pair with from_bytes. You choose the width and the byte order; Python refuses rather than truncate if the value will not fit.

Int methodPython 3.2+Live demo
Common call
n.to_bytes(4, 'big')
Returns
bytes of exactly that length, zero-padded on the high side
Replaces
struct.pack for simple fixed-width integers
Watch out
a value too large raises OverflowError — it never silently truncates
int.to_bytes(lengthlength — How many bytes to produce. Since 3.11 it defaults to 1. Too small for the value raises OverflowError.type: int · default: 1, byteorderbyteorder — 'big' puts the most significant byte first; 'little' puts it last. Since 3.11 it defaults to 'big'. Anything else raises ValueError.type: str · default: 'big', *, signedsigned — Keyword-only. False rejects negative values; True encodes them in two-complement form.type: bool · default: False=False)
→ bytes

Demo

Live evaluation
Try:
Inputs
nintinteger to pack
lengthinthow many bytes
byteorderstr'big' or 'little'
Output
(255).to_bytes(2, 'big')
b'\x00\xff'

to_bytes writes the value into exactly `length` bytes, padding the high side with zeros. Byte order decides which end the most significant byte goes: 255 in two bytes is b"\x00\xff" big-endian and b"\xff\x00" little-endian. Two things raise instead of guessing — a value wider than the requested length (OverflowError: int too big to convert) and a negative value without signed=True (OverflowError: can't convert negative int to unsigned).

Parameters

NameTypeRequiredDescription
lengthintno (1)How many bytes to produce. Since 3.11 it defaults to 1. Too small for the value raises OverflowError.
byteorderstrno ('big')'big' puts the most significant byte first; 'little' puts it last. Since 3.11 it defaults to 'big'. Anything else raises ValueError.
signedboolno (False)Keyword-only. False rejects negative values; True encodes them in two-complement form.

Return value

bytes — A bytes object of exactly `length` bytes. Raises OverflowError if the value does not fit.

Common patterns

Network byte order
Big-endian is network order — the default choice for wire protocols.
header = length.to_bytes(4, 'big')
Size the width from the value
bit_length tells you the minimum width; floor at one byte for zero.
width = max(1, n.bit_length() + 7 >> 3)
blob = n.to_bytes(width, 'big')
Signed values
Negative numbers need signed=True, and one bit of the width goes to the sign.
(-1).to_bytes(2, 'big', signed=True)   # b'\xff\xff'

Examples

1. Big-endian
(255).to_bytes(2, 'big')
Returns
b'\x00\xff'
2. Little-endian
(255).to_bytes(2, 'little')
Returns
b'\xff\x00'
3. Zero-padded
(1).to_bytes(4, 'big')
Returns
b'\x00\x00\x00\x01'
4. Exactly fills
(65535).to_bytes(2, 'big')
Returns
b'\xff\xff'
5. Too big raises
(256).to_bytes(1, 'big')
Returns
OverflowError: int too big to convert
6. Signed negative
(-1).to_bytes(2, 'big', signed=True)
Returns
b'\xff\xff'

Pitfalls

1. Negative without signed=True raises
The default is unsigned, so any negative value is rejected outright. The error mentions "unsigned", which is the hint that signed=True is what you wanted.
Rejected
(-1).to_bytes(2, 'big')
OverflowError: can't convert negative int to unsigned
Opt into signed
(-1).to_bytes(2, 'big', signed=True)
b'\xff\xff'
2. It raises rather than truncating
Unlike C casts and many struct helpers, an oversized value is an error, not a wrap-around. This is a feature — silent truncation is how corrupt protocol frames happen — but it means you must size the width correctly.
Will not fit
(256).to_bytes(1, 'big')
OverflowError: int too big to convert
Size it first
n.to_bytes(max(1, (n.bit_length() + 7) // 8), 'big')
always wide enough
3. signed=True costs you a bit of range
In two-complement the top bit is the sign, so a signed byte holds -128..127 rather than 0..255. A value that fit unsigned may overflow once you turn signed on.
Fit, then did not
(200).to_bytes(1, 'big', signed=True)
OverflowError: int too big to convert
Widen or go unsigned
(200).to_bytes(1, 'big')
b'\xc8'
4. The defaults only exist on 3.11+
Since 3.11 length defaults to 1 and byteorder to "big". On 3.10 and earlier both are required positionally, so n.to_bytes() is a TypeError there.
TypeError pre-3.11
(255).to_bytes()
TypeError: to_bytes() missing required argument
Always be explicit
(255).to_bytes(1, 'big')
b'\xff' # works everywhere

When to use

Use it
  • Writing fixed-width integers into a binary protocol or file format
  • Producing network byte order without pulling in struct
  • Hashing or checksumming an integer as raw bytes
  • Round-tripping with int.from_bytes
Reach for something else
  • Packing several fields at once → struct.pack is clearer
  • Text output → format, hex or bin
  • Arbitrary objects → pickle or a real serializer

Notes

Complexity
O(length) — one pass writing the bytes
Return
A new immutable bytes object of exactly `length` bytes
CPython impl
Objects/longobject.c :: int_to_bytes_impl
Memory
Allocates exactly `length` bytes
Thread-safe
Yes — ints and bytes are immutable

FAQ

Big-endian for anything crossing a wire or a file format, because it is network byte order and most specifications assume it. Little-endian when matching x86 memory layout or a format that specifies it. If you control both ends, pick one and write it down.

n.to_bytes(4, 'big')     # network order

History

3.2
int.to_bytes added alongside int.from_bytes.
3.11
length defaults to 1 and byteorder defaults to "big".