A UUID is 32 hexadecimal digits in groups of 8, 4, 4, 4 and 12. Two of those digits carry meaning, and this regex checks both:
- The first digit of the third group is the version: 4 for random UUIDs, 7 for the time-ordered ones, 1 for the old time-and-MAC kind. RFC 9562, which replaced RFC 4122 in 2024, defines versions 1 to 8, so
[1-8]. - The first digit of the fourth group is the variant. For RFC UUIDs it’s 8, 9, a or b, so
[89ab].
The i flag accepts upper case, which RFC 9562 allows on input even though UUIDs are written in lower case.
What it accepts
The tester below checks one UUID per line with g, i and m; for a single value, keep only i.
f47ac10b-58cc-4372-a567-0e02b2c3d479 matches: version 4
01890a5d-ac96-774b-bcce-b302099a8057 matches: version 7
6ba7b810-9dad-11d1-80b4-00c04fd430c8 matches: version 1
F47AC10B-58CC-4372-A567-0E02B2C3D479 matches: upper case
f47ac10b58cc4372a5670e02b2c3d479 no: no hyphens
00000000-0000-0000-0000-000000000000 no: the nil UUID has no version
f47ac10b-58cc-4372-c567-0e02b2c3d479 no: variant c isn't an RFC UUID
{f47ac10b-58cc-4372-a567-0e02b2c3d479} no: braces, as Windows writes GUIDs
Looser and stricter versions
To accept anything shaped like a UUID, including the nil UUID and Microsoft’s older variants, skip the two checks:
/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i
To accept only random UUIDs, the kind crypto.randomUUID() makes, pin the version to 4:
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
If your input may arrive in braces or without hyphens, normalize it first, text.replace(/[{}-]/g, ''), and check the 32 digits with /^[0-9a-f]{32}$/i.
A regex says nothing about whether a UUID was generated properly or is unique; it only checks the spelling. The UUID Generator & Decoder makes and inspects them.