Regex for UUIDs: matching the 8-4-4-4-12 layout
A UUID pattern normally checks the 8-4-4-4-12 hexadecimal layout only. Restricting it to a specific version means pinning the first digit of the third group and the first of the fourth.
At a glance
- Built in preset
- UUID
- Preset 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}
- Preset flags
- g and i
- Checks
- the layout only, not the version or the variant
- Version nibble
- the first character of the third group
- Variant nibble
- the first character of the fourth group, 8 9 a or b
In detail
The layout is fixed and easy to state: eight hex digits, then three groups of four, then twelve, separated by hyphens. The preset says exactly that and nothing more, which makes it a good scraper. Running it over a log file pulls out every identifier regardless of which version generated it, and that is usually what you want when you are looking for one.
Two nibbles carry meaning. The first character of the third group is the version, so a version 4 identifier has a 4 there. The first character of the fourth group encodes the variant, and for the layout in normal use it is 8, 9, a or b. Pinning both turns a layout check into a check that the value really is a random version 4 identifier.
The distinction matters when the identifier is doing security work. If your system issues version 4 identifiers because they are unpredictable, accepting a version 1 identifier undermines that, since a version 1 value encodes a timestamp and a node address and is guessable. A stricter pattern is the cheapest way to reject one.
The preset carries no anchors, which is right for finding identifiers inside text and wrong for validating a field. Adding ^ and $ turns it into a validator, and while you are there the case insensitive flag is worth a thought too: the canonical form is lowercase, and accepting uppercase silently creates two spellings of the same key.
Examples
const uuid = /[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}/gi;
"ID: 550e8400-e29b-41d4-a716-446655440000 and 6ba7b810-9dad-11d1-80b4-00c04fd430c8"
.match(uuid);
// ["550e8400-e29b-41d4-a716-446655440000",
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8"]const v4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
v4.test("550e8400-e29b-41d4-a716-446655440000"); // true, version 4
v4.test("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); // false, version 1The 4 after the second hyphen is the version nibble and the [89ab] after the third is the variant.
Things that catch people out
- Without anchors the pattern reports success on any string that contains an identifier, so a form field validated with it accepts a whole sentence.
- The preset accepts every version, including the timestamp based version 1, whose values are considerably more predictable than a version 4.
- Accepting both cases creates two spellings of the same key. Normalise to lowercase before storing or comparing.
Try it: Regex Tester
Type a pattern and a test string, watch every match highlight as you go, read a plain English breakdown of each token, and check the numbered and named groups it captured.
Regex Tester
LOCAL · Browser-OnlyTest and debug regular expressions with live matching and highlights
Related Regex syntax
All regex syntax →Regex for hex colours: three, six and eight digit forms
The built in preset matches the three and six digit forms and rejects the four and eight digit ones with alpha. Here is the pattern that covers all four.
Regex for IPv4 addresses with real octet range checks
The naive four groups of digits pattern accepts 999.999.999.999. Here is the alternation that enforces 0 to 255, and the leading zero case it still allows.
{n}: matching exactly n repetitions
An exact count is the clearest quantifier there is, until it is applied to a group, at which point the capture keeps only the final iteration.
Regex for ISO dates: matching YYYY-MM-DD without fake days
The preset rejects month 13 and day 32 with two alternations, and still accepts 2026-02-31. No regex can check a calendar, so parse and compare.
Regex for phone numbers, and why strict ones lose customers
Phone formatting varies by country and by habit. The built in US preset does not even match the parenthesised form in its own sample, which is the lesson.
Regex to trim whitespace, collapse runs and drop blank lines
There is no preset for this one. Four short patterns cover trimming, collapsing, per line trimming and removing blank lines, and each has a different failure.
Tools for this
- Regex Tester Free online regex tester - test and debug regular expressions with live matching and highlights
- Regex Playground Regex playground with live match highlighting, named groups, find and replace, and shareable links