Skip to content

@absoluteui/helpers/encoding

UTF-8, Base64, Base64URL, hex, data URLs, and CRC-32/Adler-32/FNV-1a checksums.

import { ... } from '@absoluteui/helpers/encoding';

Byte and text encodings that behave the same in every browser: UTF-8, Base64 and Base64URL (Unicode-safe, unlike raw btoa), hex, data: URLs, and fast non-cryptographic checksums. Reach for it when you move text through a byte channel, put small payloads in URLs, or detect changed content. For hashing or comparing secrets, use the services crypto module instead. The Helpers and services guide covers import and error conventions.

How do I put a small JSON payload in a URL or header?

Section titled “How do I put a small JSON payload in a URL or header?”

Base64URL has no +, /, or =, so the result needs no further escaping. Strings are encoded as UTF-8 first, so names with accents survive the round trip.

import { base64UrlDecodeText, base64UrlEncode } from '@absoluteui/helpers/encoding';
const state = base64UrlEncode(JSON.stringify({ employee: 'Zoë Müller', tab: 'leave' }));
/^[A-Za-z0-9_-]+$/.test(state); // => true
JSON.parse(base64UrlDecodeText(state)).employee; // => 'Zoë Müller'

How do I read an image or document pasted as a data URL?

Section titled “How do I read an image or document pasted as a data URL?”

parseDataUrl returns the media type and the decoded bytes, or undefined when the URL is malformed. Set maxBytes so an oversized paste fails before it is decoded.

import { parseDataUrl, toDataUrl } from '@absoluteui/helpers/encoding';
const pasted = toDataUrl('Payslip 2026-09', 'text/plain');
const parsed = parseDataUrl(pasted, { maxBytes: 1024 * 1024 });
parsed?.mimeType; // => 'text/plain'
parsed?.bytes.length; // => 15
parseDataUrl('not a data url'); // => undefined

How do I checksum a file that arrives in chunks?

Section titled “How do I checksum a file that arrives in chunks?”

crc32, adler32, and fnv1a32 take the previous result as a second argument, so you can hash a stream without buffering it. The result equals the checksum of the whole content.

import { crc32 } from '@absoluteui/helpers/encoding';
const chunks = ['employee_id,name\n', 'E-1001,Asha Rao\n', 'E-1002,Liam Chen\n'];
let crc: number | undefined;
for (const chunk of chunks) crc = crc32(chunk, crc);
crc === crc32(chunks.join('')); // => true

How do I derive a stable cache key or bucket from a string?

Section titled “How do I derive a stable cache key or bucket from a string?”

fnv1a32 is fast and deterministic across sessions, which makes it good for cache keys, sharding, or A/B buckets. It is not a security hash: never use it for passwords or tokens.

import { fnv1a32, hexEncode } from '@absoluteui/helpers/encoding';
const bucket = fnv1a32('E-1001') % 4;
bucket === fnv1a32('E-1001') % 4; // => true // same input, same bucket
const key = fnv1a32('/api/employees?dept=finance').toString(16).padStart(8, '0');
key.length; // => 8
hexEncode('OK', { uppercase: true }); // => '4F4B'

Decoders reject malformed input with a ValidationError instead of returning garbage. utf8Decode replaces invalid bytes with U+FFFD unless you pass fatal: true. Oversized data URLs throw a LimitError.

import { base64Decode, hexDecode, parseDataUrl, toDataUrl, utf8Decode } from '@absoluteui/helpers/encoding';
base64Decode('not*base64'); // => throws HLP_ENCODING_INVALID_BASE64
hexDecode('abc'); // => throws HLP_ENCODING_INVALID_HEX // odd length
utf8Decode(new Uint8Array([0xff]), { fatal: true }); // => throws HLP_ENCODING_INVALID_UTF8
parseDataUrl(toDataUrl('x'.repeat(2000)), { maxBytes: 1000 }); // => throws HLP_ENCODING_DATA_URL_TOO_LARGE

adler32

Adler-32 (zlib). Pass the previous result to continue over chunks (initial value 1).

function adler32(data: BinaryInput, previous?: number): number;

Example:

adler32('Wikipedia'); // => 0x11e60398

base64Decode

Decodes standard base64 (whitespace ignored, padding optional) to bytes. Throws HLP_ENCODING_INVALID_BASE64 on malformed input.

function base64Decode(text: string): Uint8Array<ArrayBuffer>;

Example:

base64Decode('AQID'); // => new Uint8Array([1, 2, 3])

base64DecodeText

Decodes base64 to a UTF-8 string.

function base64DecodeText(text: string, options?: Utf8DecodeOptions): string;

Example:

base64DecodeText('aMOpbGxvIOKckw=='); // => 'héllo ✓'

base64Encode

Base64-encodes bytes, or a string as UTF-8 (never raw btoa, so any Unicode is safe).

function base64Encode(input: BinaryInput): string;

