ASCII to Hex: Convert Text to Hexadecimal (Full Guide)

Try the Hex Converter

Converting hex back to readable text gets all the attention, but the reverse trip — turning plain text into hexadecimal — is just as common. You encode text to hex when you build test fixtures for a binary protocol, embed a magic string in firmware, escape bytes for a URL or shell, or store raw values in a database column. Get the direction backwards and you ship a payload that nothing downstream can parse.

This guide is the mirror image of hex to ASCII conversion. Here we go the other way: take a string like Hello, look at each character's byte value, and write it as two hex digits. You'll learn exactly how the mapping works, how to do it in four languages and on the command line, how to control the output format (uppercase, spacing, 0x prefixes), and where the conversion quietly breaks when your text isn't plain ASCII.

If you just need a quick answer, paste your text into the ASCII to hex converter or the text to hex tool and copy the result. If you want to understand and automate it, read on.

What "ASCII to Hex" Actually Means

ASCII assigns a number from 0 to 127 to each character. The letter A is 65, a space is 32, the digit 0 is 48, and so on. Those numbers are stored as bytes, and a byte is most naturally written in hexadecimal — base-16 — because one byte fits perfectly into exactly two hex digits (00 to FF).

So "ASCII to hex" is really a two-step lookup:

  1. Find each character's numeric code point (its ASCII value).
  2. Write that number in base-16, padded to two digits.

The word Hi becomes 4869: H is 72 decimal which is 48 hex, and i is 105 decimal which is 69 hex. There is no compression, no padding scheme, and no checksum — just a direct, reversible 1-byte-to-2-hex-digit mapping. That predictability is exactly why hex is the lingua franca for inspecting raw data.

How to Convert Text to Hex by Hand

Let's walk through Cat! so you can see every step:

Character ASCII (decimal) Hex
C 67 43
a 97 61
t 116 74
! 33 21

Concatenate the hex column and you get 43617421. To go from a decimal value to two hex digits manually: divide by 16, the quotient is the first digit, the remainder is the second. For C (67): 67 ÷ 16 = 4 remainder 3, so 43. Values 10–15 become the letters A–F.

A few sanity checks worth memorizing:

  • Uppercase letters AZ are 415A.
  • Lowercase letters az are 617A.
  • Digits 09 are 3039.
  • Space is 20, newline is 0A, tab is 09.

Notice lowercase is always exactly 0x20 (32) higher than its uppercase counterpart — that single-bit difference is how case-insensitive comparisons and the old "toggle case" tricks work.

Converting ASCII to Hex in Code

Python

Python's bytes type does the heavy lifting. The .hex() method is the canonical one-liner:

text = "Hello World"
hex_string = text.encode("ascii").hex()
print(hex_string)  # 48656c6c6f20576f726c64

Want spaces between bytes, or uppercase? bytes.hex() accepts a separator (Python 3.8+), and you can upper-case the result:

data = "Hello".encode("ascii")

print(data.hex())            # 48656c6c6f
print(data.hex(" "))         # 48 65 6c 6c 6f
print(data.hex(" ").upper()) # 48 65 6C 6C 6F

If your text might contain non-ASCII characters, encode as UTF-8 instead and decide what byte order you expect (more on that below):

"café".encode("utf-8").hex()  # 636166c3a9  — note 'é' is two bytes

JavaScript (Node.js and the Browser)

In Node, Buffer mirrors Python's approach:

const hex = Buffer.from("Hello World", "utf8").toString("hex");
console.log(hex); // 48656c6c6f20576f726c64

In the browser there's no Buffer, so use TextEncoder to get the bytes, then map each to a padded hex pair:

function textToHex(text) {
  const bytes = new TextEncoder().encode(text); // Uint8Array, UTF-8
  return Array.from(bytes)
    .map(b => b.toString(16).padStart(2, "0"))
    .join("");
}

console.log(textToHex("Hi!")); // 486921

The padStart(2, "0") matters: without it, the byte 0x09 would render as 9 and silently corrupt every offset after it. Padding is the single most common bug in hand-rolled encoders.

C

In C you iterate the bytes directly and let printf format them:

#include <stdio.h>

int main(void) {
    const char *text = "Hi!";
    for (const unsigned char *p = (const unsigned char *)text; *p; p++) {
        printf("%02x", *p);   // %02x = lowercase, zero-padded, 2 wide
    }
    printf("\n");             // prints 486921
    return 0;
}

Use unsigned char so bytes above 0x7F don't sign-extend into garbage. Swap %02x for %02X if you want uppercase output.

Command Line

The shell has several one-liners, handy inside scripts or pipelines:

# xxd: -p plain hex, no offsets/ASCII column
printf '%s' "Hello" | xxd -p
# 48656c6c6f

# od: choose 1-byte hex output, strip the offset column
printf '%s' "Hi" | od -An -tx1
#  48 69

# hexdump with a custom format string
printf '%s' "Hi" | hexdump -v -e '/1 "%02x"'
# 4869

Use printf '%s' rather than echo, because echo may append a newline (0a) and some shells interpret backslashes — both will pollute your hex.

Controlling the Output Format

"Text to hex" doesn't have one canonical layout. Depending on where the hex is going, you'll want different formatting:

