Skip to content
d.devtul.fun
中文
Regex · UUID

UUID Regex

A UUID validation pattern you can copy, plus an explanation of version and variant bits and the honest limit of what regex can prove.

The pattern

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$

Matches the canonical 8-4-4-4-12 hexadecimal form with hyphens. Case-insensitive with the i flag. It checks shape only, never version semantics.

Test this pattern

Edit the text below — matching happens locally, nothing is uploaded.

Variants

Lowercase only
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$

Rejects uppercase letters, so normalize to lower case first or you will reject valid UUIDs from strict generators.

UUID v4 only
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

Pins the version digit to 4 and the variant to 8, 9, a, or b. Use only when your system genuinely requires v4.

The UUID regex you can copy

The canonical form is eight, four, four, four, and twelve hexadecimal digits, separated by hyphens:

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$

This is the safest general-purpose check: it accepts uppercase and lowercase hex, enforces the five segment lengths, and requires exactly four hyphens in the right places. With the i flag you could drop the A-F part, but spelling it out keeps the pattern portable across engines that ignore flags.

What each segment means

  • [0-9a-fA-F]{8} — the first 32 bits, usually the low or high timestamp depending on version.
  • {4} — the next 16 bits, historically the version-related time field.
  • {4} — the version nibble sits at the start of this segment (see below).
  • {4} — the variant nibble sits at the start of this segment.
  • {12} — the final 48 bits, typically the node (MAC or random).

The hyphens are not decorative. They are part of the RFC 4122 / 9562 textual representation, and their positions encode where each field boundary falls.

Version and variant bits, the part regex can pin

A UUID is not just thirty-two hex chars; two specific positions carry meaning:

  • The version is the first hex digit of the third group (character 14, zero-indexed). Legal values today are 1 through 8: v1 time-based, v2 DCE, v3 and v5 name-based (MD5/SHA-1), v4 random, v6/v7 time-ordered, v8 custom.
  • The variant is the first hex digit of the fourth group (character 19). For the RFC 4122 layout it must be 8, 9, a, or b — that is, the two most significant bits are 10.

If you only accept v4, pin those positions:

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

The 4 after the second hyphen forces version 4; [89abAB] after the third forces a valid RFC variant.

Why regex only checks the shape

This is the core argument. A regex confirms that a string looks like a UUID. It cannot confirm that the version semantics are honored. A string can have a 4 in the version slot and still be a v4 only by accident, with zero bits of randomness — perfectly "valid" to the regex and cryptographically worthless. Conversely, a future version 9 would be rejected by today's version-pinned pattern even though it is a legitimate UUID. Regex sees digits; it does not see meaning.

Common mistakes

  • Dropping the case: writing [0-9a-f] only rejects uppercase, so 550E8400-... fails. Either add A-F or normalize case first.
  • Wrong segment counts: forgetting a group or using {16} in one block yields a pattern that matches the wrong length and silently passes garbage.
  • Using \w: \w matches digits, letters, and the underscore, so ____-____-____-____-________ would pass. Always use an explicit hex class.
  • Missing anchors: without ^ and $, 1234-... embedded inside a longer string would match a substring and fool a validator.

Real examples: accepted and rejected

InputResultWhy
550e8400-e29b-41d4-a716-446655440000AcceptedCorrect 8-4-4-4-12 shape, valid v4
550E8400-E29B-41D4-A716-446655440000AcceptedUppercase is valid hex too
123e4567-e89b-12d3-a456-426614174000AcceptedValid v1 shape
not-a-uuidRejectedNot hexadecimal, no structure
12345678-1234-1234-1234-1234567890RejectedLast group has 10 digits, needs 12

Braces, URN prefixes, and the nil UUID

Real input is messier than the canonical form:

  • Microsoft tooling wraps UUIDs in braces: {550e8400-e29b-41d4-a716-446655440000}. Strip the braces before testing, or extend the pattern.
  • URN form carries a prefix: urn:uuid:550e8400-e29b-41d4-a716-446655440000. Again, strip or allow the prefix.
  • The nil UUID 00000000-0000-0000-0000-000000000000 is syntactically valid and means "no UUID". Treat it as a sentinel, not as a real identifier.

What to use instead

For actual validation, parse rather than match. Most languages ship a UUID type that rejects malformed input and even checks version consistency:

import uuid
try:
    u = uuid.UUID("550e8400-e29b-41d4-a716-446655440000")
    print(u.version)   # 4
except ValueError:
    print("not a uuid")

In JavaScript, crypto.randomUUID() produces v4 strings and new UUID(...) (or a small library) parses them. Use the parser: it understands nil, version, and variant far better than any regex you will write.

Generating versus validating

Keep the two jobs separate. Generating a UUID should draw from a cryptographically secure random source — most standard libraries already do — while validating one is what this page is about. A regex is the weakest possible validator and a parser is the strongest. Never hand-roll random hex and hope the version bit lands correctly; call the library generator so the version and variant nibbles are set for you. If you only need a database primary key, take the library's string, run it through the parser once on the way in, and move on. No regex in the world is more trustworthy than that round trip.

Frequently asked

What is the correct UUID regex?

Use ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ for the general shape, optionally pinning the version digit.

Can a regex verify a UUID is really version 4?

Only superficially. It can confirm the version slot is 4, but not that the rest is genuinely random. Use a UUID parser for real checks.

Why should I not use \w for hex?

\w also matches the underscore, so a string of underscores would pass. Always use an explicit [0-9a-fA-F] class.

What about braces and urn:uuid: prefixes?

Strip the surrounding braces or the urn:uuid: prefix before matching, or extend the pattern to allow them.

Related regex guides

Open the full Regex Tester