$title =

How to encode and decode hex

;

$콘텐츠 = [

Hex encoding and decoding are foundational skills in software engineering, security, debugging, and data processing. If you’ve ever looked at a hash, a network packet, a color code like #FF5733, or raw bytes in a debugger, you’ve already seen hexadecimal (hex) in action.

This guide explains what hex is, how hex encoding and decoding works, when to use it, and common mistakes to avoid—with practical examples and code snippets.


What is hex?

Hexadecimal (base-16) is a number system that uses 16 symbols:

  • 0-9 for values 0–9
  • A-F (or a-f) for values 10–15

So one hex digit can represent 16 values:

Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F

Why hex is so common for bytes

Computers store data in bytes (8 bits).
Hex maps very neatly onto binary:

  • 1 hex digit = 4 bits
  • 2 hex digits = 1 byte (8 bits)

Example:

Binary byte: 11001010
Split: 1100 1010
Hex: C A → 0xCA

This is why hex is a compact, human-readable way to represent raw binary data.


What does “hex encoding” actually mean?

In practice, hex encoding usually means:

Converting binary data (bytes) into a string of hexadecimal characters.

And hex decoding means:

Converting a hexadecimal string back into the original bytes.

Important clarification

Hex encoding is not:

  • Encryption (it does not hide data securely)
  • Compression (it usually makes data larger)
  • Hashing (hashes are often displayed in hex, but hex is just the representation)

For example:

  • Raw bytes: b"Hello"
  • Hex-encoded string: 48656c6c6f

That hex string is just a textual representation of the original bytes.


How hex encoding works (step by step)

Let’s encode the ASCII text "Hi".

Step 1) Convert characters to bytes

In ASCII/UTF-8:

  • H = decimal 72 = hex 48
  • i = decimal 105 = hex 69

So the bytes are:

[0x48, 0x69]

Step 2) Convert each byte to two hex digits

  • 0x48"48"
  • 0x69"69"

Step 3) Concatenate

"Hi" → "4869"

That’s hex encoding.


How hex decoding works (step by step)

Now decode "4869" back to bytes and text.

Step 1) Split into pairs of hex digits

"48" "69"

Each pair represents one byte.

Step 2) Convert each pair to a byte

  • "48"0x48
  • "69"0x69

Step 3) Interpret bytes (if needed) as text

Bytes [0x48, 0x69] interpreted as UTF-8/ASCII text = "Hi".


Hex encoding vs text encoding (UTF-8, ASCII) — a common confusion

This is one of the most common misunderstandings.

  • UTF-8 / ASCII / UTF-16 define how characters become bytes.
  • Hex defines how bytes are represented as readable text.

So if you hex-encode a string, there are two layers:

  1. Convert the string to bytes (using UTF-8, etc.)
  2. Represent those bytes in hex

Example with non-ASCII text

String: "あ" (Japanese)

  • In UTF-8, "あ" becomes a sequence of bytes (multiple bytes)
  • Hex encoding then displays those bytes as hex characters

This is why you must always know the character encoding (usually UTF-8) when converting between text ↔ bytes ↔ hex.


Why use hex encoding?

Hex is useful because it is:

  • Human-readable (more than raw binary)
  • Compact enough (compared to binary)
  • Deterministic (same bytes always become the same hex string)
  • Widely supported in tools/libraries

Common use cases

  • Displaying binary data in logs/debuggers
  • Cryptographic outputs (hashes, keys, signatures)
  • Network protocols / packet inspection
  • File formats and memory dumps
  • IDs and tokens (sometimes)
  • Color values in web/CSS (e.g., #RRGGBB)

Size overhead of hex encoding

Hex is convenient, but it increases size.

  • Each byte (8 bits) becomes 2 hex characters
  • So hex-encoded output is typically 2× the original byte length

Example:

  • 16 bytes of binary data → 32-character hex string

This is one reason Base64 is often preferred when size matters (Base64 has lower overhead), but hex remains easier to read and debug.


Uppercase vs lowercase hex

Both are valid:

  • deadbeef
  • DEADBEEF

Hex decoding libraries usually accept either.

Best practice

Be consistent in your project:

  • Choose lowercase for logs and APIs (common)
  • Choose uppercase if required by a spec or style guide

Prefixes and formatting styles

Hex values may appear with prefixes depending on context:

  • 0x2A (common in programming languages)
  • 2A (raw hex string)
  • \x2A (byte escape notation)
  • #FF5733 (CSS color notation)

When decoding, make sure you know whether your input includes prefixes or separators.

Examples you may need to normalize:

  • 0x48 0x69
  • 48:69
  • 48-69
  • 4869

Practical examples

1) Encode/decode hex in Python

# Text -> bytes -> hex
text = "Hello, hex!"
hex_str = text.encode("utf-8").hex()
print(hex_str) # 48656c6c6f2c2068657821
# Hex -> bytes -> text
decoded_text = bytes.fromhex(hex_str).decode("utf-8")
print(decoded_text) # Hello, hex!

Decode raw binary data (not text)

If the bytes are not UTF-8 text, decode to bytes only:

data = bytes.fromhex("00ff10a5")
print(data) # b'\x00\xff\x10\xa5'

