What is a UUID Regex
There are two useful UUID patterns, and picking the wrong one is the usual reason a validator lets bad data through. The loose pattern only demands 32 hex digits in the 8-4-4-4-12 layout — it accepts a version nibble that no RFC defines. The strict pattern also constrains the version digit to 1-8 and the variant nibble to [89ab], which is what RFC 9562 actually specifies.
Both need anchors (^ and $) and the case-insensitive flag, otherwise a valid UUID embedded in a longer string will match and a truncated value in the middle of a sentence will look fine. Copy the pattern for your language below, or paste a value into the tester to see which pattern it satisfies.
How to
- Choose your language, then copy the pattern — each one is anchored and case-insensitive.
- Or paste values into the field on the left: each line is tested against the strict pattern.
- Use the table to see the detected version, which tells you whether the value is random (v4) or time-based (v7).
Use cases
- Input validation in a form or API handler, where a bad identifier should be rejected before it reaches the database.
- Log and CSV parsing, pulling identifiers out of text without accidentally matching a 32-character hash.
- Database constraints, when a column has to stay text but must never contain anything but a UUID.
Compare UUID Regex with other formats
| Option | When to use |
|---|---|
Strict pattern | Rejects anything whose version or variant nibble is not RFC-defined. Use it for validation. |
Loose pattern | Only checks the 32-hex layout. Faster, but it accepts impossible version numbers. |
Existence check | No regex can tell you whether an identifier was ever issued; that needs a lookup. |
Code examples
JavaScript
// Strict, anchored, case-insensitive
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// Loose: layout only
const LOOSE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
// Grab every UUID inside a longer string
'ids ' + '550e8400-e29b-41d4-a716-446655440000'.repeat(2)
.match(/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/gi);
Python
import re
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)
LOOSE = re.compile(r'^[0-9a-f]{8}(-?[0-9a-f]{4}){3}-?[0-9a-f]{12}$', re.I)
bool(STRICT.match('550e8400-e29b-41d4-a716-446655440000')) # True
bool(STRICT.match('550e8400-e29b-01d4-a716-446655440000')) # False
Java
import java.util.regex.Pattern;
Pattern STRICT = Pattern.compile(
"^[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}$");
STRICT.matcher(value).matches(); // true / false
PHP
<?php
$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';
if (preg_match($strict, $value) === 1) {
// well-formed UUID
}
Go
package main
import "regexp"
var strict = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
strict.MatchString(value)
MySQL
-- MySQL 8 supports REGEXP in a CHECK constraint
ALTER TABLE items ADD CONSTRAINT chk_uuid CHECK (
id REGEXP '^[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}$'
);
SELECT UUID(); -- v1
SELECT UUID_TO_BIN(UUID(), 1); -- v1 bytes, time part swapped for sorting
PostgreSQL
-- Regex input check
SELECT '550e8400-e29b-41d4-a716-446655440000'
~ '^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$';
-- Better: use the native type and let PostgreSQL 18 report the details
SELECT uuid_extract_version('018f3b7a-9c2d-7f41-a1b2-c3d4e5f60718'); -- 7
Frequently asked questions
Why does my regex accept UUIDs that are clearly wrong?
Almost always because the version and variant nibbles were left as [0-9a-f] — the loose pattern. Add [1-8] for the 13th character and [89ab] for the 17th and impossible values start being rejected.
Which pattern should I use?
Strict for input validation and database constraints, loose only when you deliberately want to find UUID-shaped tokens in free text where a non-standard variant is plausible.
Does matching prove the UUID is real?
No. A regex can only inspect the string. Whether the identifier exists in your system is a separate question that requires a lookup; see the UUID validator for the format-level answer.