How to create a GUID / UUID

2,499,503

Solution 1

UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier), according to RFC 4122, are identifiers designed to provide certain uniqueness guarantees.

While it is possible to implement RFC-compliant UUIDs in a few lines of JavaScript code (e.g., see @broofa's answer, below) there are several common pitfalls:

  • Invalid id format (UUIDs must be of the form "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", where x is one of [0-9, a-f] M is one of [1-5], and N is [8, 9, a, or b]
  • Use of a low-quality source of randomness (such as Math.random)

Thus, developers writing code for production environments are encouraged to use a rigorous, well-maintained implementation such as the uuid module.

Solution 2

[Edited 2021-10-16 to reflect latest best-practices for producing RFC4122-compliant UUIDs]

Most readers here will want to use the uuid module. It is well-tested and supported.

The crypto.randomUUID() function is an emerging standard that is supported in Node.js and an increasing number of browsers.

If neither of those work for you, there is this method (based on the original answer to this question):

function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );
}

console.log(uuidv4());

Note: The use of any UUID generator that relies on Math.random() is strongly discouraged (including snippets featured in previous versions of this answer) for reasons best-explained here. TL;DR: Math.random()-based solutions do not provide good uniqueness guarantees.

Solution 3

I really like how clean Broofa's answer is, but it's unfortunate that poor implementations of Math.random leave the chance for collision.

Here's a similar RFC4122 version 4 compliant solution that solves that issue by offsetting the first 13 hex numbers by a hex portion of the timestamp, and once depleted offsets by a hex portion of the microseconds since pageload. That way, even if Math.random is on the same seed, both clients would have to generate the UUID the exact same number of microseconds since pageload (if high-perfomance time is supported) AND at the exact same millisecond (or 10,000+ years later) to get the same UUID:

function generateUUID() { // Public Domain/MIT
    var d = new Date().getTime();//Timestamp
    var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16;//random number between 0 and 16
        if(d > 0){//Use timestamp until depleted
            r = (d + r)%16 | 0;
            d = Math.floor(d/16);
        } else {//Use microseconds since page-load if supported
            r = (d2 + r)%16 | 0;
            d2 = Math.floor(d2/16);
        }
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}

var onClick = function(){
    document.getElementById('uuid').textContent = generateUUID();
}
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID" onclick="onClick();">Generate UUID</button>

Here's a fiddle to test.


Modernized snippet for ES6

const generateUUID = () => {
  let
    d = new Date().getTime(),
    d2 = (performance && performance.now && (performance.now() * 1000)) || 0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    let r = Math.random() * 16;
    if (d > 0) {
      r = (d + r) % 16 | 0;
      d = Math.floor(d / 16);
    } else {
      r = (d2 + r) % 16 | 0;
      d2 = Math.floor(d2 / 16);
    }
    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
  });
};

const onClick = (e) => document.getElementById('uuid').textContent = generateUUID();

document.getElementById('generateUUID').addEventListener('click', onClick);

onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID">Generate UUID</button>

Solution 4

broofa's answer is pretty slick, indeed - impressively clever, really... RFC4122 compliant, somewhat readable, and compact. Awesome!

