Nanoid
Nanoid is a tiny, secure, URL-friendly unique string ID generator. It uses a URL-safe alphabet (A-Za-z0-9_-) and generates 21-character IDs by default with 126 bits of entropy - equivalent to UUID collision resistance but in a more compact format.
When to Use
Use Nanoid when you need:
URL-safe IDs - No special characters, ready for URLs
Compact format - 21 characters vs UUID’s 36
Custom alphabets - Generate hex, numeric, or custom character sets
High entropy - 126 bits of randomness (comparable to UUID)
Nanoid is NOT time-ordered . For sortable IDs, use UUID v7 or ULID instead.
Basic Usage
import { nanoid } from 'uniku/nanoid'
const id = nanoid ()
// => "V1StGXR8_Z5jdHi6B-myT"
// Custom size
const shortId = nanoid ( 10 )
// => "IRFa-VaY2b"
API Reference
Main Function
Generate a 21-character nanoid using the default URL-safe alphabet. Ultra-fast path - uses simple random byte pooling for best performance.
Generate a nanoid of custom length using the default URL-safe alphabet. Parameters:
size - Length of generated ID (0-2048, default: 21)
nanoid(options)
(options: NanoidOptions) => string
Generate a nanoid with custom options. Options:
size?: number - ID length (0-2048, default: 21)
alphabet?: string - Custom alphabet (2-256 printable ASCII characters)
random?: Uint8Array - Custom random bytes for deterministic testing
Static Methods
nanoid.isValid(id)
(id: unknown) => id is string
Validate that a value is a properly formatted nanoid string. TypeScript type guard. Important: Only validates IDs against the default URL-safe alphabet (A-Za-z0-9_-). IDs generated with custom alphabets cannot be validated with this method.nanoid . isValid ( "V1StGXR8_Z5jdHi6B-myT" ) // true
nanoid . isValid ( "not-a-nanoid!" ) // false
Constants
The default URL-safe alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-" import { URL_ALPHABET } from 'uniku/nanoid'
console . log ( URL_ALPHABET . length ) // 64
No Binary Conversion: Unlike UUID and ULID, nanoid does not provide toBytes/fromBytes methods because it is a string-native format with no canonical binary representation.
Custom Alphabets
Nanoid supports custom alphabets for specialized use cases:
Hexadecimal IDs
import { nanoid } from 'uniku/nanoid'
const hexId = nanoid ({
alphabet: '0123456789abcdef' ,
size: 12
})
// => "4f90d13a42bc"
Numeric-Only IDs
import { nanoid } from 'uniku/nanoid'
const numericId = nanoid ({
alphabet: '0123456789' ,
size: 10
})
// => "8234567901"
Lowercase Only
import { nanoid } from 'uniku/nanoid'
const lowerCaseId = nanoid ({
alphabet: 'abcdefghijklmnopqrstuvwxyz' ,
size: 16
})
// => "kpqrnwxyzabcdefg"
Custom Characters
import { nanoid } from 'uniku/nanoid'
// Using emoji (for fun - not recommended for production)
const emojiId = nanoid ({
alphabet: '😀😃😄😁😆😅😂🤣' ,
size: 8
})
// Note: Multi-byte characters work but increase size
Alphabet Requirements:
Must contain 2-256 characters
Only printable ASCII characters (codes 32-126)
No duplicate characters
Power-of-2 lengths (2, 4, 8, 16, 32, 64, 128, 256) are fastest - no rejection sampling needed
Real-World Examples
URL Shortener
import { nanoid } from 'uniku/nanoid'
interface ShortUrl {
id : string
originalUrl : string
createdAt : Date
}
function shortenUrl ( originalUrl : string ) : ShortUrl {
return {
id: nanoid ( 8 ), // 8 characters = ~47 bits of entropy
originalUrl ,
createdAt: new Date ()
}
}
// Usage: https://example.com/s/IRFa-VaY
Session Tokens
import { nanoid } from 'uniku/nanoid'
// Generate secure session tokens
const sessionToken = nanoid ( 32 ) // Extra security with 32 characters
// => "V1StGXR8_Z5jdHi6B-myT9fK3nL7pQ8"
await redis . set ( `session: ${ sessionToken } ` , userId , 'EX' , 3600 )
Invite Codes
import { nanoid } from 'uniku/nanoid'
// Generate readable invite codes (uppercase + numbers only)
const inviteCode = nanoid ({
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ,
size: 8
})
// => "K7M3P2N5"
await db . insert ( 'invites' , {
code: inviteCode ,
email: '[email protected] '
})
File Upload IDs
import { nanoid } from 'uniku/nanoid'
async function uploadFile ( file : File ) {
const fileId = nanoid ()
const extension = file . name . split ( '.' ). pop ()
const filename = ` ${ fileId } . ${ extension } `
await s3 . upload ({
Key: `uploads/ ${ filename } ` ,
Body: file
})
return `https://cdn.example.com/uploads/ ${ filename } `
}
Correlation IDs
import { nanoid } from 'uniku/nanoid'
app . use (( req , res , next ) => {
// Short correlation ID for logs
req . correlationId = nanoid ( 10 )
res . setHeader ( 'X-Correlation-ID' , req . correlationId )
next ()
})
app . get ( '/api/users' , ( req , res ) => {
logger . info ( 'Fetching users' , { correlationId: req . correlationId })
// ...
})
Testing with Deterministic Output
import { nanoid } from 'uniku/nanoid'
// Provide custom random bytes for reproducible tests
const testId = nanoid ({
size: 10 ,
random: new Uint8Array ([ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ])
})
// => "ABCDEFGHIJKmnop" (deterministic for testing)
Type Definitions
type NanoidOptions = {
/**
* Random bytes for deterministic output (testing).
* For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256):
* exactly `size` bytes needed.
* For other alphabets: ~size * 2 bytes needed (rejection sampling).
*/
random ?: Uint8Array
/**
* Custom alphabet to use. Default: URL-safe A-Za-z0-9_-
* Must be 2-256 printable ASCII characters (32-126) with no duplicates.
*/
alphabet ?: string
/**
* Length of generated ID. Default: 21. Maximum: 2048.
*/
size ?: number
}
type Nanoid = {
/** Generate nanoid with default settings */
() : string
/** Generate nanoid with custom size */
( size : number ) : string
/** Generate nanoid with options */
( options : NanoidOptions ) : string
/**
* Validate a nanoid string against the default URL-safe alphabet.
* Note: Does not validate IDs generated with custom alphabets.
*/
isValid ( id : unknown ) : id is string
}
Power-of-2 Alphabets Fastest - Direct byte mapping, no rejectionExamples: 2, 4, 8, 16, 32, 64, 128, 256 characters
Non-Power-of-2 Slower - Uses rejection samplingExamples: 10 (numeric), 26 (lowercase), 36 (alphanumeric)
The default 64-character URL-safe alphabet is optimized (power-of-2) for maximum performance.
Collision Probability
Default 21 characters:
~126 bits of entropy
Need ~2^63 IDs for 1% collision probability
Similar to UUID v4 (122 bits)
Size recommendations:
8 chars (~47 bits): URL shorteners, temporary IDs
10 chars (~59 bits): Session tokens, invite codes
21 chars (default, ~126 bits): General purpose, high security
32 chars (~189 bits): Maximum security, cryptographic use
Generation Speed Comparable to nanoid npm package (both use optimized pooling)
Size 42% shorter than UUID (21 vs 36 characters)
Entropy 126 bits (default) - same collision resistance as UUID
URL-Safe No special encoding needed in URLs
Bundle Size: ~938 bytes minified + gzipped
Validation Pattern
Default alphabet nanoid must match:
Key characteristics:
Only contains A-Z, a-z, 0-9, _, and -
Any length > 0
Custom alphabet validation not supported
Migration Guide
From nanoid Package
- import { nanoid } from 'nanoid'
+ import { nanoid } from 'uniku/nanoid'
const id = nanoid()
API is identical - drop-in replacement.
From shortid Package
- import shortid from 'shortid'
+ import { nanoid } from 'uniku/nanoid'
- const id = shortid.generate()
+ const id = nanoid(10) // shortid default is ~10 chars
Benefit: Cryptographically secure, no deprecated dependencies.
For time-ordered IDs that maintain chronological sorting, consider ULID or UUID v7 .