DEV Community

Cover image for Converting Python Bytes to Hex
Mateen Kiani
Mateen Kiani

Posted on • Originally published at milddev.com

Converting Python Bytes to Hex

Introduction

Working with binary data is a daily task for many Python developers, especially when dealing with network protocols or file formats. Yet one small step that often slips under the radar is how we convert raw bytes into a readable hex string. Why does this simple conversion matter when you can just print raw bytes?

Fortunately, Python offers built-in ways to turn bytes into hex quickly and reliably. By mastering methods like bytes.hex() or the binascii module, you can debug data flows, optimize memory use, and avoid unexpected errors.

Understanding Bytes and Hex

Before diving into code, it helps to understand what bytes and hex strings represent. A byte in Python is an immutable sequence of integers between 0 and 255. Internally, each byte holds 8 bits of data. You can create a bytes object using a constructor like:

data = bytes([104, 101, 108, 108, 111])  # b'hello'
Enter fullscreen mode Exit fullscreen mode

Hexadecimal is a base-16 numbering system. It uses digits 0 to 9 and letters a to f to represent values. One hex digit represents 4 bits, so two hex digits map exactly to one byte. For example, the byte value 255 becomes ff in hex, while 16 becomes 10.

Representing bytes as hex strings offers clear advantages. It makes logs more readable, eases debugging when you inspect raw data, and helps when sending binary over text-based channels like JSON or HTTP. Once you see raw bytes as hex pairs, it is easier to spot patterns and errors.

Built-in Python Methods

Python provides simple built-in tools for converting bytes to hex.

data = bytes([0, 255, 16])
hex_str = data.hex()
print(hex_str)  # 00ff10
Enter fullscreen mode Exit fullscreen mode

The bytes.hex() method works in Python 3.5 and later. It returns a lowercase string with two hex digits per byte. For uppercase output, you can chain a call:

hex_str_upper = data.hex().upper()
print(hex_str_upper)  # 00FF10
Enter fullscreen mode Exit fullscreen mode

For older versions or more control, use the binascii module:

import binascii

raw = bytes([0x1a, 0x2b, 0x3c])
hexl = binascii.hexlify(raw)
print(hexl)          # b'1a2b3c'
print(hexl.decode()) # 1a2b3c
Enter fullscreen mode Exit fullscreen mode

Tip: use bytes.hex() for simple cases. Reach for binascii.hexlify when you need a bytes result or work in older environments.

Both approaches are reliable. Choose based on your version, output format, and performance needs.

Converting Hex to Bytes

Often you need to reverse the process. To turn a hex string back into bytes, Python offers a straightforward method:

hex_str = 'deadbeef'
raw = bytes.fromhex(hex_str)
print(list(raw))  # [222, 173, 190, 239]
Enter fullscreen mode Exit fullscreen mode

The bytes.fromhex class method expects a string with an even number of hex digits. If you include spaces between pairs, it still works:

raw2 = bytes.fromhex('de ad be ef')
print(list(raw2))  # [222, 173, 190, 239]
Enter fullscreen mode Exit fullscreen mode

Be cautious when reading hex from user input or files. Always validate the length and content:

if len(hex_str) % 2 != 0:
    raise ValueError('Hex string length must be even')
Enter fullscreen mode Exit fullscreen mode

Converting back and forth ensures data integrity when you encode, transmit, then decode binary content.

Performance Considerations

When handling large volumes of bytes, conversion speed can matter. Benchmark with the timeit module:

import timeit
import binascii

setup = 'data = bytes([120] * 1024)'
stmt1 = 'data.hex()'
stmt2 = 'binascii.hexlify(data)'

print(timeit.timeit(stmt1, setup=setup, number=10000))
print(timeit.timeit(stmt2, setup=setup, number=10000))
Enter fullscreen mode Exit fullscreen mode

Results vary by Python version and system, but bytes.hex() is typically optimized in C. Meanwhile, binascii.hexlify may be faster if you avoid an extra decode call.

  • Reuse data buffers where possible
  • Avoid calling hex conversion in tight loops
  • Profile with real-world data sizes

Performance tip: if you only need a bytes result from hexlify, skip the decode step to save cycles.

Understanding performance helps you choose the right method when processing logs, cryptographic hashes, or binary protocols.

Common Use Cases

Converting bytes to hex appears in many areas of development:

  • Debugging network traffic: hex dumps reveal packet contents.
  • Hashing and checksums: digest methods like SHA256 return bytes that you often display as hex.
  • Data serialization: encoding binary in text formats (JSON, XML).
  • File I/O: inspecting binary files before writing or after reading.
  • Encoding-aware conversions: bridge to string operations like binary to string conversion.

In some workflows you may also convert hex back to ints:

value = int.from_bytes(raw, 'big')
Enter fullscreen mode Exit fullscreen mode

For more on that, see the guide on bytes to int conversion.

Tips and Best Practices

To make your hex conversions robust:

  • Validate inputs: check string length and character set.
  • Control case: decide on upper or lower hex and stick with it.
  • Add separators: use a join expression for spaced formats.
  • Reuse buffers: avoid creating new objects in heavy loops.

Always log both raw and hex output in tandem when diagnosing tricky encoding issues.

By following consistent patterns, teammates can read your logs without confusion. Automated tools can then parse predictable hex formats reliably.

Conclusion

Converting bytes to hex in Python is a small but powerful skill. You can use bytes.hex(), binascii.hexlify, and bytes.fromhex to inspect, log, and process data in a readable form. Understanding performance differences and common pitfalls ensures you make the right choice for your project.

Whether you are debugging network packets, generating cryptographic digests, or building data pipelines, knowing how to round-trip between bytes and hex gives you clarity and control. Try these techniques in your next script and see how much smoother your binary data tasks become.

Top comments (0)