Skip to main content

A ULID is a universally unique lexicographically sortable identifier. It is

  • 128-bit compatible with UUID

  • 1.21e+24 unique ULIDs per millisecond

  • Lexicographically sortable!

  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID

  • Uses Crockford’s base32 for better efficiency and readability (5 bits per character)

  • Case insensitive

  • No special characters (URL safe)

  • Monotonic sort order (correctly detects and handles the same millisecond)

In general the structure of a ULID is as follows:

 01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

For more information have a look at the original specification.

Installation

Use pip to install the library

$ pip install python-ulid

to include Pydantic support install the optional dependency like so

$ pip install python-ulid[pydantic]

Basic Usage

Create a new ULID object from the current timestamp

>>> from ulid import ULID
>>> ULID()
ULID(01E75HZVW36EAZKMF1W7XNMSB4)

or use one of the named constructors

>>> import time, datetime
>>> ULID.from_timestamp(time.time())
ULID(01E75J1MKKWMGG0N5MBHFMRC84)
>>> ULID.from_datetime(datetime.datetime.now())
ULID(01E75J2XBK390V2XRH44EHC10X)

There are several options for encoding the ULID object (e.g. string, hex, int, bytes, UUID):

>>> str(ulid)
'01BTGNYV6HRNK8K8VKZASZCFPE'
>>> ulid.hex
'015ea15f6cd1c56689a373fab3f63ece'
>>> int(ulid)
1820576928786795198723644692628913870
>>> bytes(ulid)
b'\x01^\xa1_l\xd1\xc5f\x89\xa3s\xfa\xb3\xf6>\xce'
>>> ulid.to_uuid()
UUID('015ea15f-6cd1-c566-89a3-73fab3f63ece')

It is also possible to directly access the timestamp component of a ULID, either in UNIX epoch or as datetime.datetime

>>> ulid.timestamp
1505945939.153
>>> ulid.datetime
datetime.datetime(2017, 9, 20, 22, 18, 59, 153000, tzinfo=datetime.timezone.utc)

Pydantic integration

The ULID class can be directly used for the popular data validation library Pydantic like so

from pydantic import BaseModel
from ulid import ULID


class Model(BaseModel):
  ulid: ULID

model = Model(ulid="DX89370400440532013000")  # OK
model = Model(ulid="not-a-ulid")  # Raises ValidationError

Monotonic Support

This library by default supports the implementation for monotonic sort order suggested by the official ULID specification.

This means that ULID values generated in the same millisecond will have linear increasing randomness values. If \(r_1\) and \(r_2\) are the randomness values of two ULIDs with the same timestamp, then \(r_2 = r_1 + 1\).

Generators and policies

Every ULID is produced by a ULIDGenerator, which samples a clock for the timestamp, sources entropy for the randomness, and enforces a monotonicity policy. The bare ULID() constructor and the ULID.from_* factory methods delegate to a shared module-level default_generator.

For most use cases the default is all you need. To customize generation — a different clock, a custom entropy source, or another monotonicity policy — create your own ULIDGenerator and call generate()

>>> from ulid import ULIDGenerator
>>> generator = ULIDGenerator()
>>> generator.generate()
ULID(01HB0N8Q4RCE7YB1M2VZK9WX3T)

Choosing a monotonicity policy

A policy decides how the randomness is resolved when multiple ULIDs are generated within the same millisecond. Three policies are available:

  • StrictMonotonicPolicy (default) — increments the randomness by 1 on a same-millisecond collision and raises ValueError if the randomness is exhausted. This is the behaviour described under Monotonic Support.

  • LaxMonotonicPolicy — increments like the strict policy, but regenerates fresh randomness instead of raising when the randomness is exhausted.

  • PureRandomPolicy — ignores previous state and always draws fresh randomness, maximizing entropy at the cost of same-millisecond sort order.

>>> from ulid import ULIDGenerator, PureRandomPolicy
>>> generator = ULIDGenerator(policy=PureRandomPolicy())
>>> generator.generate()
ULID(01HB0N9F3TA5KDQ6ZE0WYV7MRC)

Overriding the default generator

To make ULID() and the ULID.from_* constructors use a custom generator globally, reassign ulid.default_generator

>>> import ulid
>>> from ulid import ULID, ULIDGenerator, LaxMonotonicPolicy
>>> ulid.default_generator = ULIDGenerator(policy=LaxMonotonicPolicy())
>>> ULID()  # now generated with the lax policy
ULID(01HB0NB7X2M4C8VKQ0ZF5WD9RA)

Command line interface

The package comes with a CLI interface that can be invoked either by the script name ulid or as python module python -m ulid. The CLI allows you to generate, inspect and convert ULIDs, e.g.

$ ulid build
01HASFKBN8SKZTSVVS03K5AMMS

$ ulid build --from-datetime=2023-09-23T10:20:30
01HB0J0F5GCKEXNSWVAD5PEAC1

$ ulid show 01HASFKBN8SKZTSVVS03K5AMMS
ULID:      01HASFKBN8SKZTSVVS03K5AMMS
Hex:       018ab2f9aea8ccffacef7900e6555299
Int:       2049395013039097460549394558635823769
Timestamp: 1695219822.248
Datetime:  2023-09-20 14:23:42.248000+00:00

There are several flags to select specific output formats for the show command, e.g.

$ ulid show --datetime 01HASFKBN8SKZTSVVS03K5AMMS
2023-09-20 14:23:42.248000+00:00

The special character - allows to read values from stdin so that they can be piped. E.g.

$ echo 01HASFKBN8SKZTSVVS03K5AMMS | ulid show --uuid -
018ab2f9-aea8-4cff-acef-7900e6555299

$ date --iso-8601 | python -m ulid build --from-datetime -
01HAT9PVR02T3S13XB48S7GEHE

For a full overview of flags for the build and show commands use the --help option (e.g. ulid show --help).

Other implementations

Contributions

Contributions are welcome! Feel free to create pull-requests for issues or feature requests. It might be worth creating an issue upfront to discuss the matter.

Release files for python-ulid 4.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-ulid 4.0.1
File Size Uploaded
python_ulid-4.0.1.tar.gz 101.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for python-ulid 4.0.1
File Interpreter ABI Platform
python_ulid-4.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 116.3 kB

Release files / python_ulid-4.0.1.tar.gz

Download URL python_ulid-4.0.1.tar.gz
Size 101.7 kB
Tags Source
SHA-256 checksum
How to use checksums
bbeec02556190bb9dc3401faa7268696acbfbe7b6db9908c155dc3548629f20c
BLAKE2b-256 checksum
How to use checksums
d64165079023c81491a21799c0120bce5925366b6913596bf797806f19973290
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / python_ulid-4.0.1-py3-none-any.whl

Download URL python_ulid-4.0.1-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6f1d69ceb97e99fe542df8476ebcd7a668284bf53ee14b3106bcc6a341a95ed9
BLAKE2b-256 checksum
How to use checksums
b4158b39b36f55b6618ec4ca9b55134dcfd9c04cecbc72709f5d8e6bdebed9cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

4.0.1 This release

2 release files

4.0.0

2 release files

3.2.1

2 release files

3.2.0

1 release file

3.1.0

2 release files

3.0.0

2 release files

2.7.0

2 release files

2.6.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.1

2 release files

1.1.0

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page