Generate Nano IDs: short, URL-safe random identifiers that do the job of a UUID in 21 characters instead of 36. Change the size or alphabet and the bar at the bottom shows how long it would take to reach a 1% chance of a collision. Check that number before you shorten an ID. Presets cover the Nano ID default, alphanumeric, lowercase and digits, hex, numbers only and a no look-alikes set, or you can type your own alphabet.
V1StGXR8_Z5jdHi6B-myT
3kTMd5YlQ0wE7uNf_pZ2c
mB9xq-4RkLs2HvT0aYw8e import { nanoid, customAlphabet } from "nanoid";
nanoid(); // "V1StGXR8_Z5jdHi6B-myT"
nanoid(10); // "IRFa-VaY2b"
const orderId = customAlphabet("0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", 12);
orderId(); // "7K3ZQ0M8XHAT"
An ID with an alphabet of A characters and a size of L has
H = AL possible values, which is L × log2(A) bits.
By the birthday problem, the number of IDs you can create before
the chance of any two matching reaches p is about
n = sqrt(2 × H × ln(1 / (1 - p))). The page
divides n by your rate to get the time. The zelark Nano ID
collision calculator uses the same formula, and here p is fixed at
1%.
The defaults give 126 bits and roughly 149 billion years at 1,000 IDs per hour. Each character you remove divides that time by 8 (the square root of 64). For example, size 10 drops to about 17 years at the same rate, and to about two months at 100,000 IDs an hour. Enter your peak rate in IDs per hour, not your average. The estimate counts every ID ever created in the same namespace, including deleted ones.
A random byte has 256 values. With a 36-character alphabet,
byte % 36 maps 256 values onto 36 slots, so the first 4
characters get 8 chances each and the rest get 7. That makes some
IDs measurably more likely than others. Nano ID avoids the bias by
masking each byte to the next power of two (a mask of 63 for 36
characters) and discarding anything above 35. This page does the
same, with bytes from crypto.getRandomValues().
The page removes duplicates and whitespace from a custom alphabet and allows up to 256 distinct characters, like the library. Emoji and other characters outside the Basic Multilingual Plane count as one character here. However, the nanoid package indexes by UTF-16 code unit, so the same alphabet string behaves differently there.
// npm install nanoid
import { nanoid, customAlphabet } from "nanoid";
console.log(nanoid()); // 21 chars, A-Za-z0-9_-
console.log(nanoid(12)); // shorter, check the collision math first
// Custom alphabet and size, e.g. order numbers without look-alikes
const orderId = customAlphabet("346789ABCDEFGHJKLMNPQRTUVWXY", 10);
console.log(orderId()); nanoid 4 and later ship as ES modules. In an older CommonJS project use a dynamic import(), or pin nanoid@3, which still supports require().
import secrets
URL_ALPHABET = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"
def nanoid(size=21, alphabet=URL_ALPHABET):
# secrets.choice picks uniformly with no modulo bias
return "".join(secrets.choice(alphabet) for _ in range(size))
print(nanoid())
print(nanoid(10, "0123456789abcdef")) The nanoid package on PyPI does the same thing; the standard library version saves a dependency.
<?php
function nanoid(int $size = 21, string $alphabet = '_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string
{
$max = strlen($alphabet) - 1;
$id = '';
for ($i = 0; $i < $size; $i++) {
// random_int() is a CSPRNG and is unbiased
$id .= $alphabet[random_int(0, $max)];
}
return $id;
}
echo nanoid(), PHP_EOL;
echo nanoid(8, '0123456789'), PHP_EOL; Byte-indexed, so keep the alphabet ASCII. For multibyte characters, split it with mb_str_split() first.
The collision estimate uses the birthday bound n = sqrt(2 x H x ln(1 / (1 - p))) with H = alphabet size raised to the ID size and p = 1%, the same formula as the Nano ID Collision Calculator. It assumes every ID is drawn independently and uniformly. That holds for this page and for the nanoid library, but not for IDs derived from timestamps or counters.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
A random string ID from the nanoid JavaScript library: 21 characters from A-Za-z0-9_- by default, which is 126 random bits, about the same as a UUID v4 in 15 fewer characters.
Use UUID when a database column type, another language or an API contract expects one. Use Nano ID when the ID ends up in URLs or users see it and you want it shorter. With default settings the collision risk is about the same.
It depends on how many you create. Change Size and the estimate at the bottom shows the time to a 1% collision chance at your rate. For example, at 1,000 IDs per hour, size 10 lasts about 17 years and size 8 about 99 days.
Yes, at the default size. The randomness comes from crypto.getRandomValues() with the same unbiased masking as the nanoid library. Treat 21 characters (126 bits) as the minimum for a secret, and do not shorten a token that grants access.
Yes. Pick a preset or type into the Characters box. Duplicates and whitespace are removed, and the alphabet must have between 2 and 256 distinct characters, the same limits as customAlphabet() in the library.
Yes. Choose Lowercase + digits (a-z0-9) in Alphabet. Use it where case is ignored or folded: subdomains and hostnames, S3 bucket names, email local parts, or a MySQL column with a case-insensitive collation, where abc and ABC would be the same key. The alphabet has 36 characters, about 5.2 bits each, so raise Size to 25 to keep the 126 bits of the default.
It drops the characters people misread when an ID is printed or read aloud: 0 and O, 1, I and l, 2 and Z, 5 and S, and the lowercase o, s, u and v. The remaining 49 letters and digits are the nolookalikes set from nanoid-dictionary. Pick it for order numbers, support codes and anything a customer might type back to you.
Yes. Numbers (0-9) gives digit-only IDs for a numeric column or a code read over the phone, and Hex (0-9a-f) gives IDs that look like a hash or a Mongo ObjectId. Both alphabets are small, so each character carries fewer bits: 21 digits is only about 70 bits. Watch the bits figure in the estimate and raise Size until the time to a collision reads in centuries.
When you need a standard format that databases and other languages already understand, use the UUID generator. For free-form random text with symbols, use the random string generator, and for secrets people will type, the password generator.