Skip to Content
Api ReferenceCustom Alphabet

Last Updated: 3/9/2026


customAlphabet()

Create a custom ID generator with your own alphabet and default size.

Signature

function customAlphabet<Type extends string>( alphabet: string, defaultSize?: number ): (size?: number) => Type

Parameters

alphabet (required)

  • Type: string
  • Constraints: Must be ≤256 characters
  • Description: Characters to use for ID generation

defaultSize (optional)

  • Type: number
  • Default: 21
  • Description: Default length of generated IDs

Return Value

Returns a generator function:

(size?: number) => string

The generator function:

  • Accepts optional size parameter (overrides defaultSize)
  • Returns a random ID string using the custom alphabet

Examples

Numbers Only

import { customAlphabet } from 'nanoid' const nanoid = customAlphabet('1234567890', 10) console.log(nanoid()) //=> "4926581703" console.log(nanoid()) //=> "8201374650"

Hexadecimal

import { customAlphabet } from 'nanoid' const hexId = customAlphabet('0123456789abcdef', 16) console.log(hexId()) //=> "4f90d13a42b8c7e1"

Uppercase Letters

import { customAlphabet } from 'nanoid' const upperId = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 8) console.log(upperId()) //=> "KXZMRTQP"

No Ambiguous Characters

import { customAlphabet } from 'nanoid' // Remove 0, O, I, l for human-readable codes const nanoid = customAlphabet('346789ABCDEFGHJKLMNPQRTUVWXY', 8) console.log(nanoid()) //=> "6RTUVWXY"

Override Default Size

import { customAlphabet } from 'nanoid' const nanoid = customAlphabet('1234567890', 10) // Use default size console.log(nanoid()) //=> "4926581703" (10 chars) // Override size console.log(nanoid(5)) //=> "48267" (5 chars) console.log(nanoid(15)) //=> "492658170348267" (15 chars)

Use Cases

Human-Readable Codes

import { customAlphabet } from 'nanoid' // Unambiguous characters for support tickets const ticketId = customAlphabet('23456789ABCDEFGHJKLMNPQRSTUVWXYZ', 8) const ticket = { id: ticketId(), //=> "3KJRT8XY" subject: 'Login issue', status: 'open' }

Numeric IDs

import { customAlphabet } from 'nanoid' const numericId = customAlphabet('0123456789', 12) const order = { orderNumber: numericId(), //=> "849201736584" total: 99.99 }

URL-Safe Slugs (Lowercase)

import { customAlphabet } from 'nanoid' const slug = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 12) const article = { slug: slug(), //=> "k3xm9tn2pq7z" title: 'Getting Started' }

Base32 Encoding

import { customAlphabet } from 'nanoid' // RFC 4648 Base32 alphabet const base32Id = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', 16) console.log(base32Id()) //=> "3KJRT8XY2MN4PQ7Z"

Alphabet Design

Best Practices

Do:

  • Use ≤256 characters (security requirement)
  • Remove ambiguous characters for human-readable IDs (0/O, 1/I/l)
  • Consider case sensitivity of your system
  • Test alphabet in your use case (URLs, databases, etc.)

Don’t:

  • Use >256 characters (breaks security guarantees)
  • Include special characters that need URL encoding
  • Use characters that look similar (reduces readability)

Common Alphabets

import { customAlphabet } from 'nanoid' // Digits only const digits = '0123456789' // Lowercase hex const hex = '0123456789abcdef' // Alphanumeric (case-insensitive) const alphanumeric = '0123456789abcdefghijklmnopqrstuvwxyz' // Alphanumeric (case-sensitive) const alphanumericMixed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' // No ambiguous characters const unambiguous = '346789ABCDEFGHJKLMNPQRTUVWXYabcdefghjkmnpqrtuvwxy' // Base32 (RFC 4648) const base32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' // Base64 URL-safe const base64url = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'

For more alphabets, see nanoid-dictionary.

Security Considerations

Alphabet Size Limit

⚠️ Must be ≤256 characters:

// ✅ OK: 64 characters const nanoid = customAlphabet('A-Za-z0-9_-', 21) // ❌ INSECURE: 300 characters const nanoid = customAlphabet('...300 chars...', 21) // Breaks security!

Alphabets >256 characters compromise the internal random generation algorithm.

Collision Probability

Smaller alphabets increase collision risk:

Alphabet SizeID SizeEntropyIDs for 1% Collision
10 (digits)1033 bits~6,000
16 (hex)1664 bits~5 billion
32 (base32)20100 bits~1.2 trillion
64 (default)21126 bits~2.8 quintillion

Always use the collision calculator  with your alphabet size and expected ID count.

Random Generation

customAlphabet() uses the same secure random generation as nanoid():

  • Cryptographically secure
  • Hardware random generator
  • Uniform distribution (rejection sampling)

Performance

Benchmarks

nanoid() 3,693,964 ops/sec (baseline) customAlphabet() 2,799,255 ops/sec (24% slower)

Slower due to rejection sampling for non-power-of-2 alphabet sizes

Optimization Tips

  1. Use power-of-2 alphabet sizes for best performance:

    • 2, 4, 8, 16, 32, 64, 128, 256 characters
    • No rejection sampling needed
  2. Reuse generator function:

    // ✅ Good: Create once const nanoid = customAlphabet('0123456789', 10) for (let i = 0; i < 1000; i++) { const id = nanoid() // Fast } // ❌ Bad: Create every time for (let i = 0; i < 1000; i++) { const id = customAlphabet('0123456789', 10)() // Slow }

Non-Secure Variant

For non-cryptographic use cases:

import { customAlphabet } from 'nanoid/non-secure' const nanoid = customAlphabet('0123456789', 10) console.log(nanoid()) //=> "4926581703"

⚠️ Warning: Uses Math.random() instead of crypto. See Non-Secure API.

Common Mistakes

❌ Don’t exceed 256 characters

// WRONG: Breaks security const nanoid = customAlphabet('...300 characters...', 21) // ❌

❌ Don’t forget to call the returned function

import { customAlphabet } from 'nanoid' // WRONG: nanoid is the generator function, not an ID const nanoid = customAlphabet('0123456789', 10) console.log(nanoid) //=> [Function] ❌ // CORRECT: Call the function to generate ID const id = nanoid() console.log(id) //=> "4926581703" ✅

❌ Don’t use special characters without testing

// WRONG: May cause issues in URLs const nanoid = customAlphabet('!@#$%^&*()', 10) // ❌ Needs URL encoding // CORRECT: Use URL-safe characters const nanoid = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', 10) // ✅

See Also