UUID Regex: Validate UUID Format in JavaScript and Python
- The standard UUID v4 regex is: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
- This pattern checks the 8-4-4-4-12 hyphen structure, the version-4 digit, and the variant bits.
- A looser "any UUID" regex skips version/variant checks: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
- JavaScript, Python, Go, Java, and PHP all support this pattern with minor syntax differences.
- Use strict UUID v4 regex for generated IDs you control; use the loose pattern for user input or external IDs.
Table of Contents
UUID validation fails silently — pass a malformed string as a primary key or API parameter and you get a confusing 404 or a cryptic database error instead of a clear message. The fix is a regex check at the boundary. This guide gives you the exact pattern for UUID v4, a looser variant for any UUID version, and copy-paste examples for the languages developers search for most.
The Standard UUID v4 Regex Pattern
UUID v4 has a fixed structure: 8-4-4-4-12 hexadecimal characters separated by hyphens. The version digit is always 4. The variant digit is 8, 9, a, or b.
Strict UUID v4 pattern:
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
Breaking it down:
^and$anchor the match to the full string[0-9a-f]{8}— 8 hex chars-hyphen[0-9a-f]{4}— 4 hex chars-hyphen4[0-9a-f]{3}— the4pins the version to v4-hyphen[89ab][0-9a-f]{3}— variant bits: first char must be 8, 9, a, or b-hyphen[0-9a-f]{12}— 12 hex chars- The
iflag makes it case-insensitive
Valid: 550e8400-e29b-41d4-a716-446655440000
Invalid: 550e8400-e29b-31d4-a716-446655440000 (version digit is 3, not 4)
Loose UUID Regex (Any Version)
If you are validating UUIDs from external systems — API responses, legacy databases, or user input — you may receive v1, v3, v5, or v7 UUIDs. Use the loose pattern:
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
This only checks the hyphen structure and hex characters — it does not enforce version or variant bits. It will pass any valid UUID regardless of version.
Trade-off: the loose pattern also passes some technically invalid UUIDs (e.g., all-zeros 00000000-0000-0000-0000-000000000000), which is usually fine for input validation but not for strict standards compliance.
Validate UUID in JavaScript
JavaScript function using the strict v4 pattern:
function isUUIDv4(str) {
const re = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return re.test(str);
}
console.log(isUUIDv4("550e8400-e29b-41d4-a716-446655440000")); // true
console.log(isUUIDv4("not-a-uuid")); // false
console.log(isUUIDv4("550e8400e29b41d4a716446655440000")); // false — missing hyphens
For TypeScript, add a type guard:
function isUUIDv4(value: string): value is string {
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
}
Express.js middleware example:
app.get("/items/:id", (req, res) => {
if (!isUUIDv4(req.params.id)) {
return res.status(400).json({ error: "Invalid ID format" });
}
// proceed
});
Sell Custom Apparel — We Handle Printing & Free Shipping
Validate UUID in Python
Python has two approaches: the built-in uuid module and a raw regex.
Using the uuid module (recommended):
import uuid
def is_valid_uuid_v4(val):
try:
obj = uuid.UUID(val, version=4)
except ValueError:
return False
return str(obj) == val.lower()
print(is_valid_uuid_v4("550e8400-e29b-41d4-a716-446655440000")) # True
print(is_valid_uuid_v4("not-a-uuid")) # False
The uuid.UUID constructor raises ValueError on bad format. Passing version=4 additionally checks the version and variant bits.
Using regex directly (no imports needed):
import re
UUID_V4_RE = re.compile(
r"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
re.IGNORECASE
)
def is_uuid_v4(val):
return bool(UUID_V4_RE.match(val))
Compile the pattern once at module level — do not recompile inside a loop.
UUID Regex in Go, Java, and PHP
Go:
package main
import (
"regexp"
"fmt"
)
var uuidV4Re = regexp.MustCompile(
`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`,
)
func isUUIDv4(s string) bool {
return uuidV4Re.MatchString(s)
}
fmt.Println(isUUIDv4("550e8400-e29b-41d4-a716-446655440000")) // true
Go tip: use MustCompile at package level so the regex compiles once at startup, not on every call.
Java:
import java.util.regex.Pattern;
Pattern UUID_PATTERN = Pattern.compile(
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
);
boolean isValid = UUID_PATTERN.matcher(input).matches();
Java alternative: UUID.fromString(input) throws IllegalArgumentException on bad format, but it accepts any UUID version — not just v4.
PHP:
function isUUIDv4(string $val): bool {
return (bool) preg_match(
"/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i",
$val
);
}
Common Validation Mistakes
Forgetting anchors — without ^ and $, the pattern matches UUIDs embedded inside longer strings. "prefix-550e8400-e29b-41d4-a716-446655440000-suffix" would pass. Always anchor.
Case sensitivity — UUIDs from crypto.randomUUID() are lowercase; UUIDs from Java or .NET may be uppercase. Always use the i flag or include both cases explicitly.
Not handling stripped format — some systems store UUIDs without hyphens: 550e8400e29b41d4a716446655440000. Your validator will fail these unless you normalize first:
function normalizeUUID(s) {
return s.replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/i,
"$1-$2-$3-$4-$5");
}
Validating too late — validate at the API boundary, not buried inside business logic. Fail fast with a clear 400 error.
Generate Valid UUIDs to Test Against
Test your regex against real UUID v4 output using the Cheetah UUID Generator — it produces one or ten RFC-compliant UUID v4 values instantly with one click. Copy a UUID, paste it into your validator, confirm the pattern passes. Then modify a character (change the 4 to a 3 in the version position) and confirm the strict pattern fails while the loose pattern passes. This two-step test confirms both patterns behave correctly.
Generate UUID v4 Values to Test Your Regex
Grab one or ten RFC-compliant UUID v4 strings from the Cheetah UUID Generator and paste them straight into your validator. One click, zero configuration.
Open Free UUID GeneratorFrequently Asked Questions
What is the regex for UUID v4?
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i — this enforces the 8-4-4-4-12 structure, version digit 4, and the variant nibble (8, 9, a, or b).
How do I validate a UUID in JavaScript without a library?
Use a one-liner: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(yourString). No imports needed.
Should I use the strict or loose UUID regex?
Strict (with version and variant checks) when you control UUID generation and know they are always v4. Loose (structure only) when you accept UUIDs from external sources that may use other versions.
Does the uuid module in Python validate format?
Yes. uuid.UUID(val, version=4) raises ValueError if the format is invalid or if it is not a version 4 UUID. This is more readable than raw regex and is the recommended approach in Python.
Why does my UUID regex fail on uppercase UUIDs?
Omitting the case-insensitive flag. Add the i flag (JavaScript, PHP, Go) or re.IGNORECASE (Python). UUID characters are hex so A-F are valid alongside a-f.

