UUID Regex Patterns (Strict, Loose and Version-Specific)
By SimpleTools24Published 3 min read
A simple UUID regex checks for 32 hexadecimal digits in the 8-4-4-4-12 pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ with case-insensitive matching. A stricter pattern also checks that the version digit (13th) is 1–8 and the variant digit (17th) is 8, 9, a or b, as RFC 9562 requires for standard UUIDs. Choose the strictness based on what your system needs to accept.
In this guide
The Patterns
1. Loose Format Check
Accepts any hex value in UUID shape, including nil and max UUIDs and non-standard variants:
^[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}$Use it when you just need to know the string looks like a UUID.
2. Strict RFC 9562 (Versions 1–8)
Requires a defined version and the standard variant:
^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$Apply it case-insensitively (the i flag), since RFC 9562 allows upper or lower case. This rejects the nil UUID (all zeros) and max UUID (all f), which you may want to allow separately.
3. Version 4 Only
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$4. Version 7 Only
^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$Be careful with version-specific patterns: if your system starts generating v7 instead of v4, a v4-only check will reject perfectly good IDs. UUID v4 vs UUID v7 discusses that migration.
5. Optional Braces and Hyphens (GUID-Friendly)
Accepts {...} braces and the 32-digit compact form:
^\{?[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\}?$This is permissive: it also matches a brace on one side only, or hyphens in some positions but not others. If that matters, normalise the input (strip braces and hyphens, then check 32 hex digits) instead of relying on one regex.
What Each Part Checks
| Regex part | Matches | Meaning |
|---|---|---|
[0-9a-f]{8} | First group | time_low or random bits |
[0-9a-f]{4} | Second group | time_mid or random bits |
[1-8][0-9a-f]{3} | Third group | Version digit 1–8, then 3 hex digits |
[89ab][0-9a-f]{3} | Fourth group | Variant 10xx, then 3 hex digits |
[0-9a-f]{12} | Fifth group | node or random bits |
UUID format explained describes these fields in detail.
Using the Patterns in Code
const UUID_STRICT = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_STRICT.test('9b2c1f7e-5d3a-4c8b-a1e2-7f6d0c9b3a54'); // trueimport re
UUID_STRICT = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$', re.I)
bool(UUID_STRICT.match('9b2c1f7e-5d3a-4c8b-a1e2-7f6d0c9b3a54')) # TrueIn Python, prefer re.fullmatch or keep the anchors; re.match only anchors at the start. For alternatives to regex, such as parsing with uuid.UUID(), see how to validate a UUID in JavaScript and Python.
Common Regex Mistakes
- Missing anchors. Without
^and$, the pattern matches a UUID inside a longer string, such asabc9b2c1f7e-...xyz. - Forgetting case-insensitivity. Uppercase GUIDs from Microsoft tools will fail a lowercase-only pattern.
- Too strict for real data. Some systems produce values with non-standard versions or variants. Decide whether to accept them.
- Not trimming input. Trailing spaces or newlines from copy-paste make valid UUIDs fail; trim first. Why a UUID is invalid lists more input problems.
Testing Values Quickly
Before baking a pattern into your code, check a sample of real IDs from your system. The UUID validator accepts up to 1,000 lines, recognises standard, compact, braced and urn:uuid: forms, and reports each value's version, variant and canonical form, so you can see exactly what your data contains. The UUID decoder goes further for a single value, showing embedded timestamps for time-based versions.
Choosing the Right Pattern
| Situation | Pattern to use |
|---|---|
| Routing, e.g. matching /orders/{id} | Loose format check |
| Public API input | Strict RFC 9562, case-insensitive |
| System that only ever issues v4 | Strict, but consider allowing future versions |
| Importing data from Microsoft tools | Normalise braces first, then strict |
| Accepting nil UUID as "unset" | Strict plus an explicit nil check |
Regex in Databases
You can use the same patterns for data audits:
-- PostgreSQL: find text values that don't look like UUIDs
SELECT id_text
FROM imported_rows
WHERE id_text !~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$';!~* means "does not match, case-insensitive". In a native uuid column this isn't needed, because PostgreSQL rejects invalid values on insert, but it's handy for checking text columns before converting them.
Regex vs Parsing
A regex only checks shape. A UUID parser such as Python's uuid.UUID() or .NET's Guid.TryParse() also converts the value into a proper type you can compare and store. Many teams use a regex at the edge for fast rejection and a parser where the value is used.
Frequently Asked Questions
What is the regex for a UUID v4?
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ with case-insensitive matching.
Should I use a regex or a UUID parser?
A parser is usually more robust. A regex is fine for quick format checks, form validation and routing.
Does the strict regex accept the nil UUID?
No. Add an explicit check for 00000000-0000-0000-0000-000000000000 if you need it.
Are uppercase UUIDs valid?
Yes. RFC 9562 allows uppercase, lowercase or mixed hex digits.
Summary
Use the loose pattern for shape, the strict pattern for standard versions and variants, and version-specific patterns only when you truly need them. Always anchor, ignore case and trim input.
Related tools
Sources
- RFC 9562 – Universally Unique IDentifiers (UUIDs), Section 4 – IETF (opens in a new tab)
Related articles
- Validate a UUID in CodePractical validation in JavaScript and Python, plus notes for Java and C#, and how strict your checks should be.
- UUID Format ExplainedThe 8-4-4-4-12 layout, where the version and variant live, and the text forms systems accept.
- Why Is My UUID Invalid?The usual reasons a UUID gets rejected, from invisible whitespace to truncation, and how to fix each.