397

How to check if variable contains valid UUID/GUID identifier?

I'm currently interested only in validating types 1 and 4, but it should not be a limitation to your answers.

DeeZone
  • 770
  • 7
  • 16
Marek Sebera
  • 39,650
  • 37
  • 158
  • 244
  • in string format, not hex, not bin, or I don't know what do you ask for – Marek Sebera Oct 26 '11 at 16:44
  • If you cannot exclude variables containing a chain of 32 consecutive hex digits (without grouping), have a look at [my answer](http://stackoverflow.com/a/29742838/2932052) – Wolf Apr 20 '15 at 08:38
  • Might be helpful: https://www.npmjs.com/package/uuid-validate – Ben Jul 18 '20 at 18:13

18 Answers18

573

Currently, UUID's are as specified in RFC4122. An often neglected edge case is the NIL UUID, noted here. The following regex takes this into account and will return a match for a NIL UUID. See below for a UUID which only accepts non-NIL UUIDs. Both of these solutions are for versions 1 to 5 (see the first character of the third block).

Therefore to validate a UUID...

/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i

...ensures you have a canonically formatted UUID that is Version 1 through 5 and is the appropriate Variant as per RFC4122.

NOTE: Braces { and } are not canonical. They are an artifact of some systems and usages.

Easy to modify the above regex to meet the requirements of the original question.

HINT: regex group/captures

To avoid matching NIL UUID:

/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
Community
  • 1
  • 1
Gambol
  • 5,754
  • 1
  • 13
  • 2
  • 2
    I think [1-5][0-9a-f]{3} is incorrect. I have a valid UUID which has "b06a" in that part, and this was failing for me. – Felipe Brahm Jun 11 '14 at 01:25
  • 1
    @FelipeBrahm, [1-5] is right according to RFC, that 4 bits indicate the version, and there are only 5 versions. – rvignacio Jun 20 '14 at 21:28
  • 1
    749d0000-0194-1005-2e05-08d61613bf2f fails for me in the fiddle – robs Sep 09 '18 at 05:47
  • 4
    Out of curiosity, (why) wouldn't the following be valid too: `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}` – tjeerdnet Sep 11 '19 at 08:46
  • @mshaffer the line 21, second regex definition seems incorrect, the first one is ok - validates both empty and robs regex, which second def fails to do. – ignacy130 Oct 01 '19 at 12:07
  • 534b4242-627d-87f9-2977-44000f6dd830 fails – jgozal Sep 02 '22 at 12:53
  • 1
    @jgozal that's because that UUID is a pseudo-UUID, and isn't following the standards. `87f9` should only ever start with a `[1-5]`, and `2977` should only ever start with `[ab89]`. See here for a good explanation: https://www.nearform.com/blog/new-crypto-capabilities-in-node-js/ – NeoNexus DeMortis Dec 06 '22 at 01:03
90

If you want to check or validate a specific UUID version, here are the corresponding regexes.

Note that the only difference is the version number, which is explained in 4.1.3. Version chapter of UUID 4122 RFC.

The version number is the first character of the third group : [VERSION_NUMBER][0-9A-F]{3} :

  • UUID v1 :

    /^[0-9A-F]{8}-[0-9A-F]{4}-[1][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
    
  • UUID v2 :

    /^[0-9A-F]{8}-[0-9A-F]{4}-[2][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
    
  • UUID v3 :

    /^[0-9A-F]{8}-[0-9A-F]{4}-[3][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
    
  • 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
    
  • UUID v5 :

    /^[0-9A-F]{8}-[0-9A-F]{4}-[5][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
    
Ivan Gabriele
  • 6,433
  • 5
  • 39
  • 60
  • 1
    Interesting, I have a Guid created by C# that doesn't match any of these because it has a 'c' where the regex is expecting 8,9,A, or B. – ScubaSteve Mar 26 '21 at 14:51
  • @ScubaSteve https://stackoverflow.com/questions/246930/is-there-any-difference-between-a-guid-and-a-uuid – jcollum Sep 26 '22 at 17:25
78

regex to the rescue

/^[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}$/.test('01234567-9ABC-DEF0-1234-56789ABCDEF0');

or with brackets

/^\{?[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}‌​\}?$/
Marek Sebera
  • 39,650
  • 37
  • 158
  • 244
ryanb
  • 934
  • 7
  • 4
  • 3
    or if you might have brackets: /^\{?[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}\}?$/.test('01234567-9ABC-DEF0-1234-56789ABCDEF0'); – ryanb Oct 26 '11 at 16:47
  • This isn't quite correct. it misses that [1-5] (version) starts the 3rd block and [89AB] (variant) starts the 4th block. [Gambol's answer](http://stackoverflow.com/a/13653180/2932052) does it right. – Wolf Apr 20 '15 at 07:46
  • 11
    More concise version (ignoring brackets): `/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i` – c24w Oct 16 '15 at 13:56
56

If you are using Node.js for development, it is recommended to use a package called Validator. It includes all the regexes required to validate different versions of UUID's plus you get various other functions for validation.

Here is the npm link: Validator

var a = 'd3aa88e2-c754-41e0-8ba6-4198a34aa0a2'
v.isUUID(a)
true
v.isUUID('abc')
false
v.isNull(a)
false
Marek Sebera
  • 39,650
  • 37
  • 158
  • 244
Neeraj Sharma
  • 1,067
  • 7
  • 14
  • 1
    Interesting, but it looks like it expects hyphens? [Here are the four regexes it's currently using](https://github.com/chriso/validator.js/blob/ebcca98232399b8404ca6b0ec842ab4596329d58/validator.js#L60) -- `/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i` *and/or* `/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i` *and/or* `/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i` *and/or* `/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i` – ruffin Feb 20 '16 at 18:20
  • 1
    Validator only supports UUID v3-5 not v1 – peteb Jun 07 '16 at 19:46
41

If you use the uuid package, this package brings a boolean validation function where it tells you if a uuid is valid or not.

Example:

import { validate as isValidUUID } from 'uuid';

if (!isValidUUID(tx.originId)) {
  return Promise.reject('Invalid OriginID');
}
configbug
  • 746
  • 12
  • 19
25

thanks to @usertatha with some modification

function isUUID ( uuid ) {
    let s = "" + uuid;

    s = s.match('^[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}$');
    if (s === null) {
      return false;
    }
    return true;
}

Souhaieb
  • 559
  • 8
  • 12
15

Beside Gambol's answer that will do the job in nearly all cases, all answers given so far missed that the grouped formatting (8-4-4-4-12) is not mandatory to encode GUIDs in text. It's used extremely often but obviously also a plain chain of 32 hexadecimal digits can be valid.[1] regexenh:

/^[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$/i

[1] The question is about checking variables, so we should include the user-unfriendly form as well.

Community
  • 1
  • 1
Wolf
  • 9,679
  • 7
  • 62
  • 108
  • This one is my fave. Even better `{?[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}}?` – mike nelson Aug 09 '15 at 10:05
  • 1
    If you use RFC4122 as your guide, you must have the hyphens. Some other sources, such as Microsoft may use hyphen-less GUIDs in some places. If this answer wants to discuss checking VARIABLES for a valid 128bit value, there are infinite ways to to encode a 128 bit value in variables. This answer only addresses one variable encoding, of 32 hex chars in a string, which is not an RFC4122 encoding. I'm sad I had to research if the hyphens are optional. Per RFC4122, they are not. – Cameron Jan 18 '22 at 23:30
11

All type-specific regexes posted so far are failing on the "type 0" Nil UUID, defined in 4.1.7 of the RFC as:

The nil UUID is special form of UUID that is specified to have all 128 bits set to zero: 00000000-0000-0000-0000-000000000000

To modify Wolf's answer:

/^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-5][0-9a-f]{3}-?[089ab][0-9a-f]{3}-?[0-9a-f]{12}$/i

Or, to properly exclude a "type 0" without all zeros, we have the following (thanks to Luke):

/^(?:[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a‌​-f]{3}-?[0-9a-f]{12}‌​|00000000-0000-0000-‌​0000-000000000000)$/‌​i
Evan Edwards
  • 111
  • 1
  • 5
  • First UUID segment of the nil UUID should have 8 zeroes, not 7. The regex provided did not validate it with 7. – Rich Seviora May 18 '16 at 20:59
  • 2
    Yours looks nicer but allows some invalid UUIDs eg: `abcdef00-0000-0000-0000-000000000000` would match your regex. This regex will match valid UUIDs, including the nil: `/^(?:[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i` – Luke Nov 15 '17 at 17:47
8

if you use the uuid package, you can import the validate and pass the id into it

const { v4: uuidv4, validate } = require('uuid');

const { id } = request.params;
validate(id) ? true : false;
wellington
  • 81
  • 1
  • 2
4

A slightly modified version of the above answers written in a more concise way. This will validate any GUID with hyphens (however easily modified to make hyphens optional). This will also support upper and lower case characters which has become the convention regardless of the specification:

/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i

The key here is the repeating part below

(([0-9a-fA-F]{4}\-){3})

Which simply repeats the 4 char patterns 3 times

James Morrison
  • 1,954
  • 2
  • 21
  • 48
4

I think Gambol's answer is almost perfect, but it misinterprets the RFC 4122 § 4.1.1. Variant section a bit.

It covers Variant-1 UUIDs (10xx = 8..b), but does not cover Variant-0 (0xxx = 0..7) and Variant-2 (110x = c..d) variants which are reserved for backward compatibility, so they are technically valid UUIDs. Variant-4 (111x = e..f) is indeed reserved for future use, so they are not valid currently.

Also, 0 type is not valid, that "digit" is only allowed to be 0 if it's a NIL UUID (like mentioned in Evan's answer).

So I think the most accurate regex that complies with current RFC 4122 specification is (including hyphens):

/^([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-d][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i
                            ^                ^^^^^^
                    (0 type is not valid)  (only e..f variant digit is invalid currently)
Community
  • 1
  • 1
B. Zoli
  • 41
  • 3
4

If someone is using yup , JavaScript schema validator library, This functionality can be achieved with below code.

const schema = yup.object().shape({
   uuid: yup.string().uuid()
 });
 const isValid = schema.isValidSync({uuid:"string"});
NS23
  • 684
  • 5
  • 14
2

Use the .match() method to check whether String is UUID.

public boolean isUUID(String s){
    return s.match("^[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}$");
}
DeeZone
  • 770
  • 7
  • 16
userTatha
  • 103
  • 1
2

A good way to do it in Node is to use the ajv package (https://github.com/epoberezkin/ajv).

const Ajv = require('ajv');
const ajv = new Ajv({ allErrors: true, useDefaults: true, verbose: true });
const uuidSchema = { type: 'string', format: 'uuid' };
ajv.validate(uuidSchema, 'bogus'); // returns false
ajv.validate(uuidSchema, 'd42a8273-a4fe-4eb2-b4ee-c1fc57eb9865'); // returns true with v4 GUID
ajv.validate(uuidSchema, '892717ce-3bd8-11ea-b77f-2e728ce88125'); // returns true with a v1 GUID
blackcatweb
  • 1,003
  • 1
  • 10
  • 11
1

Versions 1 to 5, without using a multi-version regex when version is omitted.

const uuid_patterns = {
  1: /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  2: /^[0-9A-F]{8}-[0-9A-F]{4}-2[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
};

const isUUID = (input, version) => {    
    if(typeof input === "string"){
        if(Object.keys(uuid_patterns).includes(typeof version === "string" ? version : String(version))){
            return uuid_patterns[version].test(input);
        } else {
            return Object.values(uuid_patterns).some(pattern => pattern.test(input));
        }
    }
    return false;
}

// Testing
let valid = [
    'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
    'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
    'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
];

let invalid = [
    '',
    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',
    'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',
    'A987FBC94BED3078CF079141BA07C9F3',
    '934859',
    '987FBC9-4BED-3078-CF07A-9141BA07C9F3',
    'AAAAAAAA-1111-1111-AAAG-111111111111',
];

valid.forEach(test => console.log("Valid case, result: "+isUUID(test)));
invalid.forEach(test => console.log("Invalid case, result: "+isUUID(test)));
Benjamin
  • 45
  • 7
0

I added a UUID validator to Apache Commons Validator. It's not yet been merged, but you can vote for it here:

https://github.com/apache/commons-validator/pull/68

Daniel Heid
  • 199
  • 1
  • 5
0

I have this function, but it's essentially the same as the accepted answer.

export default function isUuid(uuid: string, isNullable: boolean = false): boolean {
    return isNullable
        ? /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid)
        : /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
}
s3c
  • 1,481
  • 19
  • 28
-3

I think a better way is using the static method fromString to avoid those regular expressions.

    id = UUID.randomUUID();
    UUID uuid = UUID.fromString(id.toString());
    Assert.assertEquals(id.toString(), uuid.toString());

On the other hand

   UUID uuidFalse = UUID.fromString("x");

throws java.lang.IllegalArgumentException: Invalid UUID string: x

slfan
  • 8,950
  • 115
  • 65
  • 78