ToolDeck

เครื่องสร้าง NanoID

สร้าง ID ที่ไม่ซ้ำกันขนาดเล็กและปลอดภัยสำหรับ URL พร้อมตัวอักษรที่กำหนดเอง

ตัวอักษร

ขนาด

จำนวน

คลิกสร้างเพื่อสร้าง NanoID

NanoID คืออะไร?

NanoID คือ random ID generator ขนาดเล็ก เร็ว และ URL-safe ตามค่าเริ่มต้นสร้าง string 21 ตัวอักษรโดยใช้ alphabet 64 ตัวอักษร (A-Za-z0-9_-) ให้ entropy ประมาณ 126 บิต — เทียบเท่า UUID v4 122 บิตแต่ใน string ที่สั้นกว่า

NanoID ไม่ฝัง timestamp หรือข้อมูลที่มีโครงสร้างใดๆ ทุก ID เป็นสุ่มล้วน สร้างจาก cryptographically secure random number generator ของระบบปฏิบัติการ (crypto.getRandomValues() ในเบราว์เซอร์, crypto.randomBytes() ใน Node.js)

NanoID vs UUID v4

NanoID และ UUID v4 ทั้งคู่เป็น random ID generator ที่ใช้ CSPRNG แตกต่างกันในรูปแบบ ความยาว และการรองรับของระบบนิเวศ:

คุณสมบัติNanoID (ค่าเริ่มต้น)UUID v4
FormatAlphanumeric URL-safe + _-Hexadecimal พร้อมขีดกลาง
ความยาว21 ตัวอักษร (ค่าเริ่มต้น)36 ตัวอักษร
Entropy~126 บิต122 บิต
URL-safeใช่ — ไม่ต้องการการ encodeใช่ (พร้อมขีดกลาง)
Alphabet64 ตัวอักษร (A-Za-z0-9_-)16 ตัวอักษร (0-9a-f)
Dependenciesต้องการ npm packageNative (crypto.randomUUID)
ปรับแต่งได้ใช่ — ความยาวและ alphabetไม่
มาตรฐานไม่มี (community library)RFC 4122 / RFC 9562

เลือก UUID v4 เมื่อความสามารถทำงานร่วมกับระบบภายนอกสำคัญ — ฐานข้อมูลที่มี UUID column แบบ native, API ที่คาดหวัง UUID format หรือโครงสร้างพื้นฐาน logging ที่ parse UUID เลือก NanoID เมื่อต้องการ ID ที่สั้นกว่าและควบคุม stack ทั้งหมด

ความน่าจะเป็นของ Collision ตามขนาด

ความน่าจะเป็น collision ของ NanoID ขึ้นอยู่กับความยาว ID และอัตราการสร้าง ตารางต่อไปนี้ใช้ alphabet 64 ตัวอักษรเริ่มต้น:

ขนาด (ตัวอักษร)ID ที่เป็นไปได้ความปลอดภัยจาก collision
664~1 ใน 4.5B — ปลอดภัยสำหรับ ID ไม่กี่พัน
864~1 ใน 4.5T — ปลอดภัยสำหรับ ID หลายล้าน
1164~1 ใน 2.8 quadrillion — ปลอดภัยสำหรับ ID หลายพันล้าน
1664~1 ใน 1.2 × 10^19 — ปลอดภัยสำหรับ ID หลายล้านล้าน
2164~1 ใน 10^30 — ปลอดภัยสำหรับ 100 พันล้าน ID ต่อวันเป็นศตวรรษ
3264เทียบเท่า UUID v4 (122 บิต)
3636เกินกว่า UUID v4

ขนาดเริ่มต้น 21 ตัวอักษร ถูกเลือกให้ตรงกับการต้านทาน collision ของ UUID v4 (~126 บิต) ในขณะที่สั้นกว่า 41% สำหรับแอปพลิเคชันส่วนใหญ่ 21 ตัวอักษรเป็นตัวเลือกที่ถูกต้อง

