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
Apache Airflow
Data Engineering
Define, schedule, and monitor complex data workflows as Python code — with a powerful UI, 80+ provider integrations, and battle-tested scalability across thousands of production deployments.
Baserow
No Code Platforms · Databases
Open-source no-code platform to build databases, apps, automations, and AI agents — self-hosted or cloud, with full data ownership.
/dev/push
Developer Tools · Devops
Self-hosted, open-source Vercel alternative that deploys Python, Node.js, PHP, and any Docker-compatible app from a Git push, with zero-downtime rollouts and real-time logs.
Khoj
AI Assistants · Knowledge Management · Productivity
A self-hostable AI second brain that chats with your documents, searches the web, builds custom agents, and runs entirely on your own LLM.
marimo
Developer Tools · Data Engineering
A reactive Python notebook that eliminates hidden state, runs reproducibly, and deploys as a web app or script — stored as pure Python, built for the AI era.
Morphik
AI Development · Search · Databases
Morphik is an AI-native ingestion and retrieval engine that lets developers store, search, and reason over visually rich documents — scanned PDFs, manuals, slides, and video — without duct-taping together OCR, an embedding model, and a vector database.
NoteDiscovery
Note Taking · Knowledge Management · Productivity
A self-hosted markdown knowledge base with MCP-powered AI integration, graph views, LaTeX math, and built-in drawing — your notes stay on your server, forever.
Okteto
Devops · Developer Tools
Develop applications directly inside your Kubernetes cluster with real-time file sync and instant hot-reload — no more docker build/redeploy cycles.
Open WebUI
AI Assistants · AI Agents
The extensible, privacy-first AI platform that runs Ollama, OpenAI, and any LLM backend behind a polished, feature-packed web interface.