UUID regex: copy-paste patterns that actually validate
The strict pattern below matches every standard UUID (v1–v8) and nothing else. Try any string against all four patterns live — testing runs in your browser.
By the Withuse team · Updated
Live tester
| Pattern | Match? |
|---|---|
| Strict RFC (v1–v8) valid version & variant digits required | ✅ match |
| v4 only random UUIDs only | ✅ match |
| Any layout (incl. NIL/MAX) 8-4-4-4-12 shape, version not checked | ✅ match |
| Braces tolerated accepts {GUID} registry style too | ✅ match |
| Detected version digit | 4 |
The four patterns
# 1. Strict RFC (v1–v8) — recommended default
^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ (flag: i)
# 2. v4 only
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ (flag: i)
# 3. Shape only — also matches NIL/MAX and future versions
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ (flag: i)
# 4. Braced GUID tolerated ({...} registry style)
^\{[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\}$|^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$Which to pick: #1 for user input, #3 if NIL UUIDs (00000000-…) are legal in your system, #2 when your API contract mandates v4, #4 when Windows-style GUIDs may arrive braced.
Usage per language
// JavaScript
const UUID_RE = /^[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_RE.test(input);
# Python — re.fullmatch avoids ^$ anchoring mistakes
import re
UUID_RE = 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_RE.fullmatch(text))
// Java — Pattern.CASE_INSENSITIVE
Pattern UUID_RE = Pattern.compile(
"[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}",
Pattern.CASE_INSENSITIVE);
UUID_RE.matcher(text).matches();
// Go — regexp is RE2; the same pattern works
var uuidRe = regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`)
uuidRe.MatchString(s)Common regex mistakes
- Forgetting anchors — without
^…$(orfullmatch),"xx550e8400-…-0000yy"passes. - Allowing version 0 or 9–f —
[0-9a-f]in the version slot accepts values no RFC version uses (unless you intend the shape-only pattern). - Missing the variant class — the fourth group must start with
[89ab]for standard UUIDs. - Case sensitivity — validate uppercase input too, or normalize with
toLowerCase()first.
If you need more than a boolean — version, timestamp, bytes — skip regex and use a parser: see Python and JavaScript guides. Structure details live in UUID length & format.
Frequently asked questions
What is the regex for a UUID?
For strict RFC validation use ^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ with the case-insensitive flag. It enforces three things at once: the 8-4-4-4-12 grouping, a version digit between 1 and 8 opening the third group, and a variant digit of 8, 9, a or b opening the fourth. Those last two checks are what separate a real validator from a shape check — a pattern using [0-9a-f] in the version position happily accepts values that no UUID specification can produce. Anchor with ^ and $ so a UUID buried inside a longer string does not pass, and remember that this pattern deliberately rejects the all-zero NIL UUID, whose version digit is 0.
Why does my UUID regex reject 00000000-0000-0000-0000-000000000000?
Because that is the NIL UUID, and its version digit is 0 while strict RFC patterns only accept 1 through 8. The same applies to the MAX UUID of all f characters, whose version digit is f. Both are legitimate special values defined by RFC 9562: NIL commonly represents an absent or not-yet-assigned identifier, and some systems store it deliberately rather than using a null column. If yours does, switch to the shape-only pattern that checks the 8-4-4-4-12 layout without inspecting the version and variant positions. The trade-off is that the looser pattern also accepts malformed values with impossible version digits, so use it only where you expect NIL or MAX to appear.
Should I validate UUIDs with regex or a parser?
Use a regular expression when you need nothing more than a boolean: filtering log lines, a quick form-input check, or a route parameter guard. Use your language's UUID parser whenever you will do something with the value afterwards, because it validates and parses in one step and hands you an object you can inspect for version, byte layout or, with v7, the embedded timestamp. Parsers are also more forgiving about input formatting, accepting hyphenless, braced and urn:uuid: forms that a strict pattern rejects — which is helpful for tolerant input handling and unhelpful if your API contract demands the exact canonical form. In that case pair the parser with a strict pattern.
Does the UUID regex need the case-insensitive flag?
In practice, yes. RFC 9562 makes lowercase the canonical output form but requires implementations to accept either case on input, and plenty of real systems emit uppercase — Microsoft tooling in particular, along with several database clients. A pattern written only with [0-9a-f] will silently reject those values, which usually surfaces as an intermittent bug when one upstream service changes. Add the i flag, or spell out [0-9a-fA-F] in every character class if your environment lacks flag support, as with some SQL CHECK constraint dialects. An alternative that avoids the question entirely is normalising input with toLowerCase() before matching, which also makes stored values consistent.
Need valid test data for your regex? Generate up to 1,000 UUIDs of any version with our free UUID generator.