Alphabet แบบกำหนดเอง

alphabet ของ NanoID ปรับแต่งได้อย่างสมบูรณ์ library รับ string ตัวอักษรที่ไม่ซ้ำใดก็ตามเป็น alphabet และสร้าง ID โดยใช้เฉพาะตัวอักษรเหล่านั้น:

ตัวเลขเท่านั้นA-Za-z0-9_-
ใช้ '0123456789' สำหรับ ID ที่เป็นตัวเลขทั้งหมด มีประโยชน์สำหรับ SMS code หรือ identifier แบบ PIN
Lowercase hexA-Za-z0-9
ใช้ '0123456789abcdef' สำหรับ hex string ที่กระชับโดยไม่มีรูปแบบ UUID ขีดกลาง
อ่านได้ง่าย0-9a-f
ยกเว้นตัวอักษรที่สับสนทางภาพ (0, O, 1, I, l) สำหรับ ID ที่ผู้ใช้อาจต้องพิมพ์ด้วยตนเอง
Domain กำหนดเอง0-9
ใช้ชุดตัวอักษรใดก็ตามที่เหมาะกับแอปพลิเคชันของคุณ เช่น เฉพาะสระ+พยัญชนะสำหรับ ID ที่ออกเสียงได้

สำคัญ: ใช้ nanoid/non-secure เฉพาะสำหรับแอปพลิเคชันที่ไม่ sensitive ด้านความปลอดภัย (เช่น UI element ID) สำหรับ ID ใดๆ ที่ต้องไม่สามารถเดาได้ ให้ใช้ default secure import เสมอ

NanoID สร้างความสุ่มอย่างไร

NanoID ใช้ cryptographically secure pseudo-random number generator (CSPRNG) ของระบบปฏิบัติการ ในเบราว์เซอร์คือ crypto.getRandomValues(); ใน Node.js คือ crypto.randomFillSync() นี่คือแหล่ง entropy เดิมที่ใช้สำหรับ TLS session key — แข็งแกร่งกว่า Math.random() อย่างมาก

Rejection Sampling (หลีกเลี่ยง Modulo Bias)

วิธีที่ไม่ซับซ้อนในการสร้างตัวอักษรสุ่มคือ: รับ byte สุ่ม (0–255) และคำนวณ byte % alphabetSize วิธีนี้ทำให้เกิด modulo bias — ตัวอักษรบางตัวปรากฏบ่อยกว่าตัวอื่นเล็กน้อยเมื่อขนาด alphabet ไม่หารลงตัวด้วย 256

NanoID กำจัด bias นี้โดยใช้ rejection sampling:

  1. กำหนด power-of-two mask ที่เล็กที่สุดที่ครอบคลุมขนาด alphabet (เช่น สำหรับ alphabet 64 ตัวอักษร mask คือ 63 = 0b00111111)
  2. สร้าง byte สุ่มและใช้ mask: byte & mask
  3. หากค่าที่ mask แล้วอยู่ในช่วง alphabet ให้ใช้ มิฉะนั้นทิ้งและลองใหม่

ซึ่งหมายความว่า byte สุ่มบางตัวถูก ทิ้ง แต่ผลลัพธ์คือการกระจายที่สม่ำเสมอสมบูรณ์แบบบน alphabet — ไม่มีตัวอักษรใดที่น่าจะเป็นมากกว่าตัวอื่น

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"

การรองรับสภาพแวดล้อม

Browser
เบราว์เซอร์สมัยใหม่ (Chrome 37+, Firefox 34+, Safari 7+) — ใช้ crypto.getRandomValues()
Node.js 14+
Node.js 14.18+ — ใช้ crypto.randomFillSync()
Deno
Deno — ใช้ crypto.getRandomValues()
Bun
React Native — ใช้ expo-crypto หรือ polyfill react-native-get-random-values
Edge / Cloudflare Workers
Edge runtime (Cloudflare Workers, Vercel Edge) — Web Crypto API มีให้ใช้
React Native
Bun — รองรับ crypto แบบ native

