Question

How to Create a GUID / UUID in JavaScript

javascriptguiduuid

Question

How can I create GUIDs (globally unique identifiers) in JavaScript?

The GUID or UUID should be at least 32 characters long and remain within the ASCII character range so it can be passed around safely.

I am also unsure which routines are available across browsers, how random the built-in number generator is, and whether it is suitable for this purpose.

Short Answer

By the end of this page, you will understand what GUIDs and UUIDs are, how they are usually generated in JavaScript, why randomness quality matters, and which browser-safe APIs to prefer. You will also learn practical patterns for generating UUIDs in modern JavaScript and what to avoid when using Math.random().

Concept

A GUID (Globally Unique Identifier) and UUID (Universally Unique Identifier) are identifiers designed to be unique across systems, sessions, devices, and time.

In JavaScript, developers usually mean a UUID string, often in the standard version 4 format, such as:

550e8400-e29b-41d4-a716-446655440000

This format:

  • uses only ASCII characters
  • is 36 characters long including hyphens
  • contains 32 hexadecimal characters
  • is commonly used in APIs, databases, frontend state, and distributed systems

Why uniqueness matters

Unique identifiers are useful when:

  • creating IDs for client-side objects
  • tagging requests or logs
  • generating keys for temporary records
  • correlating events across systems
  • avoiding collisions when many users or devices create data independently

Why Math.random() is not ideal

A common beginner approach is to build a UUID-like string using Math.random(). That may look random, but it is not cryptographically secure and can vary in quality across environments.

Problems with Math.random() for IDs:

  • it is not designed for security-sensitive randomness
  • implementations differ between engines
  • collisions are more likely than with cryptographic randomness
  • it may be predictable in some contexts

What to use instead

In modern JavaScript, the preferred option is the Web Crypto API:

  • crypto.randomUUID() generates a standard UUID directly
  • crypto.getRandomValues() provides secure random bytes if you need a custom format

These APIs are designed for better randomness and are the correct choice when generating unique tokens in browsers and modern JavaScript runtimes.

GUID vs UUID

In everyday JavaScript usage, people often use the terms interchangeably. Technically:

  • UUID is the broader standard term
  • GUID is a term popularized by Microsoft

For most web development discussions, treating them as the same kind of identifier is fine.

Mental Model

Think of a UUID like a pre-printed luggage tag at a huge airport.

  • Every bag needs a label.
  • The label must be different enough that two bags do not get confused.
  • The label uses a simple character set so machines everywhere can read it.

If you create labels by guessing with a weak random process, eventually two bags may get similar labels or the process may be predictable.

If you use a reliable machine designed to create unique labels, the chance of accidental collision becomes extremely small.

In JavaScript, crypto.randomUUID() is that reliable machine.

Take Quiz

Syntax and Examples

Modern best option: crypto.randomUUID()

If your environment supports it, this is the simplest and best choice:

const id = crypto.randomUUID();
console.log(id);
// Example: "3f29c5e2-9d6d-4d9c-a2bf-7c9f5f77d0b1"

Why this is good

  • produces a standard UUID v4
  • uses secure randomness
  • ASCII-safe output
  • easy to read and store

Custom UUID-like string using crypto.getRandomValues()

If randomUUID() is unavailable, you can generate secure random bytes and convert them to hexadecimal:

function generateHexId() {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);

  return Array.from(bytes, byte =>
    byte.toString(16).padStart(2, '0')
  ).join('');
}

const id = generateHexId();
console.log(id);
// Example: "9f3c1b2e7a4d8c0f11aa22bb33cc44dd"

This gives:

  • 32 hexadecimal characters
  • ASCII-only output
  • strong randomness

A UUID v4 formatter using crypto.getRandomValues()

function uuidv4() {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);

  bytes[6] = (bytes[6] & 0x0f) | 0x40;
  bytes[8] = (bytes[8] & 0x3f) | 0x80;

  const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0'));

  return [
    hex.slice(0, 4).join(''),
    hex.slice(4, 6).join(''),
    hex.slice(6, 8).join(''),
    hex.slice(8, 10).join(''),
    hex.slice(10, 16).join('')
  ].join('-');
}