But if you're looking at that regular expression, those many replace() callbacks, toString()'s and Math.random() function calls (where he's only using four bits of the result and wasting the rest), you may start to wonder about performance. Indeed, joelpt even decided to toss out an RFC for generic GUID speed with generateQuickGUID.

But, can we get speed and RFC compliance? I say, YES! Can we maintain readability? Well... Not really, but it's easy if you follow along.

But first, my results, compared to broofa, guid (the accepted answer), and the non-rfc-compliant generateQuickGuid:

                  Desktop   Android
           broofa: 1617ms   12869ms
               e1:  636ms    5778ms
               e2:  606ms    4754ms
               e3:  364ms    3003ms
               e4:  329ms    2015ms
               e5:  147ms    1156ms
               e6:  146ms    1035ms
               e7:  105ms     726ms
             guid:  962ms   10762ms
generateQuickGuid:  292ms    2961ms
  - Note: 500k iterations, results will vary by browser/CPU.

So by my 6th iteration of optimizations, I beat the most popular answer by over 12 times, the accepted answer by over 9 times, and the fast-non-compliant answer by 2-3 times. And I'm still RFC 4122 compliant.

Interested in how? I've put the full source on http://jsfiddle.net/jcward/7hyaC/3/ and on https://jsben.ch/xczxS

For an explanation, let's start with broofa's code:

function broofa() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

console.log(broofa())

So it replaces x with any random hexadecimal digit, y with random data (except forcing the top two bits to 10 per the RFC spec), and the regex doesn't match the - or 4 characters, so he doesn't have to deal with them. Very, very slick.

The first thing to know is that function calls are expensive, as are regular expressions (though he only uses 1, it has 32 callbacks, one for each match, and in each of the 32 callbacks it calls Math.random() and v.toString(16)).

The first step toward performance is to eliminate the RegEx and its callback functions and use a simple loop instead. This means we have to deal with the - and 4 characters whereas broofa did not. Also, note that we can use String Array indexing to keep his slick String template architecture:

function e1() {
    var u='',i=0;
    while(i++<36) {
        var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:v.toString(16)
    }
    return u;
}

console.log(e1())

Basically, the same inner logic, except we check for - or 4, and using a while loop (instead of replace() callbacks) gets us an almost 3X improvement!

The next step is a small one on the desktop but makes a decent difference on mobile. Let's make fewer Math.random() calls and utilize all those random bits instead of throwing 87% of them away with a random buffer that gets shifted out each iteration. Let's also move that template definition out of the loop, just in case it helps:

function e2() {
    var u='',m='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<36) {
        var c=m[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:v.toString(16);rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
    }
    return u
}

console.log(e2())

This saves us 10-30% depending on platform. Not bad. But the next big step gets rid of the toString function calls altogether with an optimization classic - the look-up table. A simple 16-element lookup table will perform the job of toString(16) in much less time:

function e3() {
    var h='0123456789abcdef';
    var k='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
    /* same as e4() below */
}
function e4() {
    var h=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
    var k=['x','x','x','x','x','x','x','x','-','x','x','x','x','-','4','x','x','x','-','y','x','x','x','-','x','x','x','x','x','x','x','x','x','x','x','x'];
    var u='',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<36) {
        var c=k[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:h[v];rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
    }
    return u
}

console.log(e4())

The next optimization is another classic. Since we're only handling four bits of output in each loop iteration, let's cut the number of loops in half and process eight bits in each iteration. This is tricky since we still have to handle the RFC compliant bit positions, but it's not too hard. We then have to make a larger lookup table (16x16, or 256) to store 0x00 - 0xFF, and we build it only once, outside the e5() function.

var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e5() {
    var k=['x','x','x','x','-','x','x','-','4','x','-','y','x','-','x','x','x','x','x','x'];
    var u='',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<20) {
        var c=k[i-1],r=rb&0xff,v=c=='x'?r:(c=='y'?(r&0x3f|0x80):(r&0xf|0x40));
        u+=(c=='-')?c:lut[v];rb=i%4==0?Math.random()*0xffffffff|0:rb>>8
    }
    return u
}

console.log(e5())

I tried an e6() that processes 16-bits at a time, still using the 256-element LUT, and it showed the diminishing returns of optimization. Though it had fewer iterations, the inner logic was complicated by the increased processing, and it performed the same on desktop, and only ~10% faster on mobile.

The final optimization technique to apply - unroll the loop. Since we're looping a fixed number of times, we can technically write this all out by hand. I tried this once with a single random variable, r, that I kept reassigning, and performance tanked. But with four variables assigned random data up front, then using the lookup table, and applying the proper RFC bits, this version smokes them all:

var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e7()
{
    var d0 = Math.random()*0xffffffff|0;
    var d1 = Math.random()*0xffffffff|0;
    var d2 = Math.random()*0xffffffff|0;
    var d3 = Math.random()*0xffffffff|0;
    return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+
    lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+
    lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+
    lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];
}

console.log(e7())

Modualized: http://jcward.com/UUID.js - UUID.generate()

The funny thing is, generating 16 bytes of random data is the easy part. The whole trick is expressing it in string format with RFC compliance, and it's most tightly accomplished with 16 bytes of random data, an unrolled loop and lookup table.

I hope my logic is correct -- it's very easy to make a mistake in this kind of tedious bit work. But the outputs look good to me. I hope you enjoyed this mad ride through code optimization!

Be advised: my primary goal was to show and teach potential optimization strategies. Other answers cover important topics such as collisions and truly random numbers, which are important for generating good UUIDs.

Solution 5

Use:

let uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);

document.getElementById("unique").innerHTML =
  Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
<div id="unique">
</div>

