Generator NanoID

Generuje małe, bezpieczne dla URL unikalne ID z konfigurowalnym alfabetem

Alfabet

Rozmiar

Liczba

Kliknij Generuj, aby utworzyć NanoID

Czym jest NanoID?

NanoID to mały, szybki, bezpieczny dla URL generator losowych identyfikatorów. Domyślnie produkuje 21-znakowe ciągi przy użyciu 64-znakowego alfabetu (A-Za-z0-9_-), zapewniając około 126 bitów entropii — porównywalnych do 122 bitów UUID v4, ale w krótszym ciągu.

NanoID nie osadza znacznika czasu ani żadnych danych strukturalnych. Każdy identyfikator jest czysto losowy, generowany z kryptograficznie bezpiecznego generatora liczb losowych systemu operacyjnego (crypto.getRandomValues() w przeglądarkach, crypto.randomBytes() w Node.js).

NanoID a UUID v4

NanoID i UUID v4 to generatory losowych identyfikatorów obsługiwane przez CSPRNG. Różnią się formatem, długością i obsługą przez ekosystem:

WłaściwośćNanoID (domyślnie)UUID v4
FormatAlfanumeryczny bezpieczny dla URL + _-Szesnastkowy z myślnikami
Długość21 znaków (domyślnie)36 znaków
Entropia~126 bitów122 bity
Bezpieczny dla URLTak — nie wymagane kodowanieTak (z myślnikami)
Alfabet64 znaki (A-Za-z0-9_-)16 znaków (0-9a-f)
ZależnościWymaga pakietu npmNatywny (crypto.randomUUID)
KonfigurowalnyTak — długość i alfabetNie
StandardBrak (biblioteka społecznościowa)RFC 4122 / RFC 9562

Wybierz UUID v4, gdy liczy się interoperacyjność z systemami zewnętrznymi — bazy danych z natywnymi kolumnami UUID, API oczekujące formatu UUID lub infrastruktura logowania parsująca UUID. Wybierz NanoID, gdy chcesz krótszych identyfikatorów i kontrolujesz cały stos.

Prawdopodobieństwo kolizji według rozmiaru

Prawdopodobieństwo kolizji NanoID zależy od długości identyfikatora i tempa generowania. Poniższa tabela używa domyślnego 64-znakowego alfabetu:

Rozmiar (znaki)Możliwe identyfikatoryBezpieczeństwo kolizji
664~1 na 4,5 mld — bezpieczne dla kilku tysięcy identyfikatorów
864~1 na 4,5 bln — bezpieczne dla milionów identyfikatorów
1164~1 na 2,8 biliarda — bezpieczne dla miliardów identyfikatorów
1664~1 na 1,2 × 10^19 — bezpieczne dla bilionów identyfikatorów
2164~1 na 10^30 — bezpieczne dla 100 miliardów identyfikatorów dziennie przez wieki
3264Porównywalny do UUID v4 (122 bity)
3636Przekracza UUID v4

Domyślny rozmiar 21 znaków jest wybrany tak, aby odpowiadać odporności UUID v4 na kolizje (~126 bitów), będąc przy tym o 41% krótszy. Dla większości aplikacji 21 znaków to właściwy wybór.

Niestandardowe alfabety

Alfabet NanoID jest w pełni konfigurowalny. Biblioteka akceptuje dowolny ciąg unikalnych znaków jako alfabet i generuje identyfikatory używając wyłącznie tych znaków:

Tylko cyfryA-Za-z0-9_-
Użyj '0123456789' dla identyfikatorów złożonych z samych cyfr — przydatne dla kodów SMS lub identyfikatorów w stylu PIN.
Małe litery szesnastkoweA-Za-z0-9
Użyj '0123456789abcdef' dla kompaktowych ciągów szesnastkowych bez formatu UUID z myślnikami.
Czytelny dla człowieka0-9a-f
Wyklucz wizualnie niejednoznaczne znaki (0, O, 1, I, l) dla identyfikatorów, które użytkownicy mogą musieć wpisywać ręcznie.
Niestandardowa domena0-9
Użyj dowolnego zestawu znaków odpowiedniego dla twojej aplikacji — np. tylko samogłoski+spółgłoski dla identyfikatorów do wymówienia.

Ważne: używaj nanoid/non-secure tylko dla aplikacji niewrażliwych na bezpieczeństwo (np. identyfikatory elementów UI). Dla każdego identyfikatora, który musi być nieodgadniony, zawsze używaj domyślnego bezpiecznego importu.

Jak NanoID generuje losowość

NanoID używa kryptograficznie bezpiecznego pseudolosowego generatora liczb (CSPRNG) systemu operacyjnego. W przeglądarkach to crypto.getRandomValues(); w Node.js to crypto.randomFillSync(). To to samo źródło entropii co dla kluczy sesji TLS — znacznie silniejsze niż Math.random().

Odrzucanie próbek (unikanie obciążenia modulo)