console.log(uuidv4());

This manually creates the standard UUID v4 structure.

What beginners often try

function weakId() {
  return Math.random().toString(16).slice(2);
}

This may look convenient, but it has problems:

  • length is inconsistent
  • randomness quality is weaker
  • not a standard UUID format
  • not suitable when collisions matter

Step by Step Execution

Consider this example:

function generateHexId() {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);

  return Array.from(bytes, byte =>
    byte.toString(16).padStart(2, '0')
  ).join('');
}

const id = generateHexId();
console.log(id);

Here is what happens step by step:

  1. new Uint8Array(16) creates an array of 16 bytes.
  2. Each byte can store a number from 0 to 255.
  3. crypto.getRandomValues(bytes) fills all 16 bytes with secure random values.
  4. Array.from(bytes, ...) loops over each byte.
  5. byte.toString(16) converts each number to hexadecimal.
    • for example, 255 becomes "ff"
    • 10 becomes "a"
  6. padStart(2, '0') ensures every byte becomes exactly two hex characters.
    • "a" becomes "0a"
  7. join('') combines all 16 two-character hex pieces into one 32-character string.
  8. The final result is a compact ASCII-safe identifier.

Example byte trace:

[15, 160, 3, 255]

Hex conversion:

0f a0 03 ff

Joined result:

0fa003ff

With 16 bytes, the final output has 32 hex characters.

Real World Use Cases

Client-side temporary IDs

When a user creates a note, todo, or form entry before saving to the server, you can assign a UUID locally.

Correlation IDs for logs

A frontend app can attach a UUID to a request so logs across frontend, backend, and monitoring systems can be matched.

Database record identifiers

Some systems use UUIDs instead of auto-incrementing integers to avoid exposing record counts or to support distributed creation.

File or upload tracking

A browser app can generate a unique ID for each upload session.

Offline-first applications

If users can create records while offline, UUIDs let multiple devices create unique records without needing a central server first.

API idempotency keys

A client can generate a unique ASCII-safe token to prevent duplicate API actions, such as repeated payment or order requests.

Take Quiz

Real Codebase Usage

In real projects, developers usually do not generate UUIDs manually unless they need a special format.

Common patterns

Use built-in APIs first

const id = crypto.randomUUID();

This is the most readable option.

Fallback when needed

function createId() {
  if (typeof crypto !== 'undefined' && crypto.randomUUID) {
    return crypto.randomUUID();
  }

  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);
  return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
}

Validation before use

Developers often check that an incoming ID has the expected shape.

function looksLikeUuid(value) {
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
}

Guard clauses

function saveRecord(record) {
  if (!record.id) {
    record.id = crypto.randomUUID();
  }

  // continue saving
}

Configuration and environment support

In shared libraries, developers may wrap ID generation behind one helper function so the rest of the codebase does not depend on a specific API directly.

export function generateId() {
  return crypto.randomUUID();
}

That makes it easier to test, replace, or adapt later.

Common Mistakes

1. Using Math.random() for important IDs

Broken example:

function badUuid() {
  return Math.random().toString(16).slice(2);
}

Why it is a problem:

  • not cryptographically secure
  • output length can vary
  • easier to collide than proper UUID generation

Use crypto.randomUUID() or crypto.getRandomValues() instead.

2. Assuming all random strings are UUIDs

Broken example:

const id = 'abc123';

This is just a string, not a standard UUID. If your system expects UUID format, generate or validate accordingly.

3. Forgetting ASCII-safe encoding rules

If you generate raw bytes and try to store them directly as text, the result may contain non-printable characters.

Broken example:

const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
const text = String.fromCharCode(...bytes);

This may create characters outside safe text ranges.

Convert bytes to hexadecimal instead.

4. Writing custom logic incorrectly

Broken example:

function hexId() {
  const bytes = new Uint8Array(4);
  crypto.getRandomValues(bytes);
  return Array.from(bytes, b => b.toString(16)).join('');
}

Problem:

  • values like 10 become "a" instead of "0a"
  • final string length becomes inconsistent

Fix:

return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');

5. Not checking API availability

Older environments may not support every method.

