Skip to content

How to Convert Bytes to Int in Python

Learn how to accurately convert bytes to integers in Python using int.from_bytes(), struct.unpack(), and NumPy, with clear guidance on byte order (endianness) and signedness.

Converting bytes to integers in Python is a fundamental task that comes up frequently when working with binary files, network protocols, low-level system data, or hardware interfaces. Since bytes represent raw binary data, Python needs additional context, such as byte order (endianness) and signedness, to interpret them correctly as numerical values.

In this guide, you will learn the most reliable and commonly used ways to convert bytes into integers in Python, complete with clear explanations, practical examples with outputs, and common pitfalls to avoid.

What Does Converting Bytes to Int Mean?

A bytes object in Python represents a sequence of raw binary data. Converting it to an integer means interpreting that binary sequence as a numeric value. However, the same bytes can produce different integer values depending on how you interpret them.

data = b'\x00\x01'

print(int.from_bytes(data, "big"))

print(int.from_bytes(data, "little"))

Output:

1
256

As you can see, the byte order directly affects the resulting integer. This is why understanding endianness and signedness is essential before performing any conversion.

The built-in int.from_bytes() method is the most Pythonic, readable, and flexible way to convert bytes to integers. It is available in Python 3.2 and later and requires no additional imports.

Syntax

int.from_bytes(bytes, byteorder, *, signed=False)

Parameters

Parameter Description
bytes A bytes or bytearray object to convert
byteorder "big" (MSB first) or "little" (LSB first)
signed False (default) for unsigned integers, True for signed integers using two's complement

Examples

byte_val_1 = b'\x00\x01'
res_1 = int.from_bytes(byte_val_1, "big")
print(f"Big-endian b'\\x00\\x01': {res_1}")

byte_val_2 = b'\x00\x10'
res_2 = int.from_bytes(byte_val_2, "little")
print(f"Little-endian b'\\x00\\x10': {res_2}")

byte_val_3 = b'\xfc\x00'
res_3 = int.from_bytes(byte_val_3, "big", signed=True)
print(f"Signed big-endian b'\\xfc\\x00': {res_3}")

byte_val_4 = b'\xff'
res_4 = int.from_bytes(byte_val_4, "big")
print(f"Single byte b'\\xff' unsigned: {res_4}")

res_5 = int.from_bytes(byte_val_4, "big", signed=True)
print(f"Single byte b'\\xff' signed: {res_5}")

Output:

Big-endian b'\x00\x01': 1
Little-endian b'\x00\x10': 4096
Signed big-endian b'\xfc\x00': -1024
Single byte b'\xff' unsigned: 255
Single byte b'\xff' signed: -1

How the Math Works

Understanding the underlying arithmetic helps verify your conversions:

  • Big-endian b'\x00\x01': 0x00 * 256 + 0x01 = 1
  • Little-endian b'\x00\x10': 0x00 + 0x10 * 256 = 4096
  • Signed b'\xfc\x00': The raw unsigned value is 64512, but two's complement interpretation over 2 bytes yields -1024

Method 2: Using struct.unpack()

The struct module is specifically designed for interpreting bytes as packed binary data. It is the preferred approach when working with binary file formats, network protocols, or any context where data follows a well-defined structure with fixed-size fields.

Syntax

import struct

struct.unpack(format, buffer)

The function returns a tuple, even when unpacking a single value, so you typically access element [0].

Examples

import struct

byte_data_1 = b'\x01\x02'
res_1 = struct.unpack('>H', byte_data_1)[0]
print(f"Big-endian unsigned short: {res_1}")

byte_data_2 = b'\x01\x00\x00\x00'
res_2 = struct.unpack('<I', byte_data_2)[0]
print(f"Little-endian unsigned int: {res_2}")

byte_data_3 = b'\xff\xff\xff\xfc'
res_3 = struct.unpack('>i', byte_data_3)[0]
print(f"Big-endian signed int: {res_3}")

byte_data_4 = b'\x00\x01\x00\x02'
res_4 = struct.unpack('>HH', byte_data_4)
print(f"Two unsigned shorts: {res_4}")

Output:

Big-endian unsigned short: 258
Little-endian unsigned int: 1
Big-endian signed int: -4
Two unsigned shorts: (1, 2)

Format String Reference

Character Meaning Size (bytes)
> Big-endian byte order -
< Little-endian byte order -
! Network byte order (big-endian) -
B Unsigned char 1
b Signed char 1
H Unsigned short 2
h Signed short 2
I Unsigned int 4
i Signed int 4
Q Unsigned long long 8
q Signed long long 8

