How to print a hexadecimal number in Python
Discover how to print hexadecimal numbers in Python. This guide covers various methods, real-world applications, and debugging common errors.
.png)
Printing hexadecimal numbers in Python is essential for debugging memory addresses or representing data compactly. The built-in hex() function offers a simple way to handle these conversions with clear syntax.
In this article, you'll explore techniques beyond the basics. You'll find practical formatting tips, see real-world applications, and get advice for debugging common hexadecimal conversion issues.
Basic printing with hex() function
number = 255
hex_value = hex(number)
print(hex_value)--OUTPUT--0xff
The hex() function is Python's direct method for converting an integer into a lowercase hexadecimal string. It automatically prepends the 0x prefix to the output, which is a standard convention that clearly identifies the value as hexadecimal. This built-in behavior is useful for creating unambiguous output for debugging or data representation.
The resulting string, 0xff, consists of two parts:
0x: A prefix that signals the value is in hexadecimal format.ff: The hexadecimal equivalent of the decimal number 255.
Basic hexadecimal operations
While hex() is a great start, you'll often need more control, such as custom formatting, converting between number systems, and using hexadecimal literals directly.
Formatting hex output with string formatting
number = 255
formatted_hex = f"{number:x}" # Lowercase hex without 0x prefix
formatted_hex_upper = f"{number:X}" # Uppercase hex without 0x prefix
print(formatted_hex, formatted_hex_upper)--OUTPUT--ff FF
When you need more control than the hex() function offers, f-string formatting is a powerful alternative. It allows you to embed formatted values directly into strings without the automatic 0x prefix, which is ideal for custom data representations.
- The format specifier
:xconverts an integer to a lowercase hexadecimal string, likeff. - Using
:Xproduces an uppercase hexadecimal string, such asFF.
This technique gives you clean, prefix-free output that’s easy to integrate wherever you need it.
Converting between decimal and hexadecimal
decimal_num = 255
hex_string = hex(decimal_num)
back_to_decimal = int(hex_string, 16)
print(f"Decimal: {decimal_num}, Hex: {hex_string}, Back to decimal: {back_to_decimal}")--OUTPUT--Decimal: 255, Hex: 0xff, Back to decimal: 255
Converting a hexadecimal string back to a decimal integer is straightforward with the int() function. While you're likely used to calling int() on a string, it also accepts a second argument to specify the number's base.
- To convert from hex, you pass the hexadecimal string (like
'0xff') as the first argument and16as the second. The base16tells Python to interpret the string as a hexadecimal value, correctly reversing thehex()conversion and returning the original decimal number.
Working with hexadecimal literals
hex_literal = 0xFF
hex_literal_2 = 0xA3
sum_of_hex = hex_literal + hex_literal_2
print(f"0xFF = {hex_literal}, 0xA3 = {hex_literal_2}, Sum = {sum_of_hex} (0x{sum_of_hex:x})")--OUTPUT--0xFF = 255, 0xA3 = 163, Sum = 418 (0x1a2)
You can write numbers directly in hexadecimal format within your code by using the 0x prefix. These are known as hexadecimal literals. Python treats these literals as standard integers, not strings, so you can perform arithmetic on them just as you would with decimal numbers.
- For example, when you add
0xFFand0xA3, Python interprets them as their integer values to perform the calculation. - This makes it easy to work with hex values directly in your logic without needing manual conversions first.
Advanced hexadecimal techniques
With the fundamentals covered, you can now tackle more advanced techniques like custom padding, data type conversions, and bitwise operations for sophisticated hexadecimal manipulation.
Formatting with specific width and padding
number = 26
zero_padded = f"{number:04x}" # Width of 4, zero-padded
space_padded = f"{number:8x}" # Width of 8, space-padded
full_format = f"0x{number:04X}" # With 0x prefix and uppercase
print(zero_padded, space_padded, full_format)--OUTPUT--001a 1a 0x001A
F-string formatting gives you precise control over the width and padding of hexadecimal strings. It's useful for aligning output in tables or representing fixed-size data like memory addresses.
- The format specifier
:04xpads the number with leading zeros to a total width of four characters. - If you specify only the width, like in
:8x, Python defaults to padding with spaces. - You can also combine these options with a manual
0xprefix and an uppercaseXfor fully customized output like0x001A.
Converting other data types to hexadecimal
text = "Python"
text_as_hex = text.encode('utf-8').hex()
data = bytes([65, 66, 67, 68])
data_as_hex = data.hex()
print(f"'{text}' in hex: {text_as_hex}")
print(f"{data} in hex: {data_as_hex}")--OUTPUT--'Python' in hex: 507974686f6e
b'ABCD' in hex: 41424344
Hexadecimal conversion isn't just for integers. The .hex() method works directly on bytes objects, offering a straightforward way to represent binary data. To convert a string to its hex equivalent, you must first encode it into bytes.
- Calling
text.encode('utf-8')turns the string into a sequence of bytes, which then allows you to call the.hex()method. - If you already have a
bytesobject, such as one created from a list of integers, you can call.hex()on it directly.
Bitwise operations with hex() numbers
a = 0xA5 # 10100101 in binary
b = 0x3C # 00111100 in binary
print(f"AND: {hex(a & b)}")
print(f"OR: {hex(a | b)}")
print(f"XOR: {hex(a ^ b)}")
print(f"NOT: {hex(~a & 0xFF)}") # Mask with 0xFF for 8-bit result--OUTPUT--AND: 0x24
OR: 0xbd
XOR: 0x99
NOT: 0x5a
Bitwise operators like & (AND), | (OR), and ^ (XOR) work directly on hexadecimal literals since Python treats them as integers. This allows you to perform low-level data manipulation at the binary level, with hex() formatting the result back into a hex string.
- The
&operator keeps only the bits that are set in both numbers. - The
|operator combines the bits that are set in either number. - The
^operator keeps bits that are different between the two numbers.
The ~ (NOT) operator inverts all bits. A mask like & 0xFF is often used with it to constrain the result to a positive value that fits in one byte, which prevents Python from returning a negative number.
Move faster with Replit
Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This lets you move from learning individual techniques, like using the hex() function, to building complete applications faster.
Instead of piecing together code, you can describe the app you want to build and Agent 4 will take it from an idea to a working product. You can build practical tools that leverage hexadecimal conversions, such as:
- A color converter that translates RGB values into their padded hexadecimal equivalents for web design.
- A data utility that reads binary files and displays their contents in a formatted hexadecimal view for analysis.
- A permissions calculator that uses bitwise operations on hex values to configure system access rights.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
Even with Python's simple tools, you might run into issues with negative numbers, conversion errors, or byte order when working with hexadecimal values.
Handling negative numbers with hex()
When you pass a negative integer to the hex() function, it simply prepends a minus sign to the result, like hex(-10) returning '-0xa'. While technically correct, this isn't always what you need, especially in low-level programming where negative numbers are represented using two's complement.
To get the two's complement representation, you can use a bitwise AND operation with a mask. For example, to find the 8-bit representation of -10, you could use hex(-10 & 0xFF), which correctly yields '0xf6'. This technique is essential for accurately representing values as they would appear in fixed-size memory registers.
Troubleshooting invalid literal errors when converting hex strings
A common roadblock is the ValueError: invalid literal for int() with base 16. This error pops up when you try to convert a string to an integer using int(your_string, 16), but the string contains characters that aren't valid in hexadecimal notation—anything outside of 0-9 and a-f.
This often happens due to typos or extra characters in the input string. For instance, trying to convert '0xFG' will fail because 'G' is not a valid hex digit. Before converting, ensure your string is clean and contains only valid hexadecimal characters, optionally prefixed with 0x.
Fixing byte order confusion in hexadecimal representation
When working with binary data, byte order—or endianness—can cause major headaches. It dictates the sequence in which bytes are arranged in computer memory. Most modern processors use little-endian order, where the least significant byte comes first, while network protocols typically use big-endian, with the most significant byte first.
This difference means the number 0x12345678 might be stored as 78 56 34 12 in memory. If you read these bytes and interpret them on a system with a different endianness, you'll get the wrong value. Python's int.from_bytes() and int.to_bytes() methods help you manage this by letting you explicitly specify the byte order, ensuring your data is interpreted correctly across different systems.
Handling negative numbers with hex()
Handling negative numbers with hex()
Python's hex() function handles negative numbers by adding a minus sign to the output, which isn't always the desired format for systems programming. This approach differs from two's complement representation. See how it works in the following code example.
negative_num = -42
hex_value = hex(negative_num)
print(f"Hex of {negative_num} is {hex_value}")
The code returns '-0x2a', an output that isn't the two's complement value needed for low-level programming. To get the correct byte representation for a negative number, you'll need a different approach, as shown below.
negative_num = -42
# For unsigned representation (two's complement)
hex_value = hex(negative_num & 0xFFFFFFFF)
print(f"Hex of {negative_num} is {hex_value}")
To get the two's complement representation, you can use a bitwise & operation with a mask. The mask, such as 0xFFFFFFFF, limits the number to a specific bit length, like 32 bits. This forces Python to calculate the value as it would appear in a fixed-size memory register. You'll find this technique is crucial when working with low-level hardware interfaces or network protocols where negative numbers are represented this way.
Troubleshooting invalid literal errors when converting hex strings
Troubleshooting invalid literal errors when converting hex strings
A common ValueError occurs when you try converting a hex string to an integer but forget to specify the base. By default, the int() function assumes base 10, which will fail if the string contains any hexadecimal characters from a to f. The code below demonstrates this.
hex_string = "FF" # No 0x prefix
decimal_value = int(hex_string)
print(f"Decimal value: {decimal_value}")
The code fails because the int() function attempts to interpret 'FF' as a standard decimal number. Since 'F' is not a valid digit in base 10, Python raises a ValueError. See the corrected approach below.
hex_string = "FF" # No 0x prefix
decimal_value = int(hex_string, 16) # Specify base 16
print(f"Decimal value: {decimal_value}")
To fix the ValueError, you must tell the int() function that you're working with a hexadecimal number. By default, it assumes base 10. Passing 16 as the second argument—like int('FF', 16)—explicitly sets the base and ensures the conversion works correctly.
This error often occurs when your hex string lacks the 0x prefix, as Python won't automatically guess the base. Always specify the base when converting non-decimal strings to avoid this issue.
Fixing byte order confusion in hexadecimal representation
Fixing byte order confusion in hexadecimal representation
Byte order, or endianness, dictates how bytes are arranged in memory, which can cause a number's hexadecimal representation to appear reversed. Most systems use little-endian order, where the least significant byte comes first. The following code demonstrates this unexpected behavior.
value = 258 # 0x0102
byte_data = value.to_bytes(2, byteorder='little')
hex_string = byte_data.hex()
print(f"Hex representation: {hex_string}") # Prints "0201"
The to_bytes() method with byteorder='little' stores the least significant byte first, causing the hex representation of 258 to appear as 0201. See how to produce the correct byte sequence in the code below.
value = 258 # 0x0102
byte_data = value.to_bytes(2, byteorder='big')
hex_string = byte_data.hex()
print(f"Hex representation: {hex_string}") # Prints "0102"
To fix byte order issues, specify byteorder='big' in the to_bytes() method. This ensures the most significant byte comes first, matching the standard representation you'd expect—so 0x0102 is correctly represented as 0102. You'll need to pay close attention to this when working with network protocols or specific file formats, as they often require big-endian byte order to ensure data is interpreted correctly across different systems.
Real-world applications
Putting theory into practice, you can use hexadecimal formatting for common tasks like converting RGB colors or displaying network MAC addresses.
Converting RGB colors to hexadecimal with f-string formatting
A common task in web development is converting RGB color values to hex codes, which you can handle cleanly using f-string formatting to ensure each color component is padded to two digits.
red, green, blue = 255, 0, 0 # Red color
hex_color = f"#{red:02x}{green:02x}{blue:02x}"
print(f"RGB({red}, {green}, {blue}) = {hex_color}")
yellow = (255, 255, 0)
hex_yellow = f"#{yellow[0]:02x}{yellow[1]:02x}{yellow[2]:02x}"
print(f"RGB{yellow} = {hex_yellow}")
This code demonstrates how to build a standard web hex color string from RGB values. It uses an f-string to combine a leading # with the hexadecimal representation of each color component.
- The format specifier
:02xis the core of the operation. It tells Python to convert each number to a lowercase hexadecimal string (x) and pad it with a leading zero to ensure it's always two characters long (02). - This technique works for values stored in separate variables, like
red, or accessed by index from a tuple, likeyellow[0].
Formatting MAC addresses using the join() method
You can efficiently format a list of byte values into a standard MAC address by combining a generator expression with the join() method.
mac_bytes = [0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33]
formatted_mac = ':'.join(f'{b:02x}' for b in mac_bytes)
print(f"MAC address: {formatted_mac.upper()}")
mac2 = [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]
mac2_formatted = '-'.join(f'{b:02x}' for b in mac2)
print(f"Alternative format: {mac2_formatted}")
This code snippet formats a list of byte values into a standard MAC address string. It processes each hexadecimal number from the list one by one, converting it into a consistent string format.
- Each byte is formatted into a two-digit hexadecimal string. The
f'{b:02x}'expression ensures a leading zero is added if a number is less than 16. - These formatted strings are then stitched together, using a colon or a hyphen as the separator between each part.
- Finally, the
.upper()method can be used to present the final MAC address in a conventional uppercase style.
Get started with Replit
Put your knowledge to work and build a real tool. Just tell Replit Agent 4 to “build a web app that converts RGB to hex” or “create a utility that formats MAC addresses from byte input.”
Replit Agent writes the code, tests for errors, and helps you deploy your application directly from your browser. Start building with Replit.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.



