itsdangerous
A small Python toolkit for cryptographically signing data so you can trust it hasn't been tampered with when it comes back from an untrusted client.
Repository Health
Technical Analysis
itsdangerous provides a layered API for signing and optionally serializing data so it can safely round-trip through cookies, URLs, and other untrusted channels. At the base is a Signer that HMAC-signs raw bytes with a secret key and salt; wrapped around it is a Serializer that adds pluggable JSON (or custom) encoding, so arbitrary Python objects can be signed and verified with a single dumps/loads call pair, mirroring the json module’s own interface.
Built-in variants cover the common cases web frameworks need: TimestampSigner/TimedSerializer embed a timestamp so tokens can expire after a max_age, and URLSafeSerializer/URLSafeTimedSerializer zlib-compress and base64-encode the payload so it’s safe to embed directly in a URL or cookie value. Key rotation is supported natively — pass a list of secret keys, oldest to newest, and verification tries them in reverse so old tokens keep validating during a rollover. Originally split out of Flask (which still uses it for signed session cookies), it has no runtime dependencies and is now maintained as one of the core Pallets projects alongside Flask, Jinja, Click, and Werkzeug.
What You Get
- A
Signerclass that HMAC-signs raw bytes with a secret key and salt, withsign/unsign/validatemethods - A
Serializerwrapper that signs arbitrary Python objects via a pluggable data serializer (JSON by default) TimestampSigner/TimedSerializerfor tokens that expire after a configurablemax_ageURLSafeSerializer/URLSafeTimedSerializerthat zlib-compress and base64-encode payloads for safe use in URLs and cookies- Built-in key rotation via a list of secret keys, verified newest-first so old tokens keep working during rotation
- A small, structured exception hierarchy (
BadSignature,SignatureExpired,BadPayload, etc.) that preserves the original payload and signing date for debugging
Common Use Cases
- Signing Flask/Django-style session cookies so tampering is detectable server-side
- Generating expiring email-confirmation or password-reset tokens embedded in a URL
- Issuing short-lived API tokens that don’t require a database lookup to verify
- Passing signed state through a redirect or webhook callback without a server-side session store
- Rotating a compromised or aging secret key without invalidating tokens already issued to users
Under The Hood
Architecture
The codebase is layered by responsibility: encoding.py provides base64/int helpers, exc.py defines a small exception hierarchy (BadData to BadSignature to BadTimeSignature/SignatureExpired, plus BadPayload and BadHeader), and signer.py defines a SigningAlgorithm/HMACAlgorithm pair plus the Signer class handling key derivation strategies (concat, django-concat, hmac, none) and key-rotation via a secret_keys list tried oldest-to-newest. serializer.py wraps a Signer to add pluggable payload serialization (defaulting to json) with dumps/loads, and iterates fallback_signers when unsigning to support migrating signing schemes without breaking old tokens. timed.py extends Signer into TimestampSigner (embeds a base64 timestamp) and Serializer into TimedSerializer (adds max_age expiry checks), while url_safe.py composes a URLSafeSerializerMixin (zlib compression plus base64 encoding, using a compact JSON serializer from _json.py) with Serializer/TimedSerializer via multiple inheritance to produce URLSafeSerializer and URLSafeTimedSerializer. This is composition over duplication: cryptographic verification, payload encoding, and expiry logic are each isolated behind small, independently testable classes.
Tech Stack
Pure Python 3.10+ with zero runtime dependencies, relying only on stdlib (hashlib, hmac, base64, zlib, json). Packaged with flit_core via pyproject.toml, with uv managing dependency groups for dev, docs, tests, and typing. Linting runs through ruff (bugbear, pyflakes, isort, pyupgrade rule sets), static typing is enforced with strict mypy and pyright, and the test matrix runs via tox/tox-uv across Python 3.10-3.13 and PyPy 3.11. Documentation is built with Sphinx using the Pallets Sphinx theme, and releases publish to PyPI via GitHub Actions using trusted publishing.
Code Quality
Tests live under tests/test_itsdangerous/, covering encoding, signer, serializer, timed, and URL-safe behavior with plain pytest functions and freezegun for deterministic timestamp assertions; coverage configuration targets branch coverage. Typing is comprehensive — a py.typed marker, PEP 604 unions throughout, and a Protocol-based type for pluggable serializers — checked under mypy --strict and pyright. Error handling is deliberate rather than swallowed: the exception hierarchy carries structured context (the failed payload, the signing date) instead of just a message, and signature comparison uses hmac.compare_digest to avoid timing attacks. Style is enforced via ruff and pre-commit hooks, with CI running the full suite across multiple Python versions.
API Design
The public API favors progressive disclosure: URLSafeSerializer(secret_key, salt).dumps(obj) covers the common case in one line, while the lower-level Signer/TimestampSigner classes expose raw sign/unsign primitives for callers who don’t want JSON at all. Key rotation and fallback_signers are both documented, low-boilerplate escape hatches — no subclassing required to support a secret-key rollover or a legacy token format. Method naming mirrors the standard json module’s dumps/loads convention, and every public method carries a docstring with version-change history. The main friction point is that verification failures surface as a small hierarchy of exceptions rather than a single boolean, though validate() convenience methods cover the common “is this still good” check without a try/except.
Used by 15 apps in this directory
Polar
Developer Tools · Ecommerce · Invoicing Finance
Open source payments infrastructure that turns software into a business — subscriptions, usage-based billing, digital products, and merchant-of-record compliance in one platform.
Redash
Analytics · Data Engineering
Redash lets anyone connect to 35+ SQL and NoSQL data sources, write a query in the browser, and turn the result into a shared dashboard — no separate BI suite required.
rowboat
AI Assistants · AI Development
Build, test, and deploy multi-agent AI workflows with a visual editor, RAG data sources, MCP tool integration, and a production-ready REST API.
Speakr
AI Assistants
Self-hosted AI transcription with speaker diarization, smart tagging, and multi-user collaboration — your recordings stay on your infrastructure.
TDengine
Databases
A high-performance, open-source time-series database built in C for IoT, connected vehicles, and industrial monitoring workloads, with built-in stream processing, caching, and data subscription.
Uptrace
Devops · Monitoring
Unified open-source APM that collects OpenTelemetry traces, metrics, and logs into a single self-hosted platform backed by ClickHouse.