2) Encode/decode hex in JavaScript (Node.js)

// Text -> hex
const text = "Hello, hex!";
const hex = Buffer.from(text, "utf8").toString("hex");
console.log(hex); // 48656c6c6f2c2068657821
// Hex -> text
const decoded = Buffer.from(hex, "hex").toString("utf8");
console.log(decoded); // Hello, hex!

Browser note

In browsers, use TextEncoder / TextDecoder and manual conversion if needed.


3) Encode/decode hex in shell (Linux/macOS)

Encode text to hex

echo -n "Hello" | xxd -p

Decode hex to text

echo "48656c6c6f" | xxd -r -p

4) Hex and cryptographic hashes

When you compute a SHA-256 hash, the output is binary bytes. Most tools display it in hex.

Example (conceptually):

  • Raw hash bytes: 32 bytes
  • Hex representation: 64 hex characters

This is why SHA-256 hashes are typically shown as a 64-character hex string.


Hex decoding errors and edge cases

Hex decoding is simple, but a few issues come up frequently.

1) Odd-length hex strings

Each byte requires 2 hex characters.
So a valid hex string usually has an even length.

Invalid example:

"ABC" # 3 chars (odd length)

Some parsers reject this outright. Others may allow padding, but you should not rely on that unless specified.


2) Invalid characters

Hex strings may only contain:

  • 0-9
  • a-f
  • A-F

Invalid examples:

  • 12G4 (G is not hex)
  • ZZ
  • hello (letters like h, l, o are invalid in hex context)

3) Confusing bytes with text

This is the biggest practical issue.

Hex decoding gives you bytes, not necessarily text.

If you try to decode arbitrary binary bytes as UTF-8 text, you may get errors or corrupted output.

bytes.fromhex("fffe") # valid bytes
# but .decode("utf-8") may fail

Always ask:

  • “Am I decoding to bytes?”
  • “If I need text, what encoding should I use (UTF-8, UTF-16, etc.)?”

4) Whitespace/separators in input

Some tools output hex with spaces or line breaks:

48 65 6c 6c 6f

Some libraries accept this directly; others don’t. Normalize the input if necessary by stripping whitespace/separators before decoding.


5) Endianness confusion

Hex itself is just a representation.
Endianness matters when interpreting multi-byte values (like integers), not when hex-encoding bytes.

Example bytes:

01 02 03 04

As bytes, that sequence is unambiguous.

But as a 32-bit integer:

  • Big-endian: 0x01020304
  • Little-endian: 0x04030201

If you’re parsing binary protocols or file formats, be careful not to blame hex for an endianness issue.


Hex encoding algorithm (conceptual)

If you want to understand it at a lower level, here’s the basic idea.

For each byte (0-255):

  1. High nibble = byte >> 4
  2. Low nibble = byte & 0x0F
  3. Map each nibble to a hex character (0-9, A-F)
  4. Output two characters

Example for byte 0xAF (decimal 175)

  • High nibble: 0xAA
  • Low nibble: 0xFF
  • Result: "AF"

Hex decoding reverses this:

  • Convert each hex char to a nibble
  • Combine two nibbles into one byte:
    byte = (high << 4) | low

Security considerations (important)

Hex encoding does not provide security.

If sensitive data is hex-encoded, it is still easily recoverable by anyone who can decode hex.

What hex does well

  • Makes binary data printable/transmittable in text-only environments

What it does not do

  • Protect confidentiality
  • Verify integrity
  • Prevent tampering

Use proper cryptographic tools for security:

  • Encryption (e.g., AES)
  • Hashing (e.g., SHA-256)
  • MAC/signatures for authenticity

Hex may be used to display the outputs of these tools, but it is not a security mechanism itself.


When to use hex vs Base64

Both encode bytes into text, but they serve slightly different priorities.

Use hex when:

  • Readability/debugging matters
  • You want simple per-byte visibility
  • You’re working with low-level systems/protocols

Use Base64 when:

  • Size matters more than readability
  • You need a compact text representation
  • You’re sending binary in JSON, HTTP, etc.

A quick rule of thumb:

  • Hex = easier for humans
  • Base64 = more efficient for transport

Best practices for working with hex

  • Treat hex as a representation of bytes, not as text itself
  • Be explicit about character encoding (usually UTF-8) when converting text
  • Validate input before decoding (even length, valid characters)
  • Normalize formatting (remove spaces/prefixes if your parser requires it)
  • Don’t use hex as “security”
  • Document whether your APIs expect raw bytes, hex strings, or Base64

Quick reference

Text to hex

  1. Encode text to bytes (e.g., UTF-8)
  2. Convert each byte to 2 hex digits
  3. Concatenate

Hex to text

  1. Validate hex string
  2. Convert every 2 hex digits to a byte
  3. Decode bytes using the correct text encoding (e.g., UTF-8)

Final thoughts

Hex encoding/decoding is simple once you internalize one key idea:

Hex is just a human-friendly representation of bytes.

That single concept helps avoid most bugs and misunderstandings—especially around text encoding, cryptography, and binary data handling.

If you’re writing tools, APIs, or debugging systems-level code, solid hex literacy will save you a lot of time.

];

$date =

;

$category =

;

$author =

;

$previous =

;