JavaScript now gives Uint8Array direct methods for converting binary data to Base64 and hexadecimal text. You can encode bytes with toBase64() or toHex(), and restore them with Uint8Array.fromBase64() or Uint8Array.fromHex(). These methods remove the awkward byte-to-string conversion required by older btoa() and atob() workflows.
The APIs are useful when you handle file chunks, cryptographic values, compact identifiers, network payloads, or data stored in text-only formats. They became Baseline 2025 features, so check compatibility when you support older browsers or embedded web views.
Why Use Uint8Array Encoding Methods?
A Uint8Array stores values from 0 to 255. Base64 represents those bytes with a compact text alphabet, while hexadecimal uses two readable characters for each byte. Encoding changes the representation; it does not encrypt or secure the data.
| Method | Purpose | Result |
|---|---|---|
| toBase64() | Encode an existing byte array as Base64 | String |
| fromBase64() | Create bytes from a Base64 string | New Uint8Array |
| toHex() | Encode bytes as lowercase hexadecimal | String |
| fromHex() | Create bytes from hexadecimal text | New Uint8Array |
| setFromBase64() or setFromHex() | Decode into a preallocated array | Read and written counts |
Convert Text to Base64 and Back
Text and bytes are different data types. Use TextEncoder to create UTF-8 bytes before encoding, then use TextDecoder after decoding. This approach handles characters outside basic ASCII correctly.
Example:
// Convert Unicode text into UTF-8 bytes.
const message = "Priya paid £25";
const bytes = new TextEncoder().encode(message);
// Encode the bytes, then decode them again.
const encoded = bytes.toBase64();
const restoredBytes = Uint8Array.fromBase64(encoded);
const restoredText = new TextDecoder().decode(restoredBytes);
console.log(encoded);
console.log(restoredText);
Output:
UHJpeWEgcGFpZCDCozI1
Priya paid £25
Note: Do not pass Unicode text directly to btoa(). Encoding the text with TextEncoder first preserves its UTF-8 bytes.
Use URL-Safe Base64
The default Base64 alphabet uses plus and slash characters. For URL paths, query values, or tokens, select the base64url alphabet. You can also omit trailing padding characters when the receiving system accepts unpadded Base64.
Example:
// Encode bytes with the URL-safe alphabet and no padding.
const tokenBytes = new Uint8Array([251, 255, 239]);
const token = tokenBytes.toBase64({
alphabet: "base64url",
omitPadding: true
});
// Use the same alphabet when decoding the token.
const decoded = Uint8Array.fromBase64(token, {
alphabet: "base64url"
});
console.log(token);
console.log([...decoded]);
Output:
-__v
[251, 255, 239]
Convert Bytes to Hexadecimal
Hexadecimal is longer than Base64, but it is easy to inspect and compare. It works well for hashes, colors represented as bytes, protocol fields, and diagnostic output. fromHex() requires an even number of valid hexadecimal characters and does not allow whitespace.
Example:
// Represent four binary bytes as readable hexadecimal text.
const signature = new Uint8Array([222, 173, 190, 239]);
const hex = signature.toHex();
const copy = Uint8Array.fromHex(hex);
console.log(hex);
console.log([...copy]);
Output:
deadbeef
[222, 173, 190, 239]
Decode into an Existing Buffer
Use setFromBase64() or setFromHex() when you already have storage. Each method returns how much input it read and how many bytes it wrote. This is helpful for fixed buffers and streamed Base64 input.
Example:
// Decode four bytes into the middle of a larger buffer.
const packet = new Uint8Array(8);
const result = packet.subarray(2).setFromHex("cafed00d");
console.log(result);
console.log([...packet]);
Output:
{ read: 8, written: 4 }
[0, 0, 202, 254, 208, 13, 0, 0]
Try the Uint8Array Converter
Change the message and run the example. It displays Base64, hex, and the text restored from the Base64 value.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Uint8Array Encoding Lab</title>
<style>
body { font-family: Arial, sans-serif; max-width: 700px; margin: 30px auto; padding: 0 16px; }
input[type="text"] { box-sizing: border-box; width: 100%; padding: 10px; }
button { margin: 12px 0; padding: 9px 16px; }
dt { margin-top: 10px; font-weight: bold; }
dd { margin: 4px 0 0; overflow-wrap: anywhere; }
</style>
</head>
<body>
<h1>Uint8Array Encoding Lab</h1>
<label for="message">Message</label>
<input id="message" type="text" value="Asha paid £25 for lunch.">
<button id="convert">Convert text</button>
<dl>
<dt>Base64</dt><dd id="base64"></dd>
<dt>Hex</dt><dd id="hex"></dd>
<dt>Decoded text</dt><dd id="decoded"></dd>
</dl>
<script>
const message = document.querySelector('#message');
const base64Output = document.querySelector('#base64');
const hexOutput = document.querySelector('#hex');
const decodedOutput = document.querySelector('#decoded');
function convertText() {
// TextEncoder converts Unicode text into UTF-8 bytes.
const bytes = new TextEncoder().encode(message.value);
// Check the modern methods before using them.
if (typeof bytes.toBase64 !== 'function') {
base64Output.textContent = 'Update your browser to run this example.';
hexOutput.textContent = 'Uint8Array encoding methods are unavailable.';
decodedOutput.textContent = '';
return;
}
const base64 = bytes.toBase64();
const hex = bytes.toHex();
const restoredBytes = Uint8Array.fromBase64(base64);
base64Output.textContent = base64;
hexOutput.textContent = hex;
// TextDecoder converts restored UTF-8 bytes back to text.
decodedOutput.textContent = new TextDecoder().decode(restoredBytes);
}
document.querySelector('#convert').addEventListener('click', convertText);
convertText();
</script>
</body>
</html>
Handle Compatibility Safely
Feature detection lets an application keep a fallback for older environments. Test the method on the actual typed array instead of guessing from a browser name.
Example:
// Use the modern API only when the browser provides it.
const bytes = new Uint8Array([72, 105]);
if (typeof bytes.toBase64 === "function") {
console.log(bytes.toBase64());
} else {
console.log("Use a tested Base64 fallback for this browser.");
}
Conclusion
The Uint8Array Base64 and hex methods give you a direct, reliable way to move between binary bytes and text representations. Use Base64 for compact transport, Base64URL for URL-safe values, and hex when readability matters. Keep text conversion explicit with TextEncoder and TextDecoder, validate untrusted input, and retain a fallback when older browsers remain in scope.