I want a string of fixed length, composed of characters picked randomly from a set of characters e.g. [a-zA-Z0-9].
How can I do this with JavaScript?
If you want to get crypto-strong string which meets your requirements (I see answer which use this but gives non valid answers) use
let pass = n=> [...crypto.getRandomValues(new Uint8Array(n))]
.map((x,i)=>(i=x/255*61|0,String.fromCharCode(i+(i>9?i>35?61:55:48)))).join``
let pass = n=> [...crypto.getRandomValues(new Uint8Array(n))]
.map((x,i)=>(i=x/255*61|0,String.fromCharCode(i+(i>9?i>35?61:55:48)))).join``
console.log(pass(5));
Update: thanks to Zibri comment I update code to get arbitrary-long password
The problem with responses to "I need random strings" questions (in whatever language) is practically every solution uses a flawed primary specification of string length. The questions themselves rarely reveal why the random strings are needed, but I would challenge you rarely need random strings of length, say 8. What you invariably need is some number of unique strings, for example, to use as identifiers for some purpose.
There are two leading ways to get strictly unique strings: deterministically (which is not random) and store/compare (which is onerous). What do we do? We give up the ghost. We go with probabilistic uniqueness instead. That is, we accept that there is some (however small) risk that our strings won't be unique. This is where understanding collision probability and entropy are helpful.
So I'll rephrase the invariable need as needing some number of strings with a small risk of repeat. As a concrete example, let's say you want to generate a potential of 5 million IDs. You don't want to store and compare each new string, and you want them to be random, so you accept some risk of repeat. As example, let's say a risk of less than 1 in a trillion chance of repeat. So what length of string do you need? Well, that question is underspecified as it depends on the characters used. But more importantly, it's misguided. What you need is a specification of the entropy of the strings, not their length. Entropy can be directly related to the probability of a repeat in some number of strings. String length can't.
And this is where a library like EntropyString can help. To generate random IDs that have less than 1 in a trillion chance of repeat in 5 million strings using entropy-string:
import {Random, Entropy} from 'entropy-string'
const random = new Random()
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"44hTNghjNHGGRHqH9"
entropy-string uses a character set with 32 characters by default. There are other predefined characters sets, and you can specify your own characters as well. For example, generating IDs with the same entropy as above but using hex characters:
import {Random, Entropy, charSet16} from './entropy-string'
const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"27b33372ade513715481f"
Note the difference in string length due to the difference in total number of characters in the character set used. The risk of repeat in the specified number of potential strings is the same. The string lengths are not. And best of all, the risk of repeat and the potential number of strings is explicit. No more guessing with string length.
nanoid is much more popular than entropy-string and seems just as good for my purposes.I did not find a clean solution for supporting both lowercase and uppercase characters.
Lowercase only support:
Math.random().toString(36).substr(2, 5)
Building on that solution to support lowercase and uppercase:
Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');
Change the 5 in substr(2, 5) to adjust to the length you need.
Just a simple map or reduce implementation should suffice:
const charset: string =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const random1: string = [...Array(5)]
.map((_) => charset[Math.floor(Math.random() * charset.length)])
.join("");
const random2: string = [...Array(5)]
.reduce<string>(
(acc) => acc += charset[Math.floor(Math.random() * charset.length)],
"",
);
Here's a functional style approach. The performance is sub-optimal but it was fun to write -
const char = a =>
String .fromCharCode (a)
const irand = x =>
Math .floor (Math .random () * x)
const sample = xs =>
xs .at (irand (xs.length))
const range = x => y =>
x > y
? []
: [ x, ...range (x + 1) (y) ]
const srand = rs => n =>
n <= 0
? ""
: char (sample (rs)) + srand (rs) (n - 1)
const identifier = srand ([
...range (48) (57), // include 0-9
...range (65) (90), // include A-Z
...range (97) (122), // include a-z
])
console .log (identifier (6)) //=> xUCXPI
console .log (identifier (10)) //=> JQvct8XeGt
console .log (identifier (20)) //=> ZVDwQSdRQLJEF5Wqjs17
It's hard to beat the clarity of identifier. Maybe a slight improvement could be -
const ord = x =>
x .charCodeAt (0)
const idGenerator = srand ([
...range (ord('0')) (ord('9')),
...range (ord('A')) (ord('Z')),
...range (ord('a')) (ord('z')),
])
Have fun with it. Let me know what you like/learn ^_^
U, Y and foldk? I'm trying to understand this but I'm not that familiar with functional programming and, in all honesty, have no idea what to look up. Also, I did a benchmark using Deno to compare this method with the equivalent imperative one and, as suspected, it is 4x slower 😃U and Y you will have to look into combinatory logic. foldk is a variant of fold (or reduce) which uses continuation-passing style. I re-worked the answer to be more practical and less concerned with functional primitives. You will find the performance to be greatly improved in this revision. Let me know if you have any other questions.const irand = x => { let value: number | undefined const arr = new Uint8Array(1) while (value === undefined || value >= x) { self.crypto.getRandomValues(arr) value = arr.at(0) } return value } to avoid Math.random. But blocks of code does not whow well in comments...This works for sure
<script language="javascript" type="text/javascript">
function randomString() {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
document.randform.randomfield.value = randomstring;
}
</script>
Here is my approach (with TypeScript).
I've decided to write yet another response because I didn't see any simple solution using modern js and clean code.
const DEFAULT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
function getRandomCharFromAlphabet(alphabet: string): string {
return alphabet.charAt(Math.floor(Math.random() * alphabet.length));
}
function generateId(idDesiredLength: number, alphabet = DEFAULT_ALPHABET): string {
/**
* Create n-long array and map it to random chars from given alphabet.
* Then join individual chars as string
*/
return Array.from({length: idDesiredLength}).map(() => {
return getRandomCharFromAlphabet(alphabet);
}).join('');
}
generateId(5); // jNVv7
Generate 10 characters long string. Length is set by parameter (default 10).
function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;
for(i=0; i<len; i++) {
switch(Math.floor(Math.random()*3+1)) {
case 1: // digit
str += (Math.floor(Math.random()*9)).toString();
break;
case 2: // small letter
str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
break;
case 3: // big letter
str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
break;
default:
break;
}
}
return str;
}
This one combines many of the answers give.
var randNo = Math.floor(Math.random() * 100) + 2 + "" + new Date().getTime() + Math.floor(Math.random() * 100) + 2 + (Math.random().toString(36).replace(/[^a-zA-Z]+/g, '').substr(0, 5));
console.log(randNo);
I have been using it for 1 month with great results.
You can use coderain. It's a library to generate random codes according to given pattern. Use # as a placeholder for upper and lowercase characters as well as digits:
var cr = new CodeRain("#####");
console.log(cr.next());
There are other placeholders like A for uppercase letters or 9 for digits.
What may be useful is that calling .next() will always give you a unique result so you don't have to worry about duplicates.
Here is a demo application that generates a list of unique random codes.
Full disclosure: I'm the author of coderain.
How about something like this: Date.now().toString(36)
Not very random, but short and quite unique every time you call it.
Date.now() only has millisecond resolution. When run in a simple loop, for example, you’ll get lots of duplicates. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.One liner [a-z]:
String.fromCharCode(97 + Math.floor(Math.random() * 26))
If you are developing on node js, it is better to use crypto. Here is an example of implementing the randomStr() function
const crypto = require('crypto');
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
const randomStr = (length = 5) => new Array(length)
.fill(null)
.map(() => charset.charAt(crypto.randomInt(charset.length)))
.join('');
If you are not working in a server environment, just replace the random number generator:
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
const randomStr = (length = 5) => new Array(length)
.fill(null)
.map(() => charset.charAt(Math.floor(Math.random() * charset.length)))
.join('');
Uncaught TypeError: crypto.randomInt is not a functionIf you just want uppercase letters (A-Z):
randomAZ(n: number): string {
return Array(n)
.fill(null)
.map(() => Math.random()*100%25 + 'A'.charCodeAt(0))
.map(a => String.fromCharCode(a))
.join('')
}
If you just want the first letter to be uppercase (A-Z), and the rest to be lower case (a-z):
function RandomWord(n: number): string {
return Array(n)
.fill(null)
.map(() => Math.random()*100%25 + 'A'.charCodeAt(0))
.map((a, i) => i === 0? String.fromCharCode(a) : String.fromCharCode(a+32))
.join('')
}
[a-zA-Z0-9]Here is a test script for the #1 answer (thank you @csharptest.net)
The script runs makeid() 1 million times and as you can see 5 isn't a very unique. running it with a char length of 10 is quite reliable. I've ran it about 50 times and haven't seen a duplicate yet :-)
Note: node stack size limit exceeds around 4 million so you cant run this 5 million times it won't ever finish.
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
ids ={}
count = 0
for (var i = 0; i < 1000000; i++) {
tempId = makeid();
if (typeof ids[tempId] !== 'undefined') {
ids[tempId]++;
if (ids[tempId] === 2) {
count ++;
}
count++;
}else{
ids[tempId] = 1;
}
}
console.log("there are "+count+ ' duplicate ids');
Expanding on Doubletap's elegant example by answering the issues Gertas and Dragon brought up. Simply add in a while loop to test for those rare null circumstances, and limit the characters to five.
function rndStr() {
x=Math.random().toString(36).substring(7).substr(0,5);
while (x.length!=5){
x=Math.random().toString(36).substring(7).substr(0,5);
}
return x;
}
Here's a jsfiddle alerting you with a result: http://jsfiddle.net/pLJJ7/
This is what I used. A combination of a couple here. I use it in a loop, and each ID it produces is unique. It might not be 5 characters, but it's guaranteed unique.
var newId =
"randomid_" +
(Math.random() / +new Date()).toString(36).replace(/[^a-z]+/g, '');
Also based upon doubletap's answer, this one handles any length of random required characters (lower only), and keeps generating random numbers until enough characters have been collected.
function randomChars(len) {
var chars = '';
while (chars.length < len) {
chars += Math.random().toString(36).substring(2);
}
// Remove unnecessary additional characters.
return chars.substring(0, len);
}
This method will return a random string with any of the supported unicode characters, which is not 100% what OP asks for, but what I was looking for:
function randomUnicodeString(length){
return Array.from({length: length}, ()=>{
return String.fromCharCode(Math.floor(Math.random() * (65536)))
}).join('')
}
This is the top result of google when searching for "random string javascript", but OP asks for a-zA-Z0-9 only.
For a string with upper- and lowercase letters and digits (0-9a-zA-Z), this may be the version that minifies best:
function makeId(length) {
var id = '';
var rdm62;
while (length--) {
// Generate random integer between 0 and 61, 0|x works for Math.floor(x) in this case
rdm62 = 0 | Math.random() * 62;
// Map to ascii codes: 0-9 to 48-57 (0-9), 10-35 to 65-90 (A-Z), 36-61 to 97-122 (a-z)
id += String.fromCharCode(rdm62 + (rdm62 < 10 ? 48 : rdm62 < 36 ? 55 : 61))
}
return id;
}
The content of this function minifies to 97 bytes, while the top answer needs 149 bytes (because of the characters list).
This is a slightly improved version of doubletap's answer. It considers gertas's comment about the case, when Math.random() returns 0, 0.5, 0.25, 0.125, etc.
((Math.random()+3*Number.MIN_VALUE)/Math.PI).toString(36).slice(-5)
toString my adding the smallest float to Math.random().toString has enough digits by dividing through an almost irrational number.How about this below... this will produce the really random values:
function getRandomStrings(length) {
const value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const randoms = [];
for(let i=0; i < length; i++) {
randoms.push(value[Math.floor(Math.random()*value.length)]);
}
return randoms.join('');
}
But if you looking for a shorter syntax one in ES6:
const getRandomStrings = length => Math.random().toString(36).substr(-length);
Posting an ES6-compatible version for posterity. If this is called a lot, be sure to store the .length values into constant variables.
// USAGE:
// RandomString(5);
// RandomString(5, 'all');
// RandomString(5, 'characters', '0123456789');
const RandomString = (length, style = 'frictionless', characters = '') => {
const Styles = {
'all': allCharacters,
'frictionless': frictionless,
'characters': provided
}
let result = '';
const allCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const frictionless = 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
const provided = characters;
const generate = (set) => {
return set.charAt(Math.floor(Math.random() * set.length));
};
for ( let i = 0; i < length; i++ ) {
switch(Styles[style]) {
case Styles.all:
result += generate(allCharacters);
break;
case Styles.frictionless:
result += generate(frictionless);
break;
case Styles.characters:
result += generate(provided);
break;
}
}
return result;
}
export default RandomString;
This will generate a random alpha-numeric string with the length of the first/calling string:
"12345".split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');
//or
String.prototype.rand = function() {return this.split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');};
A reduced random alphanumeric with upper and lowercase using random bytes from crypto module:
const l = 98 // length
// Node
Array.from(crypto.randomBytes(l)).reduce((s, b) => s + (b % 36).toString(36)[(b % 2) ? 'toLowerCase' : 'toUpperCase'](), '')
// Browser [WebCrypto] (Thanks to Nabulosar in comments, check his comment if you use it)
Array.from(crypto.getRandomValues(new Uint8Array(l))).reduce((s, b) => s + (b % 36).toString(36)[(b % 2) ? 'toLowerCase' : 'toUpperCase'](), '')
",,,,,".replace(/,/g,function (){return "AzByC0xDwEv9FuGt8HsIrJ7qKpLo6MnNmO5lPkQj4RiShT3gUfVe2WdXcY1bZa".charAt(Math.floor(Math.random()*62))});
true-randomresult! They are onlypseudo-random. When using random strings for protection or security, don't use any of them!!! Try one of these api's: random.org