ตัวอย่างโค้ด

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"

Browser (CDN)

NanoID สามารถใช้โดยตรงในเบราว์เซอร์ผ่าน CDN import ไม่ต้องมี build step สำหรับ prototype อย่างรวดเร็ว

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
}

คำถามที่พบบ่อย

NanoID มีความปลอดภัยทางการเข้ารหัสไหม?
ใช่ — เมื่อใช้ default import NanoID สร้าง ID โดยใช้ OS-level CSPRNG (crypto.getRandomValues ในเบราว์เซอร์, crypto.randomFillSync ใน Node.js) นี่คือแหล่ง entropy เดิมที่ใช้สำหรับการสร้าง cryptographic key ค่า NanoID เหมาะสำหรับ session token, API key และ identifier ที่ sensitive ด้านความปลอดภัยอื่นๆ
สามารถใช้ NanoID เป็น database primary key ได้ไหม?
ใช่ NanoID string เป็น URL-safe และสามารถเก็บเป็น column CHAR หรือ VARCHAR ได้ อย่างไรก็ตาม NanoID ไม่มี timestamp component ดังนั้น ID ไม่เรียงลำดับตาม generation order — จะทำให้ B-tree index แตกกระจายที่อัตรา insert สูง คล้ายกับ UUID v4 สำหรับ primary key ที่เรียงตามเวลา ใช้ ULID หรือ UUID v7 แทน
NanoID เปรียบกับ crypto.randomUUID() อย่างไร?
ทั้งคู่ใช้ CSPRNG และให้ความสุ่มที่แข็งแกร่ง crypto.randomUUID() เป็น native (ไม่มี dependency) สร้าง UUID v4 string พร้อมขีดกลาง 36 ตัวอักษร และได้รับการยอมรับจากฐานข้อมูลและ API ทั่วไป NanoID ต้องการ npm package แต่สร้าง string ที่สั้นกว่า (21 ตัวอักษรเริ่มต้น) พร้อม alphabet ที่ปรับแต่งได้ สำหรับกรณีส่วนใหญ่ แนะนำ crypto.randomUUID() เพื่อหลีกเลี่ยง dependency
จะเกิดอะไรขึ้นหากใช้ NanoID ที่สั้นมาก?
ID สั้น (เช่น 6–8 ตัวอักษร) มีความน่าจะเป็น collision สูงกว่ามาก NanoID 6 ตัวอักษรจาก alphabet 64 ตัวอักษรเริ่มต้นมีค่าที่เป็นไปได้เพียง ~68 พันล้านค่า เหมาะสำหรับ ID ไม่กี่พันก่อนที่ความเสี่ยง collision จะกลายเป็นสิ่งที่ต้องระวัง ใช้ตาราง collision probability ด้านบนเพื่อเลือกขนาดที่เหมาะสมสำหรับปริมาณ ID ที่คาดหวัง
สามารถใช้ NanoID ในเบราว์เซอร์โดยไม่ต้องใช้ npm ได้ไหม?
ใช่ NanoID รองรับ ESM import จาก CDN (เช่น jsDelivr หรือ esm.sh) import เป็น module ใน script tag ที่มี type='module' มีประโยชน์สำหรับ prototype อย่างรวดเร็วแต่ไม่แนะนำสำหรับ production — กำหนด version เฉพาะและพิจารณา self-hosting script
NanoID ทำงานได้ในทุกสภาพแวดล้อมไหม?
NanoID ทำงานได้ในเบราว์เซอร์สมัยใหม่ทั้งหมด, Node.js, Deno, Bun, Cloudflare Workers และ Vercel Edge Functions สำหรับ React Native ต้องการ polyfill สำหรับ getRandomValues (react-native-get-random-values) library ออกแบบให้ไม่ขึ้นกับสภาพแวดล้อมและตรวจจับ crypto API ที่มีอยู่โดยอัตโนมัติ