Base16 (hex) encoder / decoder

Encode text to hexadecimal bytes or decode hex back to text using RFC 4648 §8.

Docify's Base16 encoder (also called hex or hexadecimal) implements RFC 4648 §8 using the 0-9 A-F alphabet. Each byte becomes two hex characters. Example: foobar encodes to 666F6F626172. No padding is used. Decoding is case-insensitive and accepts whitespace between digit pairs. This is not integer conversion (use Number Base Converter) or CSS colors (use Color Converter). Nothing is uploaded.

Plain text
Base16 output

How it works

  1. Encoding: Input text is converted to UTF-8 bytes. Each byte is represented as two hexadecimal digits (00-FF). Output is always uppercase.
  2. Decoding: Hex digits are parsed in pairs and converted back to bytes, then decoded as UTF-8. Whitespace between pairs is ignored. Case is insensitive.
  3. No padding: Unlike Base64 and Base32, hex encoding requires no padding because each byte maps to exactly two characters.
  4. Efficiency: Hex is 50% efficient (2 characters per byte) vs Base64 at 75% (4 characters per 3 bytes). Use hex for debugging and readability, Base64 for compactness.

Encoding efficiency comparison

EncodingCharacters / byteEfficiency
Base16 (hex)250%
Base321.662.5%
Base641.3375%

Base16 in Python and Node

The snippets below encode UTF-8 bytes as RFC 4648 §8 hexadecimal (two digits per octet, no padding). That is the same Base16 this page returns for text. Node 'hex' and CPython bytes.hex() write lowercase; this page writes uppercase 0–9 A–F, so the snippets call toUpperCase() / upper(). They are not integer conversion (hex(255) is '0xff') and not CSS color hex. For how hex compares to Base64 and Base32, see Hex vs Base64 vs Base32: RFC 4648 Encodings.

Node.js with Buffer

Node's Buffer encoding 'hex' is RFC 4648 §8 in lowercase. Pass 'utf8' so the bytes match this page's encodeURIComponent path, then upper-case the string. Decode accepts both cases:

const encoded = Buffer.from('foobar', 'utf8').toString('hex').toUpperCase();
// "666F6F626172"

const decoded = Buffer.from(encoded, 'hex').toString('utf8');
// "foobar"

Python with bytes.hex

bytes.hex() is lowercase; call .upper() to match this page. Encode UTF-8 first — a str has no hex() that returns RFC 4648 octets. bytes.fromhex accepts both cases and spaces between pairs:

encoded = 'foobar'.encode('utf-8').hex().upper()
# '666F6F626172'

decoded = bytes.fromhex(encoded).decode('utf-8')
# 'foobar'

Odd-length hex is rejected here and by bytes.fromhex; Node 'hex' drops the last nibble (666 decodes as f). This page strips all whitespace, then reads pairs; bytes.fromhex allows spaces between complete pairs; Node 'hex' stops at the first non-hex character, so 66 6F is only f. binascii.hexlify is the same lowercase encode; unhexlify rejects spaces. Integer hex(255) belongs on the Number Base Converter; CSS #3366cc belongs on the Color Converter.

Base16 in the shell

Text encode on this page converts UTF-8 bytes to RFC 4648 §8 hexadecimal (two digits per octet, 0–9 A–F) with no spaces, wrap, or padding. GNU coreutils 8.31+ basenc --base16 writes that same uppercase alphabet. It wraps at 76 characters by default; pass -w 0 to match this page. echo appends a newline, so use printf to match this page's encoding of foobar. macOS ships neither basenc nor base32. Homebrew coreutils installs gbasenc. OpenSSL has openssl base64, not a Base16 encoder. basenc --base32 is RFC 4648 §6 and --base32hex is §7 — those belong on Base32 and Base32hex. There is no POSIX Base16 encoder that writes a continuous uppercase stream. hexdump and xxd samples stay below. These commands encode octets, not integer hex(255) or CSS color hex.

GNU basenc (Linux)

Coreutils basenc --base16 reads a file or stdin. Decode with -d. GNU -i means --ignore-garbage on decode — it is not an input-file flag:

# Text without a trailing newline (same as this page)
printf 'foobar' | basenc --base16 -w 0
# 666F6F626172

printf '666F6F626172' | basenc --base16 -d
# foobar

Default GNU decode is stricter than this page. Lowercase letters fail with basenc: invalid input — this decoder always accepts both cases. -i skips lowercase as garbage; it does not casefold, so 666f6f626172 with -i decodes as ffbar (the f digits are dropped). Spaces between pairs also need -i; this page strips all whitespace. Newlines in the encoded stream are allowed. Odd-length hex writes the complete octets, then errors on the dangling nibble (666 prints f and exits 1). This page rejects odd length before decoding. Empty stdin encodes to empty; this page asks for text. For hexdump and xxd, see the blocks below. For Python or Node on macOS or Windows, use the snippets above.

hexdump (util-linux / BSD)

hexdump -C is a hex+ASCII dump with offsets — not RFC 4648 Base16. The format string below writes one continuous uppercase stream. There is no decode flag; use xxd -r -p or the Python block above:

# Text without a trailing newline (same as this page)
printf 'foobar' | hexdump -ve '1/1 "%02X"'
# 666F6F626172

xxd -p (vim)

Plain -p / -ps hex is lowercase. Default wrap is 30 octets; -c 0 is a single line on vim 8.2.4088+ (older xxd, including many macOS builds, caps -c at 256). Decode with -r -p:

printf 'foobar' | xxd -p -u
# 666F6F626172

printf '666F6F626172' | xxd -r -p
# foobar

POSIX od -An -tx1 writes space-separated lowercase bytes and a leading space ( 66 6f 6f 62 61 72). Repeated lines become * unless you pass -v. Default xxd (no -p) and Windows certutil -encodehex are offset dumps, not this page's stream. xxd -r -p skips garbage; this page rejects non-hex after stripping whitespace. Odd-length hex is rejected here. Integer hex belongs on the Number Base Converter; CSS colors belong on the Color Converter.

FAQ

Does this tool upload my text?
No. All encoding and decoding runs in your browser using JavaScript. Nothing is sent to a server.
What is Base16 / hexadecimal encoding?
Base16 represents each byte as two hexadecimal characters (0-9 A-F). It is the most verbose base encoding but the easiest to read and debug. Also called "hex encoding."
Is Base16 decoding case-sensitive?
No. This decoder accepts both uppercase and lowercase hex digits. 666F6F626172 and 666f6f626172 decode to the same result.
Does Base16 use padding like Base64?
No. Base16 has no padding because each byte maps exactly to two characters. The encoded length is always exactly twice the input byte length.
Is this the same as integer hex conversion?
No. This tool encodes/decodes UTF-8 byte sequences. To convert integers between decimal and hex (e.g., 255 ↔ FF), use our Number Base Converter tool.
Is this the same as CSS color hex codes?
No. CSS hex colors (#3366cc) represent RGB values in a specific format. This tool encodes arbitrary text as hex bytes. Use our Color Converter for CSS colors.

Related