shortuuid review
shortuuid 1.0.13 turns a 128-bit Python UUID into shorter text using a 57-character alphabet that omits look-alike characters. The usual result is 22 URL-safe characters and can be decoded back to the original UUID when the same alphabet is used. It can create random UUID4 values, deterministic UUID5 values from DNS names or URLs, arbitrary secure random strings, and Django CharField values. Version 1.0.13 changed the random-string generator to use rejection sampling, removing modulo bias. It does not make UUIDs sortable, attach expiry, or turn an identifier into an authentication token.
shortuuid 1.0.13 installed in 0.2 seconds and occupied 1 MB in our sandbox, with no dependencies or audit findings. Use it to display or transport UUIDs compactly; choose UUID7 or ULID when ordering matters, and a token system when authorization matters.
We installed it
| Install | ✓ · 0.2s | 1 package on disk · 1 MB |
| Import | ✓ | import shortuuid in 0.15s · pure Python · py.typed · requires Python >=3.6 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does shortuuid install cleanly?
Yes. In a fresh container with an empty cache, pip install shortuuid finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.
What does shortuuid need to run?
Python >=3.6, and nothing compiled: it is pure Python. In our run import shortuuid succeeded in 0.15s, and the package ships py.typed for type checkers.
shortuuid or nanoid: which should you use?
nanoid: Choose it for configurable secure random strings when UUID compatibility and reversibility are unnecessary. shortuuid 1.0.13 installed in 0.2 seconds and occupied 1 MB in our sandbox, with no dependencies or audit findings.
When should you not use shortuuid?
Database insertion order matters. Encoded UUID4 values are still random; UUID7 or ULID is a better index key for time ordering.
Use it if
- Existing UUID values need shorter text in URLs or support screens without losing reversible 128-bit identity.
- Human transcription matters and the default alphabet should exclude 0, O, 1, l, and I.
- A DNS name or URL must map repeatedly to the same compact UUID5 representation.
- Separate services can agree on one custom alphabet and require compatible encode and decode operations.
- Database insertion order matters. Encoded UUID4 values are still random; UUID7 or ULID is a better index key for time ordering.
- You intend to slice a 22-character value casually. Truncation throws away UUID bits, so collision risk depends on the retained length and traffic.
- The value is an API secret or session token. shortuuid supplies identifiers, with no expiry, revocation, audience, or authorization semantics.
- Services cannot freeze one alphabet and its order. A different alphabet decodes the same text to a different UUID or rejects it.
- You expect `ShortUUIDField` to behave like Django's UUIDField. It subclasses CharField and generates a random string of the configured length.
Setup reality
We installed shortuuid 1.0.13 in a fresh, unprivileged Python 3.12 sandbox in 0.2 seconds. It left one package and 1 MB on disk, with 0 direct dependencies and 0 known pip-audit vulnerabilities. import shortuuid worked in 0.15 seconds. Our measurement setup used 3 CPUs, 8 GB of RAM, and no cache. The package is pure Python, includes py.typed, requires Python 3.6 or newer, and uses the BSD-3-Clause license.
No credentials or configuration file are involved. shortuuid.uuid() makes a UUID4 and encodes it; passing a DNS name or URL selects a deterministic UUID5 namespace. random(length=22) instead returns random alphabet characters and is not a reversible UUID. Version 1.0.13 improved that random selection with rejection sampling. Decide which identity contract belongs in storage before the first row is written.
Encoding depends on the alphabet. The module-level set_alphabet mutates shared state and sorts plus deduplicates input by default. For different tenants or threads, construct separate ShortUUID instances. Use dont_sort_alphabet=True only when matching another implementation's exact order. Values created before version 1.0.0 used reversed byte significance; decode those once with legacy=True and rewrite them, because the README says that compatibility path may disappear.
The optional Django field imports Django only when used, subclasses CharField, and creates random strings rather than UUID objects. Set a database uniqueness constraint and retry collisions, especially below the default 22 characters. The CLI can generate, encode, and decode individual values, but it does not coordinate uniqueness across processes or machines.
Patterns
Generate a compact UUID4 generate-short-uuid
import shortuuid
identifier = shortuuid.uuid()The default output is normally 22 characters and reversibly represents a random 128-bit UUID.
Encode an existing UUID encode-existing-uuid
from uuid import UUID
import shortuuid
value = UUID('6ca4f0f8-2508-4bac-b8f1-5d1e3da2247a')
text = shortuuid.encode(value)Keep the alphabet fixed anywhere the encoded form is stored or exchanged.
Recover a UUID object decode-short-uuid
import shortuuid
value = shortuuid.decode('MLpZDiEXM4VsUryR9oE8uc')decode returns `uuid.UUID`; malformed characters raise ValueError.
Create a deterministic ID from a name generate-named-uuid
import shortuuid
site_id = shortuuid.uuid(name='example.com')
url_id = shortuuid.uuid(name='https://example.com/items/42')Plain names use the DNS namespace, while URL-shaped names use the URL namespace for UUID5 generation.
Generate a random token-shaped string generate-random-string
import shortuuid
value = shortuuid.random(length=24)Version 1.0.13 uses rejection sampling. The result is random alphabet text, not an encoded UUID and not a complete authorization token system.
Isolate a custom alphabet use-custom-alphabet
import shortuuid
codec = shortuuid.ShortUUID(alphabet='23456789abcdef')
text = codec.uuid()
value = codec.decode(text)A class instance avoids changing the module-wide alphabet used by unrelated callers.
Match another implementation's ordering preserve-alphabet-order
import shortuuid
codec = shortuuid.ShortUUID()
codec.set_alphabet('abcdefgh1230', dont_sort_alphabet=True)The flag keeps the supplied order after duplicate removal; without it, shortuuid sorts the alphabet.
Convert a pre-1.0 encoding migrate-legacy-value
import shortuuid
old = 'legacy-value'
new = shortuuid.encode(shortuuid.decode(old, legacy=True))Use `legacy=True` only for values produced before 1.0.0, then persist the new encoding because legacy support may be removed.
Add a Django short ID field define-django-field
from django.db import models
from shortuuid.django_fields import ShortUUIDField
class Order(models.Model):
id = ShortUUIDField(length=22, primary_key=True, editable=False)ShortUUIDField is a CharField that generates random strings. Add the uniqueness and migration behavior your schema requires.
Prefix a Django identifier prefix-django-id
from shortuuid.django_fields import ShortUUIDField
public_id = ShortUUIDField(
prefix='ord_',
length=16,
max_length=20,
unique=True,
)max_length must accommodate the prefix plus generated length; version 1.0.9 fixed that length accounting.
Encode a UUID in the shell encode-from-cli
shortuuid encode 6ca4f0f8-2508-4bac-b8f1-5d1e3da2247aCLI encode and decode commands were added in the 1.0 line and operate on one value per invocation.
Retry a uniqueness collision guard-collision
from django.db import IntegrityError, transaction
def create_order(Order):
for _ in range(3):
try:
with transaction.atomic():
return Order.objects.create()
except IntegrityError:
pass
raise RuntimeError('could not allocate a unique ID')Truncated random IDs need a database uniqueness constraint and bounded retry path; shortuuid does not coordinate generators.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| nanoid | PyPI | Choose it for configurable secure random strings when UUID compatibility and reversibility are unnecessary. |
| ulid-py | PyPI | Choose it when lexicographic order should carry a timestamp while retaining a compact textual form. |
| uuid6 | PyPI | Choose it for RFC-aligned UUID6, UUID7, or UUID8 values that stay inside standard UUID tooling. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

