Nano ID Generator

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.

Generated IDs
 

1 Nano ID Generator example

Default settings (size 21)

V1StGXR8_Z5jdHi6B-myT
3kTMd5YlQ0wE7uNf_pZ2c
mB9xq-4RkLs2HvT0aYw8e

Same thing with the nanoid package

import { nanoid, customAlphabet } from "nanoid";

nanoid();                 // "V1StGXR8_Z5jdHi6B-myT"
nanoid(10);               // "IRFa-VaY2b"

const orderId = customAlphabet("0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", 12);
orderId();                // "7K3ZQ0M8XHAT"

2 The collision estimate uses the birthday bound

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.

3 Rejection sampling keeps every character equally likely

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.

How to use the Nano ID Generator tool

  1. Set Size (21 by default) and Count (1 to 1000). The list regenerates as you type.
  2. Pick an Alphabet preset, or type your own characters into the Characters box, and the preset switches to Custom.
  3. Set IDs per hour to your real peak rate and read the collision estimate in the bar under the list.
  4. Click Generate for a fresh batch, Copy All to copy them one per line, or Download to save nanoids.txt.
  5. Choose Lowercase + digits for case-insensitive systems, No look-alikes for codes people will type, and Numbers or Hex when the format demands it, then raise Size until the estimate reads in centuries.

How to generate a Nano ID in JavaScript, Python and PHP

JavaScript (nanoid package)

// 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().

Python (standard library)

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

<?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.

Common errors and how to fix them

Error [ERR_REQUIRE_ESM]: require() of ES Module nanoid not supported
nanoid 4 and later are ES modules, and older Node versions (before 20.19 and 22.12) cannot require() them. Switch the file to import, use await import("nanoid"), or install nanoid@3 for CommonJS.
Duplicate IDs showed up in production
The usual causes are a size cut down without checking the math, or Math.random() based code such as nanoid/non-secure. Put your real peak volume into IDs per hour and pick a size that gives centuries, not years.
IDs with - or _ break a double-click select or a filename
Double-click selection stops at - in most editors, and a leading - looks like a command-line flag. Use the Alphanumeric preset if the IDs are copied by hand or used as filenames.
Custom alphabet IDs look less random than expected
A small alphabet needs a longer size for the same strength: 21 hex characters is 84 bits, not 126. Compare the bits figure in the estimate, not the length.

Good to know

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.

Specifications and references

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.

Frequently Asked Questions

What is a Nano ID?

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.

Nano ID vs UUID: which should I use?

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.

How short can a Nano ID safely be?

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.

Are the IDs random enough for secrets?

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.

Can I use my own alphabet?

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.

Can I generate a lowercase-only Nano ID?

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.

What does the No look-alikes alphabet leave out?

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.

Can I generate a numeric-only or hex Nano ID?

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.

Related

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.

More Generators

Browse all generators

Copied to clipboard!