Search packages, repositories and app categories

GitHub repositorypasssy/nanoid2

nanoid2

passsy/nanoid2 open-source repository details.

nanoid2 project cover
Stars
12
Forks
1
Last push (UTC)
Sep 6, 2026
Project status
Active

Original README

English project snapshot. Visit GitHub for the latest content.

nanoid2

Nano ID logo by Anton Lovchikov

pub

Dart implementation of ai/nanoid.

This is a fork of package:nanoid with a more Dart-like API.

Install

dart pub add nanoid2

Usage

import 'package:nanoid2/nanoid2.dart';

void main() {
  final id = nanoid(); 
  // => LXL0J9b-Uj1C0sZH837Fk
  // 21 characters
}
Custom length
import 'package:nanoid2/nanoid2.dart';

void main() {
  final String longId = nanoid(length: 64);
  // => sTTAY72ZgB3DFE6oyQlJI5hhvkebrlnheY81wzZHIBbqHHswEyw1LV2hHCrUC6bw
  // 64 characters
}
Which alphabet?

Every alphabet trades away characters to gain some property, and pays for it in entropy per character. Pick the constraint you actually have, then use the length that keeps you at 126 bits, the same collision resistance as UUID v4 and as the 21 character default.

Alphabet Characters Bits per char Length for 126 bits You need
cookieSafe [a-zA-Z0-9!#$%&'*+.^_`|~-], 77 chars 6.27 21 To put the id in a cookie value
url [a-zA-Z0-9_-], 64 chars 6.00 21 Nothing in particular, this is the default
base64 [a-zA-Z0-9+/], 64 chars 6.00 21 The classic Base64 symbols +/ instead of _-
alphanumeric [a-zA-Z0-9], 62 chars 5.95 22 Letters and digits, no symbols at all
base58 [1-9A-HJ-NP-Za-km-z], 58 chars 5.86 22 A short id for a URL that nobody dictates
noDoppelganger [346-9A-HJ-NP-RT-Ya-kmnp-rtw-z], 49 chars 5.61 23 No lookalikes, but vowels are fine
noDoppelgangerSafe [6-9B-DF-HJ-NP-RTWb-df-hjkmnp-rtwz], 36 chars 5.17 25 An id that can never resemble a word
crockfordBase32 [0-9A-HJKMNP-TV-Z], 32 chars 5.00 26 An id that survives being read out loud or typed back in
lowercase [a-z], 26 chars 4.70 27 Case-insensitive storage, such as a hostname or a bucket name
uppercase [A-Z], 26 chars 4.70 27 The same, where the surrounding text is uppercase
hexadecimalLowercase [0-9a-f], 16 chars 4.00 32 To interoperate with something that parses hex
hexadecimalUppercase [0-9A-F], 16 chars 4.00 32 The same, where the reader expects uppercase hex
numbers [0-9], 10 chars 3.32 38 Digits only, for a PIN or a numeric code

Rows run from the most to the least entropy per character. A smaller alphabet is not weaker, it just needs a longer id to hold the same 126 bits.

Collisions

Ids collide the way birthdays do. With N possible ids you get roughly sqrt(N) of them before a collision is likely, and every way of phrasing the question lands within a small factor of that. Pick a length from the number of ids you will ever create, not from a time span.

Ids you can create at each length, for four alphabet sizes, marked with a UUIDv4 and a YouTube video id, before a one in a million chance of a single collision

Both axes matter: a longer id buys you more, and so does a larger alphabet. A digits only id has to be 1.8 times as long as a url id to be equally safe, which is why numbers sits so far below.

The dashed line is a UUIDv4, which spends 36 characters on 122 random bits. The default 21 characters is the shortest url id that clears it, and it clears it by 4x while being 15 characters shorter. That is where the default comes from.

Some ids you already know, measured the same way:

Id What it is Ids before a 1 in a million risk
git short sha 7 hex characters 23
YouTube video id 11 characters of the url alphabet 12 million
UUIDv4 122 random bits, written as 36 characters 3.3 quadrillion
nanoid default 21 characters of the url alphabet 13 quadrillion

git and YouTube both hold far more ids than their row allows, because neither leans on randomness alone. git keeps the full 160 bit hash and only abbreviates for display, lengthening the prefix once it turns ambiguous. YouTube is billions of videos past its own line, so it has to be checking. Every number here is for minting an id blind and never looking. Writing into a column with a unique index and retrying on conflict buys you a shorter id than the table allows.

The same numbers for the default url alphabet, to read off exactly:

Length Ids you can create Which is
6 371 too few to use
8 24 thousand a hobby project
10 1.5 million one table in one database
12 97 million a busy table
14 6 billion one id every second for 197 years
16 398 billion a thousand ids a second for 12 years
21 (default) 13 quadrillion a billion ids a day for 36,000 years

Below 12 characters the numbers get small enough to matter, so check them. At the default they are far enough away that nothing you build will reach them.

Custom alphabet
import 'package:nanoid2/nanoid2.dart';

void main() {
  // use your own alphabets
  nanoid(alphabet: '13579'); // only odd numbers
  nanoid(alphabet: '1234567890abcdef'); // hex lowercase

  // or use any of the existing alphabets
  nanoid(alphabet: Alphabet.url); // default [a-zA-Z0-9_-], 64 chars
  nanoid(alphabet: Alphabet.numbers); // [0-9], 10 chars
  nanoid(alphabet: Alphabet.hexadecimalLowercase); // [0-9a-f], 16 chars
  nanoid(alphabet: Alphabet.hexadecimalUppercase); // [0-9A-F], 16 chars
  nanoid(alphabet: Alphabet.lowercase); // [a-z], 26 chars
  nanoid(alphabet: Alphabet.uppercase); // [A-Z], 26 chars
  nanoid(alphabet: Alphabet.alphanumeric); // [a-zA-Z0-9], 62 chars
  nanoid(alphabet: Alphabet.base64); // [a-zA-Z0-9+/], 64 chars
  nanoid(alphabet: Alphabet.base58); // [1-9A-HJ-NP-Za-km-z], 58 chars
  nanoid(alphabet: Alphabet.cookieSafe); // [a-zA-Z0-9!#$%&'*+.^_`|~-], 77 chars
  nanoid(alphabet: Alphabet.crockfordBase32); // [0-9A-HJKMNP-TV-Z], 32 chars

  // Numbers and english letters without lookalikes: 1, l, I, 0, O, o, u, v, 5, S, s, 2, Z. 49 chars
  nanoid(alphabet: Alphabet.noDoppelganger);
  // Numbers and consonants without lookalikes, should never look like an english word, 36 chars
  nanoid(alphabet: Alphabet.noDoppelgangerSafe);
}

License

MIT License

Copyright (c) 2023 Pascal Welsch, Rongjian Zhang, Andrey Sitnik

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Pascal Welsch GitHub avatar
GitHub author

Pascal Welsch ↗

Flutter Expert / CTO of phntm.xyz / Co-founder of @wiredashio / speaker / cat-lover

wiredash.comCologneOfficial website ↗
LanguagesDart

Dependencies used

Dependency list 2 items

  • lintDevelopment>=1.0.0 <3.0.0
  • testDevelopment^1.16.4

How do I choose a repository?

Start with your use case, compare repository activity, and check the original project before adopting it.

  1. Search by repository name, owner or description, then narrow the results by topic.
  2. Compare stars, forks and recent pushes. Stars show community interest, not a guarantee of quality.
  3. Read the README, license and issues on GitHub before using a project.

Sources and maintenance

“A repository is the most basic element of GitHub.”

GitHub Docs — About repositories ↗