Safer approach:

if (typeof crypto !== 'undefined' && crypto.randomUUID) {
  console.log(crypto.randomUUID());
}

6. Using UUIDs where sequential IDs are actually better

UUIDs are useful, but not always necessary. For tiny local scripts, a counter may be simpler and easier to debug.

Comparisons

Common approaches compared

ApproachExample outputSecure randomnessStandard formatASCII-safeRecommended
crypto.randomUUID()3f29c5e2-9d6d-4d9c-a2bf-7c9f5f77d0b1YesYesYesYes
crypto.getRandomValues() + hex9f3c1b2e7a4d8c0f11aa22bb33cc44ddYesNot automaticallyYesYes
Math.random() stringa13bf09cNoNoUsuallyNo
Incrementing counter1, 2, 3NoNoYesOnly for simple local cases

UUID vs plain random hex

TypeLengthHas hyphensStandardizedGood use case
UUID v436 charsYesYesAPIs, distributed systems, shared formats
32-char hex string32 charsNoNot necessarilyCompact custom IDs

randomUUID() vs getRandomValues()

Featurecrypto.randomUUID()crypto.getRandomValues()
SimplicityEasiestMore manual work
Output formatUUID v4Raw random bytes
FlexibilityFixed formatFully customizable
Best forStandard UUIDsCustom ASCII-safe IDs
Take Quiz

Cheat Sheet

Quick reference

Best modern option

const id = crypto.randomUUID();

Generate a 32-character hex ID

function generateHexId() {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);
  return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
}

Rules to remember

  • UUIDs are usually represented as hex strings.
  • Standard UUID v4 format is 36 characters including hyphens.
  • Hex-only IDs are ASCII-safe.
  • Prefer crypto.randomUUID() when available.
  • Use crypto.getRandomValues() for secure custom formats.
  • Avoid Math.random() when uniqueness matters.

Standard UUID pattern

xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx

Where:

  • 4 indicates version 4
  • y is one of 8, 9, a, or b

Good validation regex

/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i

Edge cases

  • Math.random() output length is not fixed.
  • Raw bytes are not safe text by themselves.
  • Missing padStart(2, '0') can shorten your ID unexpectedly.

FAQ

What is the difference between a GUID and a UUID?

In most JavaScript discussions, they are treated as the same idea: a unique identifier string. UUID is the standard term, while GUID is a commonly used name from Microsoft ecosystems.

Can I use Math.random() to generate a UUID in JavaScript?

You can create a random-looking string with it, but it is not the recommended choice when uniqueness matters. Use crypto.randomUUID() or crypto.getRandomValues() instead.

Is crypto.randomUUID() supported in browsers?

It is supported in modern environments. If you need wider compatibility or a custom format, use crypto.getRandomValues().

Why are UUIDs often written with hyphens?

That is the common textual representation of the standard UUID format. The hyphens improve readability but are not the source of uniqueness.

How long is a UUID in JavaScript?

A standard UUID string is 36 characters long, including hyphens, or 32 hexadecimal characters without them.

Are UUIDs guaranteed to be unique?

Not absolutely, but properly generated UUIDs have an extremely low chance of collision and are considered safe for most applications.

Can I generate a UUID without a library?

Yes. In modern JavaScript, you can use built-in crypto APIs directly.

Should I store UUIDs as strings?

Yes, that is common and practical, especially when sending them through APIs, logging them, or storing them in JSON.

Take Quiz

Mini Project

Description

Build a small JavaScript utility that creates safe unique IDs for client-side records. This mirrors a common real-world need: creating IDs for notes, tasks, uploads, or offline data before the server assigns a permanent identifier.

Goal

Create a reusable ID generator that returns either a standard UUID or a 32-character hexadecimal ID using secure browser APIs.

Requirements

  1. Create a function that returns a standard UUID when crypto.randomUUID() is available.
  2. Add a fallback that generates a 32-character hexadecimal ID using crypto.getRandomValues().
  3. Ensure the result contains only ASCII-safe characters.
  4. Generate and print several example IDs.
  5. Add a simple validation check for UUID-shaped strings.
Take Quiz

Keep learning

Related questions

View more