Categories
javascript random string

Generate random string/characters in JavaScript

2511

I want a 5 character string composed of characters picked randomly from the set [a-zA-Z0-9].

What’s the best way to do this with JavaScript?

17

  • 74

    Warning: None of the answers have a true-random result! They are only pseudo-random. When using random strings for protection or security, don’t use any of them!!! Try one of these api’s: random.org

    May 29, 2013 at 11:33


  • 65

    Math.random().toString(36).replace(/[^a-z]+/g, ”)

    – Muaz Khan

    Sep 14, 2013 at 14:47

  • 24

    Please put the solution in a solution.

    – chryss

    Sep 24, 2013 at 4:36

  • 318

    Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);

    – Friedrich

    Aug 15, 2014 at 9:28

  • 17

    Note HTML5 webcrypto randomness API provides real randomness.

    Jan 9, 2016 at 16:54

3345

I think this will work for you:

function makeid(length) {
    var result="";
    var characters="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    var charactersLength = characters.length;
    for ( var i = 0; i < length; i++ ) {
      result += characters.charAt(Math.floor(Math.random() * 
 charactersLength));
   }
   return result;
}

console.log(makeid(5));

20

2930

//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);

Note: The above algorithm has the following weaknesses:

  • It will generate anywhere between 0 and 6 characters due to the fact that trailing zeros get removed when stringifying floating points.
  • It depends deeply on the algorithm used to stringify floating point numbers, which is horrifically complex. (See the paper “How to Print Floating-Point Numbers Accurately”.)
  • Math.random() may produce predictable (“random-looking” but not really random) output depending on the implementation. The resulting string is not suitable when you need to guarantee uniqueness or unpredictability.
  • Even if it produced 6 uniformly random, unpredictable characters, you can expect to see a duplicate after generating only about 50,000 strings, due to the birthday paradox. (sqrt(36^6) = 46656)

22

  • 316

    Math.random().toString(36).substr(2, 5), because .substring(7) causes it to be longer than 5 characters. Full points, still!

    – dragon

    May 7, 2012 at 8:13

  • 85

    @Scoop The toString method of a number type in javascript takes an optional parameter to convert the number into a given base. If you pass two, for example, you’ll see your number represented in binary. Similar to hex (base 16), base 36 uses letters to represent digits beyond 9. By converting a random number to base 36, you’ll wind up with a bunch of seemingly random letters and numbers.

    Jan 3, 2013 at 20:45

  • 81

    Looks beautiful but in few cases this generates empty string! If random returns 0, 0.5, 0.25, 0.125… will result in empty or short string.

    – gertas

    Mar 15, 2013 at 19:55

  • 77

    @gertas This can be avoided by (Math.random() + 1).toString(36).substring(7);

    Aug 11, 2013 at 17:17

  • 34

    @hacklikecrack, the duplicates occur because substring(7) takes the digits from the least significant part of the base-36 string. toString(36) appears to convert the random number to a 16 digit base-36 string, but the precision required for this would be 36^16 = 7.958e24 possible numbers, where the precision of Math.random() is only 4.5e15. Taking the digits from most significant end with .slice(2,5) solves this: 5 digit example

    – Luke

    Dec 4, 2014 at 0:48

783

Math.random is bad for this kind of thing

Option 1

If you’re able to do this server-side, just use the crypto module –

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

The resulting string will be twice as long as the random bytes you generate; each byte encoded to hex is 2 characters. 20 bytes will be 40 characters of hex.


Option 2

If you have to do this client-side, perhaps try the uuid module –

var uuid = require("uuid");
var id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

Option 3

If you have to do this client-side and you don’t have to support old browsers, you can do it without dependencies –

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
  return dec.toString(16).padStart(2, "0")
}

// generateId :: Integer -> String
function generateId (len) {
  var arr = new Uint8Array((len || 40) / 2)
  window.crypto.getRandomValues(arr)
  return Array.from(arr, dec2hex).join('')
}

console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"

console.log(generateId(20))
// "c1a050a4cd1556948d41"

For more information on crypto.getRandomValues

The crypto.getRandomValues() method lets you get cryptographically strong random values. The array given as the parameter is filled with random numbers (random in its cryptographic meaning).

Here’s a little console example –

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]

> window.crypto
Crypto { subtle: SubtleCrypto }

> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed

> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]

For IE11 support you can use –

(window.crypto || window.msCrypto).getRandomValues(arr)

For browser coverage see https://caniuse.com/#feat=getrandomvalues

20

  • 6

    Exactly. While a UUID is fine for assigning an ID to a thing, using it as a string of random characters isn’t a great idea for this (and probably other) reasons.

    Aug 4, 2015 at 17:42

  • 3

    No need for .map() in Option 3. Array.from(arr, dec2hex).join('') === Array.from(arr).map(dec2hex).join(''). Thanks for introducing me to these features 🙂

    May 11, 2017 at 19:28

  • 7

    You should mention in the answer that option 2 also needs node.js to work, it’s not pure javascript.

    – Esko

    Aug 21, 2018 at 11:47

  • 8

    While being more cryptographically secure, this doesn’t actually satisfy the requirements of the question because it only outputs 0-9 and a-f (Hexadecimal), and not 0-9, a-z, A-Z.

    – qJake

    Oct 17, 2018 at 19:46

  • 1

    @AneesAhmed777 the dec2hex was provided an example encoder. It’s up to you to represent the bytes however you choose. I updated the post with your suggestion.

    – Mulan

    Dec 1, 2020 at 17:29