NanoID Generator
Generate tiny URL-safe unique IDs with customizable alphabet
Abeceda
Velikost
Počet
Klikněte na Generovat pro vytvoření NanoID
Co je NanoID?
NanoID je malý, rychlý, URL-bezpečný generátor náhodných ID. Ve výchozím nastavení produkuje 21znakové řetězce pomocí 64znakové abecedy (A-Za-z0-9_-), čímž poskytuje přibližně 126 bitů entropie — srovnatelné s 122 bity UUID v4, ale v kratším řetězci.
NanoID nevkládá časové razítko ani žádná strukturovaná data. Každé ID je čistě náhodné, generované z kryptograficky bezpečného generátoru náhodných čísel operačního systému (crypto.getRandomValues() v prohlížečích, crypto.randomBytes() v Node.js).
NanoID vs UUID v4
NanoID a UUID v4 jsou oba generátory náhodných ID podporované CSPRNG. Liší se ve formátu, délce a podpoře ekosystému:
| Vlastnost | NanoID (výchozí) | UUID v4 |
|---|---|---|
| Formát | URL-bezpečné alfanumerické + _- | Hexadecimální s pomlčkami |
| Délka | 21 znaků (výchozí) | 36 znaků |
| Entropie | ~126 bitů | 122 bitů |
| URL-bezpečné | Ano — není potřeba kódování | Ano (s pomlčkami) |
| Abeceda | 64 znaků (A-Za-z0-9_-) | 16 znaků (0-9a-f) |
| Závislosti | Vyžaduje balíček npm | Nativní (crypto.randomUUID) |
| Přizpůsobitelné | Ano — délka a abeceda | Ne |
| Standard | Žádný (komunitní knihovna) | RFC 4122 / RFC 9562 |
Zvolte UUID v4, když záleží na interoperabilitě s externími systémy — databáze s nativními sloupci UUID, API očekávající formát UUID nebo logovací infrastruktura, která parsuje UUID. Zvolte NanoID, když chcete kratší ID a ovládáte celý stack.
Pravděpodobnost kolize podle velikosti
Pravděpodobnost kolize NanoID závisí na délce ID a rychlosti generování. Následující tabulka používá výchozí 64znakovou abecedu:
| Velikost (znaky) | Možná ID | Bezpečnost kolize |
|---|---|---|
| 6 | 64 | ~1 z 4,5B — bezpečné pro několik tisíc ID |
| 8 | 64 | ~1 z 4,5B — bezpečné pro miliony ID |
| 11 | 64 | ~1 z 2,8 kvadrilionu — bezpečné pro miliardy ID |
| 16 | 64 | ~1 z 1,2 × 10^19 — bezpečné pro biliony ID |
| 21 | 64 | ~1 z 10^30 — bezpečné pro 100 miliard ID denně po staletí |
| 32 | 64 | Srovnatelné s UUID v4 (122 bitů) |
| 36 | 36 | Překračuje UUID v4 |
Výchozí velikost 21 znaků je zvolena tak, aby odpovídala odolnosti UUID v4 vůči kolizím (~126 bitů) při délce o 41 % kratší. Pro většinu aplikací je 21 znaků správnou volbou.
Vlastní abecedy
Abeceda NanoID je plně přizpůsobitelná. Knihovna přijímá libovolný řetězec unikátních znaků jako abecedu a generuje ID pouze pomocí těchto znaků:
A-Za-z0-9_-A-Za-z0-90-9a-f0-9Důležité: používejte nanoid/non-secure pouze pro aplikace nesensitivní na zabezpečení (např. ID prvků uživatelského rozhraní). Pro jakékoliv ID, které musí být neuhádnutelné, vždy používejte výchozí bezpečný import.
Jak NanoID generuje náhodnost
NanoID používá kryptograficky bezpečný pseudonáhodný generátor čísel (CSPRNG) operačního systému. V prohlížečích je to crypto.getRandomValues(); v Node.js je to crypto.randomFillSync(). Toto je stejný zdroj entropie používaný pro klíče relace TLS — mnohem silnější než Math.random().
Odmítnutí vzorkování (vyhýbání se modulo bias)
Naivní přístup ke generování náhodných znaků by byl: vezměte náhodný bajt (0–255) a vypočítejte byte % alphabetSize. To zavádí modulo bias — některé znaky se vyskytují o něco častěji než jiné, když velikost abecedy nerozděluje 256 rovnoměrně.
NanoID eliminuje tuto bias pomocí odmítnutí vzorkování:
- Určete nejmenší masku mocniny dvou, která pokrývá velikost abecedy (např. pro abecedu 64 znaků je maska 63 = 0b00111111)
- Vygenerujte náhodné bajty a aplikujte masku:
byte & mask - Pokud je maskovaná hodnota v rozsahu abecedy, použijte ji. Jinak zahoďte a zkuste znovu.
To znamená, že některé náhodné bajty jsou zahozeny, ale výsledkem je perfektně rovnoměrné rozdělení přes abecedu — žádný znak není pravděpodobnější než jiný.
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = crypto.getRandomValues(new Uint8Array(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) {
id += alphabet[idx]
if (id.length === size) break
}
}
}
return id
}
const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21) // → "V1StGXR8_Z5jdHi6B-myT"Podpora prostředí
Příklady kódu
JavaScript / TypeScript
// npm i nanoid
import { nanoid } from 'nanoid'
nanoid() // → "V1StGXR8_Z5jdHi6B-myT" (21 chars, URL-safe)
nanoid(8) // → "Uakgb_J5" (custom size)
// Custom alphabet
import { customAlphabet } from 'nanoid'
const hexId = customAlphabet('0123456789abcdef', 16)
hexId() // → "4f3a1b8c9d2e0f7a"
const numId = customAlphabet('0123456789', 8)
numId() // → "30812894"Prohlížeč (CDN)
NanoID lze použít přímo v prohlížeči prostřednictvím importu CDN. Není potřeba žádný krok sestavení pro rychlé prototypování.
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = crypto.getRandomValues(new Uint8Array(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) {
id += alphabet[idx]
if (id.length === size) break
}
}
}
return id
}
const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21) // → "V1StGXR8_Z5jdHi6B-myT"Python
# pip install nanoid
from nanoid import generate
generate() # → "V1StGXR8_Z5jdHi6B-myT"
generate(size=8) # → "Uakgb_J5"
generate('0123456789abcdef', 16) # custom alphabet + sizeNode.js (CommonJS)
// Node.js — stdlib only, no npm needed
const { randomFillSync } = require('crypto')
function nanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = randomFillSync(Buffer.alloc(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) { id += alphabet[idx]; if (id.length === size) break }
}
}
return id
}