Example:

base64Encode('héllo ✓'); // => 'aMOpbGxvIOKckw=='

base64UrlDecode

Decodes base64url (padding optional). Throws HLP_ENCODING_INVALID_BASE64 on malformed input.

function base64UrlDecode(text: string): Uint8Array<ArrayBuffer>;

Example:

base64UrlDecode('-_8'); // => new Uint8Array([251, 255])

base64UrlDecodeText

Decodes base64url to a UTF-8 string.

function base64UrlDecodeText(text: string, options?: Utf8DecodeOptions): string;

Example:

base64UrlDecodeText(base64UrlEncode('{"a":1}')); // => '{"a":1}'

base64UrlEncode

Base64url-encodes (RFC 4648 the specification) without padding.

function base64UrlEncode(input: BinaryInput): string;

Example:

base64UrlEncode(new Uint8Array([251, 255])); // => '-_8'

bytesEqual

Byte-wise equality. Not constant-time: use the services crypto module to compare secrets.

function bytesEqual(a: BytesLike, b: BytesLike): boolean;

Example:

bytesEqual(new Uint8Array([1]), new Uint8Array([1])); // => true

concatBytes

Concatenates byte arrays into a new Uint8Array.

function concatBytes(...parts: readonly BytesLike[]): Uint8Array<ArrayBuffer>;

Example:

concatBytes(new Uint8Array([1]), new Uint8Array([2, 3])); // => new Uint8Array([1, 2, 3])

crc32

CRC-32/ISO-HDLC (zlib, ZIP, PNG). Pass the previous result to continue over chunks. Returns an unsigned 32-bit integer.

function crc32(data: BinaryInput, previous?: number): number;

Example:

crc32('123456789'); // => 0xcbf43926
crc32(' world', crc32('hello')); // => crc32('hello world') // incremental over chunks

fnv1a32

FNV-1a 32-bit hash (strings are hashed as UTF-8). Non-cryptographic: use for buckets and cache keys.

function fnv1a32(data: BinaryInput, previous?: number): number;

Example:

fnv1a32('a'); // => 0xe40c292c

hexDecode

Decodes hex (either case, even length). Throws HLP_ENCODING_INVALID_HEX otherwise.

function hexDecode(text: string): Uint8Array<ArrayBuffer>;

Example:

hexDecode('00FF'); // => new Uint8Array([0, 255])

hexEncode

Lowercase hex encoding of bytes (or a UTF-8 string).

function hexEncode(input: BinaryInput, options?: {
readonly uppercase?: boolean;
}): string;

Example:

hexEncode(new Uint8Array([0, 255])); // => '00ff'

isBase64

True when text is decodable base64 (strict by default: no whitespace).

function isBase64(text: string, options?: IsBase64Options): boolean;

Example:

isBase64('AQID'); // => true
isBase64('AQI*'); // => false

parseDataUrl

Parses a data: URL. Returns undefined when malformed; throws LimitError when over maxBytes.

function parseDataUrl(url: string, options?: ParseDataUrlOptions): ParsedDataUrl | undefined;

Example:

parseDataUrl('data:text/plain;charset=utf-8,hi%21')?.bytes; // => new Uint8Array([104, 105, 33]) // 'hi!'

toDataUrl

Builds a base64 data: URL.

function toDataUrl(input: BinaryInput, mimeType?: string): string;

Example:

toDataUrl('hi', 'text/plain'); // => 'data:text/plain;base64,aGk='

utf8Decode

Decodes UTF-8 bytes to a string.

function utf8Decode(bytes: BytesLike, options?: Utf8DecodeOptions): string;

Example:

utf8Decode(new Uint8Array([226, 130, 172])); // => '€'

utf8Encode

Encodes a string as UTF-8. Lone surrogates become U+FFFD.

function utf8Encode(text: string): Uint8Array<ArrayBuffer>;

Example:

utf8Encode('€'); // => new Uint8Array([226, 130, 172])

IsBase64Options

interface IsBase64Options {
readonly alphabet?: 'base64' | 'base64url';
readonly requirePadding?: boolean;
readonly allowWhitespace?: boolean;
}

ParseDataUrlOptions

interface ParseDataUrlOptions {
readonly maxBytes?: number;
}

ParsedDataUrl

interface ParsedDataUrl {
readonly mimeType: string;
readonly parameters: Readonly<Record<string, string>>;
readonly base64: boolean;
readonly bytes: Uint8Array<ArrayBuffer>;
}

Utf8DecodeOptions

interface Utf8DecodeOptions {
readonly fatal?: boolean;
readonly keepBom?: boolean;
}

BinaryInput

Bytes, or a string that is encoded as UTF-8 first.

type BinaryInput = BytesLike | string;

BytesLike

Anything that can be viewed as bytes.

type BytesLike = Uint8Array | ArrayBuffer | ArrayBufferView;