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.

Live tester

PatternMatch?
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 digit4

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

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.

References