When to Choose struct.unpack() Over int.from_bytes()

  • You need to unpack multiple values from a single byte sequence in one call
  • You are parsing structured binary formats (file headers, packet layouts)
  • You want the format to serve as self-documenting code for the binary layout

Method 3: Using numpy.frombuffer()

When working with large binary datasets or performance-critical applications, NumPy provides a fast and memory-efficient way to convert bytes to integers. This method truly shines when you need to interpret a byte buffer as an array of integers rather than a single value.

Syntax

import numpy as np

numpy.frombuffer(buffer, dtype)

Examples

import numpy as np

byte_data_1 = b'\x01\x02'
res_1 = np.frombuffer(byte_data_1, dtype='>u2')[0]
print(f"Big-endian unsigned short: {res_1}")

byte_data_2 = b'\x01\x00\x00\x00'
res_2 = np.frombuffer(byte_data_2, dtype='>i4')[0]
print(f"Big-endian signed int: {res_2}")

byte_data_3 = b'\x01\x00\x00\x00'
res_3 = np.frombuffer(byte_data_3, dtype='<u4')[0]
print(f"Little-endian unsigned int: {res_3}")

byte_data_4 = b'\x01\x00\x02\x00\x03\x00\x04\x00'
res_4 = np.frombuffer(byte_data_4, dtype='<u2')
print(f"Array of little-endian unsigned shorts: {res_4}")

Output:

Big-endian unsigned short: 258
Big-endian signed int: 16777216
Little-endian unsigned int: 1
Array of little-endian unsigned shorts: [1 2 3 4]

NumPy dtype Notation

Prefix Meaning
> Big-endian
< Little-endian
u Unsigned integer
i Signed integer
Number Size in bytes (1, 2, 4, or 8)

For example, <u4 means "little-endian unsigned 4-byte integer."

When to Use NumPy

  • Processing large binary streams with many values
  • Working with scientific or sensor data stored in binary format
  • Situations where vectorized operations on the resulting integers are needed
  • Performance-critical applications where converting thousands or millions of values one by one would be too slow

Common Mistake: Using the Wrong Byte Order

One of the most frequent bugs when converting bytes to integers is assuming the wrong endianness. The same bytes produce completely different values depending on byte order.

Incorrect assumption (expected 1, used big-endian):

result = int.from_bytes(b'\x01\x00', "big")
print(result)

Output:

256

Correct approach (data is actually little-endian):

result = int.from_bytes(b'\x01\x00', "little")
print(result)

Output:

1

Common Mistake: Forgetting to Handle Signed Integers

When bytes represent a signed value (such as a negative temperature reading or a signed offset), omitting the signed=True parameter produces an incorrect positive number.

Incorrect (treats b'\xff\xff' as unsigned):

result = int.from_bytes(b'\xff\xff', "big")
print(result)

Output:

65535

Correct (interprets as signed using two's complement):

result = int.from_bytes(b'\xff\xff', "big", signed=True)
print(result)

Output:

-1

Quick Comparison of All Three Methods

Feature int.from_bytes() struct.unpack() numpy.frombuffer()
Built-in Yes Yes No (requires NumPy)
Handles arbitrary byte lengths Yes No (fixed sizes only) No (fixed sizes only)
Unpack multiple values at once No Yes Yes
Best for bulk data No No Yes
Readability High Medium Medium
Recommended for general use Yes Structured formats Large datasets

Best Practices

  • Prefer int.from_bytes() for most single-value conversions due to its clarity and simplicity.
  • Use struct.unpack() when dealing with structured binary formats or when you need to unpack multiple fields from a single buffer.
  • Use NumPy for large-scale binary data processing where performance matters.
  • Always verify byte order and signedness against the specification of your data source before performing any conversion.
  • Document binary formats clearly in your codebase so other developers understand the expected byte layout.
  • Validate input length before conversion to avoid unexpected errors from truncated or malformed data.

Conclusion

Python provides multiple powerful tools to convert bytes into integers. For most everyday applications, int.from_bytes() is the best choice, offering excellent readability and full control over byte order and signedness. For parsing structured binary data with multiple fields, struct.unpack() is the natural fit. When performance is critical and you are processing large volumes of binary data, NumPy delivers the speed and efficiency you need.

Understanding how bytes map to integers, and being mindful of endianness and signedness, ensures correctness, portability, and reliability whenever you work with low-level binary data in Python.

Navigation