UUID formats
A UUID is a 128-bit number. That number can be represented in several ways depending on the context:
| Format | Example | Length | Use case |
|---|---|---|---|
| Standard string | 550e8400-e29b-41d4-a716-446655440000 | 36 chars | Default, human-readable, most APIs |
| Hex (no hyphens) | 550e8400e29b41d4a716446655440000 | 32 chars | Compact string storage, some databases |
| Base64 | VQ6EAOKbQdSnFkRmVUQAAA== | 24 chars | JSON payloads, HTTP headers |
| URL-safe Base64 | VQ6EAOKbQdSnFkRmVUQAAA | 22 chars | URL parameters, JWT claims |
| URN | urn:uuid:550e8400-e29b-41d4-a716-446655440000 | 45 chars | XML, SAML, formal URI contexts |
| Binary | 16 raw bytes | 16 bytes | Database storage (BINARY(16) in MySQL/SQLite) |
All formats represent the exact same 128-bit value — conversion between them is lossless.
Format conversion in code
JavaScript / TypeScript
// Standard string → no-hyphen hex
function toHex(uuid: string): string {
return uuid.replace(/-/g, '');
}
// Standard string → Uint8Array (binary)
function toBytes(uuid: string): Uint8Array {
const hex = uuid.replace(/-/g, '');
const bytes = new Uint8Array(16);
for (let i = 0; i < 16; i++) {
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
}
return bytes;
}
// Standard string → URL-safe Base64 (22 chars, no padding)
function toBase64url(uuid: string): string {
const bytes = toBytes(uuid);
const b64 = btoa(String.fromCharCode(...bytes));
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
// URL-safe Base64 → standard string
function fromBase64url(b64url: string): string {
const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/') + '==';
const binary = atob(b64);
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
return [
hex.slice(0, 8),
hex.slice(8, 12),
hex.slice(12, 16),
hex.slice(16, 20),
hex.slice(20),
].join('-');
}
// Standard string → URN
function toURN(uuid: string): string {
return `urn:uuid:${uuid.toLowerCase()}`;
}
Python
import uuid
import base64
u = uuid.UUID('550e8400-e29b-41d4-a716-446655440000')
# Standard string (default)
print(str(u)) # 550e8400-e29b-41d4-a716-446655440000
# 32-char hex
print(u.hex) # 550e8400e29b41d4a716446655440000
# Raw bytes (16 bytes)
print(u.bytes) # b'\x55\x0e\x84\x00...'
# Base64 (24 chars with padding)
b64 = base64.b64encode(u.bytes).decode()
print(b64) # VQ6EAOKbQdSnFkRmVUQAAA==
# URL-safe Base64 (22 chars, no padding)
b64url = base64.urlsafe_b64encode(u.bytes).decode().rstrip('=')
print(b64url) # VQ6EAOKbQdSnFkRmVUQAAA
# URN
print(u.urn) # urn:uuid:550e8400-e29b-41d4-a716-446655440000
# Round-trip from bytes back to UUID
u2 = uuid.UUID(bytes=u.bytes)
print(u2 == u) # True
Go
import (
"encoding/base64"
"fmt"
"github.com/google/uuid"
)
u := uuid.MustParse("550e8400-e29b-41d4-a716-446655440000")
// Standard string
fmt.Println(u.String()) // 550e8400-e29b-41d4-a716-446655440000
// No-hyphen hex
fmt.Println(fmt.Sprintf("%x", [16]byte(u))) // 550e8400...
// Raw bytes (16-byte array)
bytes := [16]byte(u)
// URL-safe Base64 (no padding)
b64 := base64.RawURLEncoding.EncodeToString(bytes[:])
fmt.Println(b64) // VQ6EAOKbQdSnFkRmVUQAAA
// URN
fmt.Println("urn:uuid:" + u.String())
Which format should I use?
Standard hyphenated string is the right default. It is human-readable, universally supported, and unambiguous. Use it for logs, API responses, and any context where a human might read the value.
Hex without hyphens is useful when column width matters and the application always controls display (e.g., internal cache keys, Redis).
URL-safe Base64 (22 chars) cuts UUID length nearly in half and is safe to put directly in a URL path or query parameter without encoding. Useful when ID length visibly affects UX (short URLs, QR codes).
Binary (16 bytes) is the most storage-efficient option and gives the best database index performance. Use BINARY(16) in MySQL/SQLite, or the native uuid type in PostgreSQL. Never use a text column for binary UUIDs — the byte order must be preserved exactly.
URN is for formal URI contexts — XML namespaces, SAML assertions, DNS-SD, or any spec that requires a URI scheme. Do not use URNs in general application code; the standard string is sufficient.
Storing the converted format in a database
MySQL / SQLite — binary storage
-- Store as 16-byte binary
CREATE TABLE events (
id BINARY(16) PRIMARY KEY
);
-- Insert (convert string → binary in the query)
INSERT INTO events (id)
VALUES (UNHEX(REPLACE('018c4a14-2d91-7abc-8def-000000000001', '-', '')));
-- Query (convert back for display)
SELECT LOWER(HEX(id)) FROM events;
PostgreSQL — native uuid type
PostgreSQL’s uuid type stores 16 bytes internally and accepts any standard UUID string format directly — no manual conversion needed.
INSERT INTO events (id) VALUES ('018c4a14-2d91-7abc-8def-000000000001');
-- PostgreSQL normalises it to lowercase hyphenated form automatically
Related tools
- UUID Validator — confirm a UUID is valid before converting
- UUID Decoder — read the version and timestamp from a UUID
- UUID in Databases — storage format guide for PostgreSQL, MySQL, and SQLite
Frequently asked questions
What formats can a UUID be represented in?
A UUID can be represented as: the standard hyphenated string (8-4-4-4-12 hex), a 32-character hex string with no hyphens, a Base64 or URL-safe Base64 string (22 characters), a URN (urn:uuid:…), or raw 16-byte binary. The hyphenated string is the canonical form defined by RFC 9562.
Why store UUIDs as binary instead of strings?
Binary (16 bytes) is half the storage of a VARCHAR(36) UUID string (36 bytes). More importantly, binary comparison is faster than string comparison in indexes, and binary avoids encoding inconsistencies (uppercase vs lowercase). PostgreSQL's native uuid type and SQL Server's uniqueidentifier both store binary internally.
What is the UUID URN format?
The UUID URN (Uniform Resource Name) format is urn:uuid: followed by the standard hyphenated UUID, for example urn:uuid:550e8400-e29b-41d4-a716-446655440000. It is defined by RFC 9562 and used in contexts where a URI is required — such as XML namespaces, SAML, and some API specifications.