Of course! Converting a Python int to bytes is a common task, especially in low-level programming, cryptography, and networking. The key is to understand that an integer is just a number, and to convert it to bytes, you need to specify two things:

- Endianness: The order of the bytes (most significant byte first or least significant byte first).
- Length: The number of bytes to use. This determines the range of numbers you can represent.
Let's break down the methods, from the simplest to the most manual.
The Short Answer: Use int.to_bytes()
For most cases, the built-in int.to_bytes() method is the best and most Pythonic way.
# A positive integer
my_int = 123456
# Convert to 4 bytes, in big-endian order
bytes_big_endian = my_int.to_bytes(4, 'big')
print(f"Big-endian: {bytes_big_endian}")
# Output: Big-endian: b'\x01\xe2@'
# Convert to 4 bytes, in little-endian order
bytes_little_endian = my_int.to_bytes(4, 'little')
print(f"Little-endian: {bytes_little_endian}")
# Output: Little-endian: b'@\xe2\x01\x00'
Detailed Explanation of int.to_bytes()
The method signature is:
int.to_bytes(length, byteorder, *, signed=False)
length
This is the number of bytes the resulting byte string should have. It's a required argument.

- If the number is too large to fit in the specified number of bytes, Python will raise an
OverflowError. - If the number is smaller than the maximum value for the given length, it will be padded with zeros at the beginning (for big-endian) or end (for little-endian).
# Number is small enough to fit in 4 bytes
small_int = 255
print(small_int.to_bytes(4, 'big')) # Padded with 3 leading zeros
# Output: b'\x00\x00\x00\xff'
# Number is too large for 2 bytes
large_int = 70000
try:
large_int.to_bytes(2, 'big')
except OverflowError as e:
print(e)
# Output: int too big to convert
byteorder
This specifies the order of the bytes. It's also a required argument.
'big': Most significant byte (MSB) is at the beginning of the byte string. This is the network standard order.'little': Least significant byte (LSB) is at the beginning of the byte string. This is common for x86 processors.'native': Uses the native byte order of the system ('big'on big-endian systems,'little'on little-endian systems).'>': Synonym for'big'.'<': Synonym for'little'.
signed (Optional)
This is a keyword-only argument ( in the signature). It's a boolean that indicates whether the integer should be treated as a signed value.
signed=False(default): The integer is treated as unsigned. This is the most common case.signed=True: The integer is treated as signed (can be negative).
Important: When signed=True, you must provide a length that is sufficient to represent the negative number (typically using two's complement). Python will raise an OverflowError if the length is too small.
# Signed integer example
negative_int = -12345
# To represent -12345, we need at least 3 bytes
# Let's see what 3 bytes can hold for signed integers:
# 3 bytes = 24 bits. The range is -2^23 to 2^23 - 1, which is -8,388,608 to 8,388,607.
# -12345 is within this range.
bytes_signed = negative_int.to_bytes(3, 'big', signed=True)
print(f"Signed: {bytes_signed}")
# Output: Signed: b'\xf6\xd7\xf7'
# This is the same number, but represented in 4 bytes
bytes_signed_4 = negative_int.to_bytes(4, 'big', signed=True)
print(f"Signed (4 bytes): {bytes_signed_4}")
# Output: Signed (4 bytes): b'\xff\xf6\xd7\xf7'
Alternative Method: int.bit_length() and Bitwise Operations
If you want to understand what's happening under the hood or need more control, you can manually construct the bytes. This involves using bitwise operators (>>, &) and the bytes() constructor.

The logic is:
- Determine the required number of bytes.
- Loop, shifting the integer right by 8 bits in each iteration.
- In each iteration, take the lowest 8 bits using a bitwise AND with
0xff. - Append these 8 bits to a list.
- Reverse the list if you want big-endian order.
def int_to_bytes_manual(n: int, byteorder: str = 'big') -> bytes:
"""Converts an integer to bytes manually."""
if n == 0:
return b'\x00'
# Handle negative numbers by getting their two's complement representation
if n < 0:
n = (1 << (n.bit_length() + 1)) + n
byte_list = []
while n:
byte_list.append(n & 0xff) # Get the last 8 bits
n >>= 8 # Shift right by 8 bits
# Pad to a multiple of 8 bits if necessary (though the loop handles it)
# This is more for conceptual clarity
if len(byte_list) == 0:
return b'\x00'
# Reverse for big-endian, keep as is for little-endian
if byteorder == 'big':
byte_list.reverse()
return bytes(byte_list)
# Example usage
my_int = 0x12345678 # 305419896 in decimal
bytes_be = int_to_bytes_manual(my_int, 'big')
print(f"Manual Big-endian: {bytes_be.hex()}")
# Output: Manual Big-endian: 12345678
bytes_le = int_to_bytes_manual(my_int, 'little')
print(f"Manual Little-endian: {bytes_le.hex()}")
# Output: Manual Little-endian: 78563412
The Reverse: Converting Bytes to an int
The reverse operation is just as straightforward using int.from_bytes().
my_bytes = b'\x12\x34\x56\x78'
# Convert from big-endian bytes to an integer
int_from_be = int.from_bytes(my_bytes, 'big')
print(f"Integer from big-endian: {int_from_be}")
# Output: Integer from big-endian: 305419896
# Convert from little-endian bytes to an integer
int_from_le = int.from_bytes(my_bytes, 'little')
print(f"Integer from little-endian: {int_from_le}")
# Output: Integer from little-endian: 2025915346
Summary: Which Method to Use?
| Method | When to Use | Pros | Cons |
|---|---|---|---|
int.to_bytes() |
Almost always. This is the standard, recommended way. | - Simple, readable, and Pythonic. - Handles endianness, signedness, and padding automatically. - Less error-prone. |
- None for standard use cases. |
| Manual Bitwise | - Learning how it works. - Extremely specific, non-standard requirements. |
- Full control over the conversion process. - No hidden "magic". |
- Verbose and complex. - Easy to make mistakes (e.g., off-by-one errors, handling negatives). |