Naiwnym podejściem do generowania losowych znaków byłoby: weź losowy bajt (0–255) i oblicz byte % alphabetSize. Wprowadza to obciążenie modulo — niektóre znaki pojawiają się nieco częściej niż inne, gdy rozmiar alfabetu nie dzieli równo 256.

NanoID eliminuje to obciążenie przy użyciu odrzucania próbek:

  1. Wyznacz najmniejszą maskę potęgi dwójki pokrywającą rozmiar alfabetu (np. dla 64-znakowego alfabetu maska to 63 = 0b00111111)
  2. Generuj losowe bajty i zastosuj maskę: byte & mask
  3. Jeśli zamaskowana wartość mieści się w zakresie alfabetu, użyj jej. W przeciwnym razie odrzuć i spróbuj ponownie.

Oznacza to, że niektóre losowe bajty są odrzucane, ale wynikiem jest perfekcyjnie równomierny rozkład po alfabecie — żaden znak nie jest bardziej prawdopodobny niż inny.

How the algorithm works — step by step
// 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"

Obsługa środowisk

Browser
Nowoczesne przeglądarki (Chrome 37+, Firefox 34+, Safari 7+) — używa crypto.getRandomValues()
Node.js 14+
Node.js 14.18+ — używa crypto.randomFillSync()
Deno
Deno — używa crypto.getRandomValues()
Bun
React Native — używa polyfilla expo-crypto lub react-native-get-random-values
Edge / Cloudflare Workers
Edge runtimes (Cloudflare Workers, Vercel Edge) — dostępne Web Crypto API
React Native
Bun — natywna obsługa crypto

Przykłady kodu

JavaScript / TypeScript

JavaScript
// 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"

Przeglądarka (CDN)

NanoID może być używany bezpośrednio w przeglądarce poprzez import CDN. Nie wymagany krok budowania dla szybkiego prototypowania.

JavaScript
// 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

Python
# pip install nanoid
from nanoid import generate

generate()              # → "V1StGXR8_Z5jdHi6B-myT"
generate(size=8)        # → "Uakgb_J5"
generate('0123456789abcdef', 16)  # custom alphabet + size

Node.js (CommonJS)

JavaScript
// 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
}

Często zadawane pytania

Czy NanoID jest kryptograficznie bezpieczny?
Tak — przy użyciu domyślnego importu NanoID generuje identyfikatory przy użyciu CSPRNG na poziomie systemu operacyjnego (crypto.getRandomValues w przeglądarkach, crypto.randomFillSync w Node.js). To to samo źródło entropii co dla generowania kluczy kryptograficznych. Wartości NanoID nadają się do tokenów sesji, kluczy API i innych identyfikatorów wrażliwych na bezpieczeństwo.
Czy mogę użyć NanoID jako klucza głównego w bazie danych?
Tak. Ciągi NanoID są bezpieczne dla URL i mogą być przechowywane jako kolumny CHAR lub VARCHAR. Jednak NanoID nie ma komponentu znacznika czasu, więc identyfikatory nie są sortowalne według kolejności generowania — spowoduje to fragmentację indeksu B-tree przy wysokich wskaźnikach wstawiania, podobnie jak UUID v4. Dla kluczy głównych posortowanych według czasu użyj ULID lub UUID v7.
Jak NanoID porównuje się z crypto.randomUUID()?
Oba używają CSPRNG i zapewniają silną losowość. crypto.randomUUID() jest natywny (brak zależności), produkuje 36-znakowe ciągi UUID v4 z myślnikami i jest powszechnie rozpoznawany przez bazy danych i API. NanoID wymaga pakietu npm, ale produkuje krótsze ciągi (domyślnie 21 znaków) z konfigurowalnym alfabetem. W większości przypadków preferuj crypto.randomUUID(), aby uniknąć zależności.
Co się stanie, jeśli użyję bardzo krótkiego NanoID?
Krótkie identyfikatory (np. 6–8 znaków) mają znacznie wyższe prawdopodobieństwo kolizji. 6-znakowy NanoID z domyślnego 64-znakowego alfabetu ma tylko ~68 miliardów możliwych wartości — odpowiedni dla kilku tysięcy identyfikatorów, zanim ryzyko kolizji stanie się nietrywalne. Użyj powyższej tabeli prawdopodobieństwa kolizji, aby wybrać odpowiedni rozmiar dla oczekiwanego wolumenu identyfikatorów.
Czy mogę użyć NanoID w przeglądarce bez npm?
Tak. NanoID obsługuje importy ESM z CDN (np. jsDelivr lub esm.sh). Importuj jako moduł w tagu script z type="module". Jest to przydatne do szybkiego prototypowania, ale nie zalecane do produkcji — zablokuj do konkretnej wersji i rozważ samodzielne hostowanie skryptu.
Czy NanoID działa we wszystkich środowiskach?
NanoID działa we wszystkich nowoczesnych przeglądarkach, Node.js, Deno, Bun, Cloudflare Workers i Vercel Edge Functions. Dla React Native wymagany jest polyfill dla getRandomValues (react-native-get-random-values). Biblioteka jest zaprojektowana tak, aby być niezależna od środowiska i automatycznie wykrywa dostępne API crypto.