π UCID stands for Unique Custom ID, the easiest, fastest, and most customizable ID generator you'll ever meet!
Because it's...
- πΏ Compact β Zero dependencies!
- πͺΆ Lightweight β Less than 50kb!
- π§ Simple β Just call a single function and boom π₯: instant ID!
- π Secure β Fresh, unique IDs every. single. time.
- π CLI β spin up IDs faster than you can blink!
UCID runs independently without any dependencies β just pure JavaScript magic β¨.
If you use the default options, even if you generate 1 BILLION IDs PER SECOND, you'd need hundreds of millions of years to have a meaningful chance of a collision. Sounds unbelievable? Letβs do the math:
ID Format: xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx
Character Set: 36 characters (0β9
, aβz
)
Length: 32 characters
Randomness Source: Cryptographically secure (crypto.randomBytes
)
36^32 β 6.334 Γ 10^49
- IDs per second: 1,000,000,000
- Seconds per year: 60 Γ 60 Γ 24 Γ 365 = 31,536,000
- IDs per year: 1 Γ 10^9 Γ 31,536,000 = 3.1536 Γ 10^16
β(36^32) = 36^16 β 7.961 Γ 10^24
7.961 Γ 10^24 Γ· 3.1536 Γ 10^16 β 252,443,706 years
Using cryptographically secure randomness, your custom 32-character base36 ID format would take ~252 million years of generating 1 BILLION IDs PER SECOND to reach a 50% chance of collision.
This makes it EXTREMELY SAFE for any real-world application. Offers greater collision resistance than UUID v4 (~82 thousand years of generating 1 BILLION IDs PER SECOND) thanks to a larger entropy space (6.334 Γ 10^49), powered by cryptographically secure randomness.
npm install unique-custom-id
ES Modules:
import ucid from 'unique-custom-id';
CommonJS:
const ucid = require('unique-custom-id');
const id = ucid();
console.log(id);
// Result: dzcmj4dt-7zcqaoo0-t1mtis3v-3dh7r59v
UCID isnβt just easy β itβs flexible too! Customize your ID like a pro π οΈ
Control letter casing:
lowercase
:true
by defaultuppercase
:false
by default
ucid({
uppercase: true,
});
// Result: TevajtrU-Eei8SnWa-0EZqr6NE-jMAHX0D6
ucid({
uppercase: true,
lowercase: false,
});
// Result: FFJL9DAO-V3YPLZ2V-252L7URX-XCS3GWP5
Toggle digits or symbols:
numbers
:true
by defaultsymbols
:false
by default
ucid({
symbols: true,
});
// Result: 5w55an#e-kw7bw7f3-7iomwp#o-dd79$yf1
ucid({
numbers: false,
});
// Result: jueldfjw-ljhiphtl-ajuptedx-rramdwne
Set how many segments (octets) the ID should have. Default: 4
.
ucid({
octets: 3,
});
// Result: 4nlwrx87-fi65iq27-43wh2s05
ucid({
octets: 6,
});
// Result: hr5bg68k-ycxqfb1o-pkofgsm2-j6hnimgy-ehcxulnl-ptmvuf3j
Define how long each octet should be. Default: 8
.
ucid({
octetLength: 4,
});
// Result: k6ue-bvfq-fc99-oe07
ucid({
octetLength: 12,
});
// Result: nz4kkg3jxxot-9v9bmx6y8ngt-x4ciymz48z9d-mqopg9mad4v2
Use a custom character set to generate your ID:
ucid({
includeOnly: '1234567890abcdef',
});
// Result: f800cdb7-0082b1b8-f0736eb3-4b16949a
Add timestamp to your ID. Either prefix
or suffix
.
prefix
: before the ID. Aliases:prefix
,p
,pre
,pref
suffix
: after the ID. Aliases:suffix
,s
,suf
,suff
ucid({
timestamp: 'prefix', // `p`, `pre` or `pref` works too
});
// Result: 20250904-k0ebaf6m-j31g7koc-b25p0p2n-u9iah5i4
ucid({
timestamp: 'suff',
});
// Result: 05mdc0cp-6k6xvl9c-mgc7s9e3-t98ckh3f-20250904
Controls how the timestamp is formatted.
You can use whatever format you like. yyyy-mm-dd, mm-dd-yy, however you like it, with additional predefined formats:
- unix / epoch
- military
- iso
- utc
- rfc (rfc3339)
- filetime / winft (Windows FILETIME)
ucid({
octets: 3,
timestamp: 's',
timestampFormat: 'dd-mm-yyyy-hh:mm:ss:ms',
});
// Result: gtrf9t1h-u00ycxuw-mxzhjuty-04-09-2025-12:09:00:39
ucid({
octets: 3,
timestamp: 'p',
timestampFormat: 'unix',
});
// Result: 1756976740-61p0xk4r-1ad6fg3l-gxwsgpgk
Customize the character(s) used to separate octets. Default: "-"
ucid({ octetSeparator: '=' });
// Result: pro9mns=odvhrd3i=28e2mqzg=t3n530m9
ucid({ octetSeparator: '~' });
// Result: qm09extn~dy7s1bd1~t6fl9q2g~mv352ie4
Set the exact length of each octet individually.
ucid({
octets: 3,
octetFormat: '352',
});
// Result: h0c-hgkf0-k9
ucid({
octets: 4,
octetFormat: [2, 4, 6, 8],
});
// Result: cb-udw8-e6m4wt-i9kim7xb
ucid({
octets: 2,
octetFormat: 49,
});
// Result: pr3e-piis0fdy9
Generate id with predefined formats. Many of them have aliases.
- uuid / uuidv4 / universal / universal-id
- sha / sha1
- sha256
- objectid / object / object-id
- ulid
- nanoid / nano-id / nano
- ksuid
- cuid
- snowflake / snowflake-id
ucid({
idFormat: 'uuid' // uuidv4, universal also works
});
// Result: fab50a3a-bb8f-ff37-434b-5bbcd94d1167
ucid({
idFormat: 'sha' // sha1 also works
});
// Result: f1e1a9ae50951ff9d68b82743095a3ab273ebe97
ucid({
idFormat: 'nanoid' // nano also works
})
// Result: HQMFVMRMCkXIvtLWhT8ty
Number of IDs to generate.
ucid({
instances: 3,
});
/*
Result: [
'9v7z1v59-0v28lo6h-8g5qpnhk-dx5f6412',
'5689u3lw-ns4wk8sc-u57bgwxz-nm9r8ydf',
'ul7pdyya-bgubmkef-zlpp7b79-7v2oo5dq'
]
*/
ucid({
octets: 4,
octetFormat: [2, 4, 6, 8],
instances: 5,
});
/*
Result: [
'rd-c0ix-mtifus-z7ibcbip',
'l6-gngn-1v04eg-do2yei8v',
'kf-fprl-klp5bw-o7gcv39u',
'tm-v4hq-8h964i-cnpswp29',
'uq-iwcb-u44bey-yj0nvs98'
]
*/
- Use
%id
as a placeholder to inject generated IDs into custom strings. - Use
%ts
as a placeholder to inject timestamp into custom strings.
ucid({
octets: 1,
octetLength: 8,
includeOnly: '1234567890abcdef',
template: 'user-%id-session-%id',
});
// Result: user-1a97ada5-session-ec64776c
ucid({
octets: 1,
octetLength: 8,
includeOnly: '1234567890abcdef',
template: 'user-%id-at-%ts',
});
// Result: user-26001cde-at-20250903
Add static strings before or after your ID.
ucid({
prefix: 'ID-',
suffix: '-done',
});
// Result: ID-k0ebaf6m-j31g7koc-b25p0p2n-u9iah5i4-done
Returns a full object instead of just the generated ID string.
If verbose
is true
, UCID will return an object containing the generated ID and other options that were passed in.
This is especially useful for logging, debugging, testing, or introspection. Default: false
ucid({
octets: 3,
octetLength: 12,
includeOnly: '1234567890abcdef',
verbose: true,
});
/*
Result: {
ucid: '795ebe1fd531-dbf06d32bd02-f512ad09e84a',
octets: 3,
uppercase: false,
lowercase: true,
octetLength: 12,
octetFormat: '',
numbers: true,
octetSeparator: '-',
symbols: false,
includeOnly: '1234567890abcdef',
template: null,
prefix: '',
suffix: '',
verbose: true
}
*/
Function to customize each octet further than other options.
ucid({
octets: 2,
octetLength: 8,
includeOnly: '1234567890abcdef',
customize: (octet, i) => (i % 2 ? octet.toUpperCase() : octet.toLowerCase()),
});
// Result: 80a1a368-A738C260-32eaf5e3-3AF2803F
ucid({
octets: 3,
octetLength: 6,
includeOnly: '1234567890abcdef',
customize: (octet, i) =>
i == 0 ? `user-${octet}` : i == 1 ? `session-${octet}` : `${i}${octet}`,
});
// Result: user-81cd0a-session-13634d-212fb85
Optional function that acts as a gate before UCID generation begins.
It must call resolve()
to allow generation or reject(msg)
to skip it.
If reject()
is called, UCID generation is aborted, and the ucid function returns undefined
.
If reject()
is passed an Error
object, it will be thrown. Otherwise, the error message is logged.
// Allow generation only in production
ucid({
condition: (resolve, reject) =>
process.env.NODE_ENV === 'production'
? resolve()
: reject('UCID generation is disabled in non-production environments.'),
});
// Check authentication
ucid({
condition: (resolve, reject) =>
auth?.currentUser?.email
? resolve()
: reject(new Error('User must be authenticated.')),
});
We love contributions! π
If youβre thinking about improving UCID, fixing a bug, or just having fun, make sure to read the contributing guide before you start. Itβs got everything you need to know to get up and running! π
UCID is built for security, flexibility, and speed β perfect for devs who want secure and customizable identifiers in milliseconds.
const magic = ucid();
console.log(`β¨ Your shiny new ID: ${magic}`);