Style Example Where it's used
Continuous lowercase 48656c6c6f Database literals, hashes, compact storage
Space-separated 48 65 6c 6c 6f Hex editors, packet dumps, human reading
0x-prefixed bytes 0x48 0x65 0x6c C arrays, embedded constants
\x escapes \x48\x65\x6c C/Python string literals, shell printf
Colon-separated 48:65:6c:6c:6f MAC-style / TLS fingerprints
Uppercase 48656C6C6F RFCs, some protocol specs

Hex is case-insensitive — 4f and 4F are the same byte — so uppercase versus lowercase is purely cosmetic. Pick one and stay consistent within a project so diffs stay clean.

Where ASCII to Hex Quietly Breaks

Your text isn't actually ASCII

ASCII only covers 0–127. The moment you include é, , , an emoji, or a "smart quote" pasted from a word processor, you're outside ASCII. Most encoders silently fall back to UTF-8, where those characters become multiple bytes: é is c3 a9, and 😀 is four bytes (f0 9f 98 80). That's correct behavior, but if a downstream system expected one byte per character, the offsets will be wrong. Always know whether you're encoding as ASCII or UTF-8. For a deeper look, see ASCII vs UTF-8 vs Unicode.

Invisible whitespace and line endings

A trailing space, a tab, or a Windows-style \r\n line ending all encode to real bytes (20, 09, 0d 0a). If your hex output is two characters longer than you expect, check for a stray newline — this is the classic "but I only typed five letters" surprise.

Byte order is a non-issue for text

People sometimes ask about big-endian versus little-endian when encoding strings. For text, there is no endianness: each character is an independent byte written left to right. Endianness only matters when you encode multi-byte numbers (a 32-bit integer), not characters. Don't reverse your byte pairs.

Padding and odd lengths

Because every byte is exactly two hex digits, valid hex from text is always an even number of characters. If you ever produce an odd-length string, a padStart/%02x step is missing somewhere.

Practical Use Cases

  • Building protocol test vectors. Hand a parser a known hex payload and assert the decoded result. Encoding your expected text to hex gives you the fixture.
  • Embedding constants in C/assembly. Magic numbers, signatures, and lookup tables are often written as hex byte arrays.
  • Escaping for shells and URLs. Percent-encoding (%48) and \x48 escapes are hex under the hood; knowing the byte values lets you craft or debug them.
  • Storing binary in text columns. Some databases accept hex literals (e.g. X'48656C6C6F') for BLOB/BINARY columns.
  • Generating fingerprints and IDs. Colon-separated hex is the standard display format for hashes and certificate thumbprints.

FAQ

How do I convert ASCII text to hex in Python?

Encode the string to bytes and call .hex(): "Hello".encode("ascii").hex() returns 48656c6c6f. Add a separator for readability with "Hello".encode().hex(" "), and .upper() for uppercase. Use .encode("utf-8") instead of "ascii" if the text may contain accented or non-Latin characters.

Is text-to-hex the same as Base64 or URL encoding?

No. All three turn text into a safe representation, but hex uses two characters per byte (16 symbols, 0–9 and A–F), Base64 uses four characters per three bytes (64 symbols), and URL encoding only escapes unsafe characters as %HH. Hex is the most verbose but the easiest to read byte-by-byte. See the comparison table in our hex to ASCII guide.

Should hex output be uppercase or lowercase?

Either works — hex is case-insensitive, so 4f and 4F represent the identical byte. Lowercase is more common in programming and tooling (Python, Git, xxd all default to it); uppercase appears in some RFCs and protocol specs. Just stay consistent within a codebase.

Why is my hex twice as long as the number of characters?

That's expected: each character is one byte and every byte is two hex digits, so the hex string is always exactly twice the byte count. If it's more than double, your text contains multi-byte UTF-8 characters or hidden whitespace such as a trailing newline.

How do I add spaces or 0x prefixes between bytes?

Format after conversion. In Python, data.hex(" ") inserts spaces. For 0x prefixes or \x escapes, map over the byte pairs and prepend the prefix to each. The ASCII to hex tool also offers spacing and prefix options without writing any code.

Can I convert text with emojis to hex?

Yes, but encode as UTF-8, not ASCII — emojis are outside the ASCII range and occupy multiple bytes (a typical emoji is four bytes). "😀".encode("utf-8").hex() returns f09f9880. Decoding it back requires reading those four bytes together as one UTF-8 sequence.

Conclusion

Encoding text to hex is the straightforward inverse of decoding it: map each character to its byte value, write that value as two hex digits, and format the result however the destination expects. The mechanics are simple, but the edge cases — UTF-8 multi-byte characters, hidden whitespace, missing zero-padding — are where real bugs live, so always be explicit about your encoding and double-check the length.

For one-off jobs, the ASCII to hex converter and text to hex tool give you instant, formatted output. When you need it in a pipeline, reach for bytes.hex(), Buffer.toString("hex"), or a tidy printf "%02x" loop — and now you know exactly what each byte means.

Convert Hex to ASCII Instantly

Paste hex strings and get readable text. Supports multiple formats, batch conversion, all client-side.

Open Hex Converter