If IDs are generated more than 1 millisecond apart, they are 100% unique.

If two IDs are generated at shorter intervals, and assuming that the random method is truly random, this would generate IDs that are 99.99999999999999% likely to be globally unique (collision in 1 of 10^15).

You can increase this number by adding more digits, but to generate 100% unique IDs you will need to use a global counter.

If you need RFC compatibility, this formatting will pass as a valid version 4 GUID:

let u = Date.now().toString(16) + Math.random().toString(16) + '0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');

let u = Date.now().toString(16)+Math.random().toString(16)+'0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');
document.getElementById("unique").innerHTML = guid;
<div id="unique">
</div>

The above code follow the intention, but not the letter of the RFC. Among other discrepancies it's a few random digits short. (Add more random digits if you need it) The upside is that this is really fast :) You can test validity of your GUID here

Share:
2,499,503
Jason Cohen
Author by

Jason Cohen

I'm the founder of WP Engine and Smart Bear Software. I blog regularly about running a bootstrapped software company including marketing, sales, programming, product development, and life in general. Blog: Startups + Marketing + Geekery Twitter: @asmartbear

Updated on April 05, 2022

Comments

  • Jason Cohen
    Jason Cohen about 2 years

    I'm trying to create globally-unique identifiers in JavaScript. I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc.

    The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.

    • AnthonyWJones
      AnthonyWJones over 15 years
      GUIDs when repesented as as strings are at least 36 and no more than 38 characters in length and match the pattern ^\{?[a-zA-Z0-9]{36}?\}$ and hence are always ascii.
    • George V. Reilly
      George V. Reilly about 14 years
      David Bau provides a much better, seedable random number generator at davidbau.com/archives/2010/01/30/… I wrote up a slightly different approach to generating UUIDs at blogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.h‌​tml
    • Abhishek
      Abhishek over 10 years
      Weird that no one has mentioned this yet but for completeness, there's a plethora of guid generators on npm I'm willing to bet most of them work in browser too.
    • dors
      dors over 3 years
      If anyone wants more options like different versions of the uuid and non standard guid support, REST based uuid generation services like these [fungenerators.com/api/uuid ] are an attractive option too.
    • smallscript
      smallscript over 3 years
      Some 12 years later with BigInt and ES6 classes, other techniques that yield rates of 500,000 uuid/sec can be done. See reference
    • TommyAutoMagically
      TommyAutoMagically over 2 years
      As others have mentioned, if you're only generating a small number of uuids in a browser, just use URL.createObjectURL(new Blob()).substr(-36). (Excellent browser support, too). (To avoid memory leakage, call URL.revokeObjectURL(url))
  • ochameau
    ochameau over 15 years
    Note that this isn't a GUID in the technical sense, because it does nothing to guarantee uniqueness. That may or may not matter depending on your application.
  • Jason DeFontes
    Jason DeFontes over 15 years
    Actually, the RFC allows for UUIDs that are created from random numbers. You just have to twiddle a couple of bits to identify it as such. See section 4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers: rfc-archive.org/getrfc.php?rfc=4122
  • Brandon DuRette
    Brandon DuRette over 15 years
    A quick note about performance. This solution creates 36 strings total to get a single result. If performance is critical, consider creating an array and joining as recommended by: tinyurl.com/y37xtx Further research indicates it may not matter, so YMMV: tinyurl.com/3l7945
  • devios1
    devios1 about 12 years
    Bear in mind, new Date().getTime() is not updated every millisecond. I'm not sure how this affects the expected randomness of your algorithm.
  • Cam Jackson
    Cam Jackson over 11 years
    Surely the answer to @Muxa's question is 'no'? It's never truly safe to trust something that came from the client. I guess it depends on how likely your users are to bring up a javascript console and manually change the variable so to something they want. Or they could just POST you back the id that they want. It would also depend on whether the user picking their own ID is going to cause vulnerabilities. Either way, if it's a random number ID that's going into a table, I would probably be generating it server-side, so that I know I have control over the process.
  • broofa
    broofa over 11 years
    @DrewNoakes - UUIDs aren't just a string of completely random #'s. The "4" is the uuid version (4 = "random"). The "y" marks where the uuid variant (field layout, basically) needs to be embedded. See sections 4.1.1 and 4.1.3 of ietf.org/rfc/rfc4122.txt for more info.
  • MgSam
    MgSam about 11 years
    You should declare the array size beforehand rather than sizing it dynamically as you build the GUID. var s = new Array(36);
  • John Velonis
    John Velonis about 11 years
    I think there's a very minor bug in the line that sets bits bits 6-7 of the clock_seq_hi_and_reserved to 01. Since s[19] is a character '0'..'f' and not an int 0x0..0xf, (s[19] & 0x3) | 0x8 will not be randomly distributed -- it will tend to produce more '9's and fewer 'b's. This only makes a difference if you care about the random distribution for some reason.
  • JLRishe
    JLRishe over 10 years
    This implementation is incorrect. Certain characters of the GUID require special treatment (e.g. the 13th digit needs to be the number 4).
  • SavoryBytes
    SavoryBytes about 10 years
    performance.now would be even better. Unlike Date.now, the timestamps returned by performance.now() are not limited to one-millisecond resolution. Instead, they represent times as floating-point numbers with up to microsecond precision. Also unlike Date.now, the values returned by performance.now() always increase at a constant rate, independent of the system clock which might be adjusted manually or skewed by software such as the Network Time Protocol.
  • Sebastian
    Sebastian about 10 years
    What is bothering about all answers is that it seems ok for JavaScript to store the GUID as a string. Your answer at least tackles the much more efficient storage using a Uint16Array. The toString function should be using the binary representation in an JavaScript object
  • Dave
    Dave almost 9 years
    This code still contains a couple of errors: the Math.random()*0xFFFFFFFF lines should be Math.random()*0x100000000 for full randomness, and >>>0 should be used instead of |0 to keep the values unsigned (though with the current code I think it gets away OK even though they are signed). Finally it would be a very good idea these days to use window.crypto.getRandomValues if available, and fall-back to Math.random only if absolutely necessary. Math.random may well have less than 128 bits of entropy, in which case this would be more vulnerable to collisions than necessary.
  • humanityANDpeace
    humanityANDpeace over 7 years
    note that the first version, the one ` window.crypto.getRandomValues, does not keep the Version 4 UUIDs format defined by RFC 4122. That is instead of xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` it yields xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
  • broofa
    broofa almost 7 years
    Regarding uniqueness, it's worth noting that version 1,3, and 5 UUIDs are deterministic in ways version 4 isn't. If the inputs to these uuid generators - node id in v1, namespace and name in v3 and v5 - are unique (as they're supposed to be), then the resulting UUIDs be unique. In theory, anyway.
  • broofa
    broofa almost 7 years
    This UUIDs produced by this code are either weak-but-RFC-compliant (_guid), or strong-but-not-RFC-compliant (_cryptoGuid). The former uses Math.random(), which is now known to be a poor RNG. The latter is failing to set the version and variant fields.
  • Marco Kerwitz
    Marco Kerwitz over 6 years
    This is not UUID though?
  • Simon Rigét
    Simon Rigét about 6 years
    No. UUID/GUID's is a 122 bit (+ six reserved bits) number. it might guarantee uniqueness through a global counter service, but often it relays on time, MAC address and randomness. UUID's are not random! The UID I suggest here is not fully compressed. You could compress it, to a 122 bit integer, add the 6 predefined bits and extra random bits (remove a few timer bits) and you end up with a perfectly formed UUID/GUID, that you would then have to convert to hex. To me that doesn't really add anything other than compliance to the length of the ID.
  • Simon Rigét
    Simon Rigét about 6 years
    Relaying on MAC addresses for uniqueness on virtual machines is a bad idea!
  • Matt
    Matt about 6 years
    @broofa - What would you suggest to make it strong and RFC-compliant? And why is _cryptoGuid not RFC-compliant?
  • broofa
    broofa about 6 years
    @Matt _cryptoGuid() sets all 128 bits randomly, meaning it doesn't set the version and variant fields as described in the RFC. See my alternate implementation of uuidv4() that uses crypto.getRandomValues() in my top-voted answer, above, for a strong+compliant implementation.
  • alek kowalczyk
    alek kowalczyk about 6 years
    Such approach is still a thing in 2018? Wow :-)
  • inf3rno
    inf3rno over 5 years
    Well most of the js devs are web developers, and we won't understand what bitwise operators do, because we don't use them most of the times we develop. Actually I never needed any of them, and I am a js dev since '97. So your example code is still totally unreadable to the average web developer who will read it. Not to mention that you still use single letter variable names, which makes it even more cryptic. Probably read Clean Code, maybe that helps: amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/…
  • vsync
    vsync over 5 years
    BTW, why does it generate only numbers and not characters as well? much less secure
  • Kasey Speakman
    Kasey Speakman over 5 years
    This literally calls AWS S3 to get a random ID. If calling a server is okay, you can just have the server generate a UUID.
  • magikMaker
    magikMaker about 5 years
    you can also add characters (letters ) like this: Array.from((window.crypto || window.msCrypto).getRandomValues(new Uint32Array(4))).map(n => n.toString(16)).join('-')
  • Seph Reed
    Seph Reed almost 5 years
    I do something like this, but with leading characters and some dashes (e.g [slug, date, random].join("_") to create usr_1dcn27itd_hj6onj6phr. It makes it so the id also doubles as a "created at" field
  • Mark Amery
    Mark Amery over 4 years
    This uses Math.random under the hood. Therefore broken and likely to suffer collisions in browsers with bad Math.random implementations. Prefer uuid since it uses the crypto API where available.
  • tatsu
    tatsu over 4 years
    @inf3rno don't bash him, all the proposed solutions in this thread are cryptic but they are correct answers considering the question was to have a one-liner of sorts. that's what one-liners are cryptic. they can't afford to be readable to the average developer but they save screen real estate where a simple preceding comment will do. And as a result, ends up being much more readable that way then if it had been in "readable code" instead.
  • ceving
    ceving over 4 years
    @user1529413 Yes. Uniqueness requires an index.
  • Egor Litvinchuk
    Egor Litvinchuk about 4 years
    Thank you for detailed description! Specifically nibble caged between 8 and 11 with equivalents explanation is super helpful.
  • Josh from Qaribou
    Josh from Qaribou almost 4 years
    This is my favourite answer, because it's building a UUID as a 16-byte (128 bit) value, and not its serialized, nice to read form. It'd be trivially easy to drop the string stuff and just set the correct bits of a random 128bit, which is all a uuidv4 needs to be. You could base64 it for shorter URLs, pass it back to some webassembly, store it in less memory space than as a string, make it a 4096-size buffer and put 256 uuids in it, store in a browser db, etc. Much better than having everything as a long, lowercase hex-encoded string from the start.
  • Abhi Beckert
    Abhi Beckert almost 4 years
    This should not be the accepted answer. It does not actually answer the question - instead encouraging the import of 25,000 lines of code for something you can do with one line of code in any modern browser.
  • hPNJ7MHTyg
    hPNJ7MHTyg almost 4 years
    I know you've added a lot of caveats in your post, but you're better off just striking out the first answer now, a lot of noobs will just come to this answer and copy the first thing they see without reading the rest. In reality you can't reliably generate UUIDs from the Math.random API and it would be dangerous to rely on that.
  • fcdt
    fcdt almost 4 years
    What's the difference to this post?
  • dbc
    dbc almost 4 years
    @fcdt - the difference is c === 'x' instead of c == 'x'.
  • DeusXMachina
    DeusXMachina over 3 years
    This is technically not a compliant UUID4. It's neat that it has the timestamp, but you are better off using a UUID1 at that point. With this scheme, there's a 1 in 10,000 chance of a collision every time there is a millisecond collision, which if you emit events every second, that's 1/1000, or 1 in 10 million, every second. That's pretty much guaranteed to occur in any production bigger than basically hobby scale. Semantically, UUIDs shouldn't be timestamp fields. That's what timestamp fields are for. They are meant for "give me an ID which will NEVER collide".
  • tarkh
    tarkh over 3 years
    @DeusXMachina thanks for commenting, I 100% agree. That's why in NodeJS library, which I've pointed at the end of my post, I use process.hrtime.bigint() for timestamps, which gives me nanosecond scale (1 million chance in a second) + random number from 10000 to 90000 at the end. So finally it goes to multi-billion chance in 1 sec, if my calculations is right. Anyway this is non-standard approach with specific use case, as I've mentioned above.
  • DeusXMachina
    DeusXMachina over 3 years
    Ah, I missed that. Perhaps edit your explanation so that it's a bit more obvious you are using ns resolution. "...produce a new UUID every millisecond + add a random 5-digit number". Still, why not use uuid1? That provides 0.1 µs resolution plus another 48 bits of entropy. en.wikipedia.org/wiki/…
  • Phil
    Phil over 3 years
    @AbhiBeckert the answer is from 2008 and for node.js projects it might be valid to choose a dependency more over project size
  • Peter Mortensen
    Peter Mortensen over 3 years
    Instead of the "updates" sections (that is what the revision history is for), it would be better if this answer is as if it was written today.
  • Abhi Beckert
    Abhi Beckert over 3 years
    @Phil this is a "highly active question", which means it should have an excellent answer with a green tick. Unfortunately that's not the case. There is nothing wrong or incorrect with this answer (if there was, I'd edit the answer) - but another far better answer exists below and I think it should be at the top of the list. Also the question is specifically relating to javascript in a browser, not node.js.
  • totalhack
    totalhack over 3 years
    Building on @SephReed's comment, I think having the date part first is nice since it sorts chronologically, which may provide benefits later if storing or indexing the IDs.
  • Steve Schnepp
    Steve Schnepp over 3 years
    If you really want to keep the versioning inline, and not behind revision history, you have to reverse the order : keep the most up to date answer as first.
  • Nemesarial
    Nemesarial over 3 years
    Can I just say -- I cannot count how many times I've pointed devs to this answer because it so beautifully points out the tradeoffs between performance, code-elegance, and readability. Thank you Jeff.
  • Slothario
    Slothario over 3 years
    "uuidv4" is a little cryptic -- I'm naming it "gitGudGuids" in my project (joking).
  • Andrew
    Andrew over 3 years
    I don't know if @Broofa's answer has changed since these tests were run (or if the browser engines running the tests have changed - it has been five years), but I just ran them both on two different benchmarking services (jsben.ch and jsbench.github.io), and in each case Broofa's answer (using Math.random) was faster than this e7() version by 30 - 35%.
  • NVRM
    NVRM over 3 years
    Invalid should be xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  • tarkh
    tarkh over 3 years
    @NVRM It IS valid, you can check result in any online UUID validators, i.e. here: freecodeformat.com/validate-uuid-guid.php
  • vladsiv
    vladsiv over 3 years
    Note: These imports didn't work for me. Import statements have changed, as stated in the repo: const { v4: uuidv4 } = require('uuid'); and ES6: import { v4 as uuidv4 } from 'uuid';
  • Paulo Henrique Queiroz
    Paulo Henrique Queiroz over 3 years
    works like a charm. Better than trying to generate manually. Very clever!
  • Basj
    Basj over 3 years
    For those wondering: toString(36) converts in a base-36 numeration (0..9a..z). Example: (35).toString(36) is z.
  • Aral Roca
    Aral Roca over 3 years
    The performance is quite worst, but depending on the case it can be enough
  • smallscript
    smallscript over 3 years
    For the fastest combined generator that is compliant w/node-clock-seq, monotonic in time, etc. This forms a good basis to seed a uuid4 generator w/60-bits of epoch70 μ-seconds of monotonic time, 4-bit uuid-version, and 48-bit node-id and 13-bit clock-seq with 3-bit uuid-variant. --<br> Combining using BigInt to write ntohl and related conversion this works very fast with the lut approach here. --<br> I can provide code if desired.
  • Peter Mortensen
    Peter Mortensen over 3 years
    The actual time resolution may or may not be 17 ms (1/60 second), not 1 ms.
  • Peter Mortensen
    Peter Mortensen over 3 years
    The redirected URL says "Applies to: SharePoint Foundation 2010"
  • Peter Mortensen
    Peter Mortensen over 3 years
    Why is it better?
  • wafs
    wafs about 3 years
    Alternatively window.URL.createObjectURL(new Blob([])).split('/').pop() will do the same without having to rely on external factors like URL length.
  • John
    John about 3 years
    Would Crypto.getRandomValues fix the main problems with Math.random??
  • Peter Mortensen
    Peter Mortensen about 3 years
    An explanation would be in order.
  • Peter Mortensen
    Peter Mortensen about 3 years
    An explanation would be in order. E.g., what ES6 features does it use that previous answers don't? Please respond by editing your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
  • Peter Mortensen
    Peter Mortensen about 3 years
    An explanation would be in order.
  • Peter Mortensen
    Peter Mortensen about 3 years
    What is "Blob"/"Blobs"?
  • Briguy37
    Briguy37 about 3 years
    Note: Zak had made an update to add the following. const { performance } = require('perf_hooks'); to define the performance variable. Thus for node.js strict implementations this may be needed. However, this has been removed from the answer because it broke the snippet and will not work with JavaScript used in most other environments, e.g. in browsers.
  • Munawwar
    Munawwar almost 3 years
    I challenge the claim that Math.random is that low of a quality of randomness. v8.dev/blog/math-random. As you can see, it's passes a good test suite, and the same algorithm is used by v8, FF and Safari. And the RFC states, pseudo-random numbers are acceptable for UUIDs
  • M. Justin
    M. Justin almost 3 years
    Is the inclusion of a UUID here guaranteed, or is it just something that the current browser implementations all happen to do?
  • M. Justin
    M. Justin almost 3 years
    The proposal currently is proposing including it in the crypto interface: const uuid = crypto.randomUUID(); // "52e6953d-edbe-4953-be2e-65ed3836b2f0"
  • FatalError
    FatalError almost 3 years
    Not compatible with IE since .repeat method is not available.
  • FatalError
    FatalError almost 3 years
    Changing '0'.repeat(16) to '000000' worked for me. I don't know why 0 needs to be repeated 16 times, only couple of times should be enough.
  • Simon Rigét
    Simon Rigét almost 3 years
    The the many zeros in front are needed, because a random number might be just one digit. Even if its very rare, it still has to work.
  • Doomd
    Doomd almost 3 years
    @Andy is right. Broofa's code is faster as of Aug 2021. I implemented Dave's suggestions and ran the test myself. But I don't imagine the difference should matter all that much in production: jsbench.github.io/#80610cde9bc93d0f3068e5793e60ff11
  • bedalton
    bedalton over 2 years
    I feel your comparisons may be unfair as broofa's anwer appears to be for an e4 UUID, and your testing against Ward's e7 implementation here. When you compare broofa's answer to the e4 version presented to here, this answer is faster.
  • Armen Michaeli
    Armen Michaeli over 2 years
    @PeterMortensen A blob is an opaque, efficient representation of some amount of "raw" (binary) data, for convenience of scripting on the Web.
  • Naveen Reddy Marthala
    Naveen Reddy Marthala over 2 years
    i am new to javascript. when I run the ES6 version with node 14, i get ReferenceError: performance is not defined. How do i fix it?
  • Briguy37
    Briguy37 over 2 years
    @NaveenReddyMarthala Node.js by default runs JavaScript in strict mode, which unfortunately doesn't allow boolean logic operators to shorthand check the truthiness of undefined variables. To fix this, try replacing var d2 = (performance .. with var d2 = (typeof performance !== 'undefined' .. as in the update version. The other option (which will actually utilize the enhanced precision of performance with Node.js rather than throwing it away) is to re-add const { performance } = require('perf_hooks'); in your requirements.
  • Naveen Reddy Marthala
    Naveen Reddy Marthala over 2 years
    Thanks @Briguy37
  • Ayyash
    Ayyash over 2 years
    im a bit confused, in javascript [1e7]+-1e3 does not really mean anything, an array is added to a number? what am I missing? note: in typescript it does not pass
  • TommyAutoMagically
    TommyAutoMagically over 2 years
    @bedalton: Why would we compare broofa's answer to "the e4 version"? The "4" in e4 simply refers to the iteration of optimization and not to the version of UUID, right?
  • TommyAutoMagically
    TommyAutoMagically over 2 years
    Umm this most definitely does not work. To work reliably on different domains, it needs to be changed to something like window.URL.createObjectURL(new Blob([])).substr(-36)
  • manuell
    manuell over 2 years
    @Ayyash In my Chrome F12 console [1e7]+-1e3 evaluates to a string: '10000000-1000'
  • manuell
    manuell over 2 years
  • bedalton
    bedalton over 2 years
    I did not catch that
  • broofa
    broofa over 2 years
    @ayyash The original derivation of that code snippet can be found here: gist.github.com/jed/982883 . It is, admittedly, ludicrously cryptic. For something less cryptic: gist.github.com/jed/982883#gistcomment-2403369
  • wazz
    wazz over 2 years
    Very new browsers required for crypto.randomUUID(). caniuse.com/mdn-api_crypto_randomuuid.
  • Daniel Marschall
    Daniel Marschall over 2 years
    These GUIDs are invalid because they don't specify version and variant required by the ITU-T | ISO recommendation.
  • Prestaul
    Prestaul over 2 years
    @DanielMarschall, this doesn't produce UUIDs, but does produce valid GUIDs which were common place in Microsoft code (e.g. .Net) in 2008 when this answer was written. Note, that this is also why the hex characters are forced to upper case. See: docs.microsoft.com/en-us/windows/win32/msi/guid
  • Daniel Marschall
    Daniel Marschall over 2 years
    @Prestaul I understand that GUID is an implementation of UUID. I am not aware that GUIDs don't follow the rules of the ITU-T, which say that random GUIDs ("version 4") need the "version" field set to 4 and the variant bits set to 0b01. Of course they are "valid" in regards syntax. But it is not correct to produce GUIDs which do not follow the specifications (i.e. produce a random GUID but label it as time based would cause invalid metadata about the GUID).
  • Prestaul
    Prestaul over 2 years
    @DanielMarschall You are correct that this doesn't follow the UUID/GUID specs. I'm simply stating that, in 2008 when this was written, GUID and UUID did not mean the same thing and Microsoft had its own definition and implementation of GUIDs which was in quite common use. That definition (did you see the link I shared) does not have a version/variant in it.
  • Prestaul
    Prestaul over 2 years
    FWIW, this answer was edited early on to recommend using one of the better solutions but that recommendation was removed later by the community.
  • vsync
    vsync over 2 years
    Do you have a working example that can run on the browser?
  • Armen Michaeli
    Armen Michaeli over 2 years
    The answer is certainly valid for Web browsers and so the example above will work.
  • vsync
    vsync over 2 years
    I don't see any code example here which can be copy-pasted and tried in the console
  • Armen Michaeli
    Armen Michaeli over 2 years
    I am not much in favour of writing answers where code must necessarily be copied for pasting in the console, among other places. The usage context seldom matches, so assume it would stand to reason those who need to make use of the answer are able to read it and understand and put it into use (adapting what code is presented among the prose that is there to explain it). It's all in the answer, really, is it not? Save for a literal body of code that can be copied and pasted in the console, I mean?
  • vsync
    vsync over 2 years
    I wanted to test this in the console to see what is the output. The Answer has a lot of text but I haven't read it because I don't have time to read long tests in answer, I want code which I can copy-paste. If I don't see such, I scroll to another answer
  • Brian Cannard
    Brian Cannard over 2 years
    And Safari is coming as well!
  • Roope Hakulinen
    Roope Hakulinen about 2 years
    @Ayyash this seems to produce the same result with valid JS/TS: 1e7 + '-' + 1e3
  • Charaf
    Charaf about 2 years
    One should never rely on external sources to generate one's randomness, especially when it comes to generating wallet addresses for instance.
  • Charaf
    Charaf about 2 years
    What's the drawback of this solution?
  • Hashbrown
    Hashbrown about 2 years
    Then disable that part or point it at your own server farm? Not hard. But if you're supporting something that doesnt support crypto you do not want to be relying on Math. Who the hell is using client side random for wallet addresses anyway? If using node you'd call out to the OS for uuid generation. I actually don't get your point @Charaf
  • Tikolu
    Tikolu about 2 years
    @Charaf Doesn't seem to have many drawbacks except for no support on Internet Explorer
  • dota2pro
    dota2pro about 2 years
    This doesn't work in Typescript it says can't add number[] and number
  • lissajous
    lissajous about 2 years
    On Safari 15.3 you will get: "ikdev.com/98455e8b-7f1c-44b3-8424-91e06214cb50", so this is not good solution.
  • Lucas
    Lucas about 2 years
    FYI there's some concern and advice given about memory management highlighted on MDN. developer.mozilla.org/en-US/docs/Web/API/URL/…
  • asduj
    asduj about 2 years
    instead of substr which is deprecated now, the slice might be used
  • PLG
    PLG about 2 years
    nodejs/React gives the warning: Use parentheses to clarify the intended order of operations: no-mixed-operators; great solution though.
  • NickyTheWrench
    NickyTheWrench almost 2 years
    Typescript users: you can add <any> right before the first array, like this: <any>[1e7] - quick way to get it to pass.
  • JSON
    JSON almost 2 years
    I think this answer should be edited by a qualified mod. Not only is it factually wrong, but it also doesn't answer the question at hand. Javascript development is different in the context of browser vs server. It's not trivial when a question targets the browser. Might well be saying use a node.js package when a question is specifically about Edge or Opera. Also, it may be better to request a UUID over REST, although that's only opinion. This way various means can be used to ensure it is truly unique. The server can even use the suggested package. But most servers don't use node.js either.
  • JSON
    JSON almost 2 years
    Or even better use asm.js. if we're going to offer irrelevant answers we might as well go hard on it