Skip to main content

ScopeMask (Python)

ScopeMask converts internal identifiers: database keys, emails, UUIDs, etc into short, opaque strings that are safe to expose in URLs and APIs, and decodes them back to the original value on demand. Each id is bound to a scope and a secret, with a keyed integrity check.

Install

pip install scopemask
# or
uv add scopemask

Configuration

Create a ScopeMask with a secret. The secret is required and is the key every id is derived from; keep it private and stable.

from scopemask import ScopeMask

scope_mask = ScopeMask("parity-secret")

Optional keyword arguments:

  • min_length: pad every id to at least this many characters (default 16).
  • base_alphabet: the characters ids are built from; must be unique (default A–Z, a–z, 0–9).
  • previous_secrets: extra secrets accepted when decoding but never used for encoding, so ids made with an old secret keep working after you rotate.
scope_mask = ScopeMask(
    "parity-secret",
    min_length=24,
    base_alphabet="ABCDEFGHJKLMNPQRSTUVWXYZ23456789",
    previous_secrets=("old-secret",),
)

Encode and decode

scope_mask.encode("user", 42)                    # "xgFeePgoWUZHCNLo"
scope_mask.decode("user", "xgFeePgoWUZHCNLo")    # 42

Value types

Integers, strings, bytes, and UUIDs are supported. The original type is restored on decode.

import uuid

scope_mask.encode("user", "hello")                # "yqBiRnZBIdqXslkrXM"
scope_mask.encode("user", b"\x00\x01\xff")        # "RLDIyRQmFljZ1gBD"
scope_mask.encode("user", uuid.UUID("12345678-1234-5678-1234-567812345678"))
# "miQAnixf6TYaACwhThxDJ973X5vSuKqjp2W"

Scopes

The same value produces a different id in each scope.

scope_mask.encode("user", 42)     # "xgFeePgoWUZHCNLo"
scope_mask.encode("order", 42)    # "8DGttE8msCZHsJVG"

Prefixes

Add a prefix for readable ids. Pass the same prefix when decoding.

scope_mask.encode("user", 42, prefix="id_")        # "id_xgFeePgoWUZHCNLo"
scope_mask.encode("webhook", 42, prefix="whs_")    # "whs_jU5IIH0OxGnQg5u1"
scope_mask.decode("user", "id_xgFeePgoWUZHCNLo", prefix="id_")   # 42

Bound scope

Bind a scope and prefix once, then call the same methods without repeating them.

users = scope_mask.scope("user", prefix="id_")

users.encode(42)                     # "id_xgFeePgoWUZHCNLo"
users.decode("id_xgFeePgoWUZHCNLo")  # 42
users.try_decode("not-a-real-id")    # None

ids = users.encode_many([1, 2, 3])
users.decode_many(ids)               # [1, 2, 3]
users.try_decode_many(ids)           # [1, 2, 3]

Batch operations

ids = scope_mask.encode_many("user", [1, 2, 3])
scope_mask.decode_many("user", ids)   # [1, 2, 3]

Safe decoding

decode raises InvalidId on an invalid id. Use try_decode to get None instead.

scope_mask.try_decode("user", "not-a-real-id")         # None
scope_mask.try_decode_many("user", ["not-a-real-id"])  # [None]
scope_mask.encode("user", None)                        # None

Additional resources

See Overview for more details.

Release files for scopemask 1.0.0

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

Source distribution (sdist)

Source distribution for scopemask 1.0.0
File Size Uploaded
scopemask-1.0.0.tar.gz 66.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for scopemask 1.0.0
File Interpreter ABI Platform
scopemask-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 72.2 kB

Release files / scopemask-1.0.0.tar.gz

Download URL scopemask-1.0.0.tar.gz
Size 66.0 kB
Tags Source
SHA-256 checksum
How to use checksums
1298f6aee4b6e459ab9ef49459c966ccd60569d25f7643e34442d441e0cbe372
BLAKE2b-256 checksum
How to use checksums
098046df25d2b32026c99df3e5c9554f36da6d63babd34a0daa49345716e9d39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.

Transparency log

Release files / scopemask-1.0.0-py3-none-any.whl

Download URL scopemask-1.0.0-py3-none-any.whl
Size 6.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a4d02159434feb4588e56dc118b1b9684b1a33bbef3aae8de1c6750cec674315
BLAKE2b-256 checksum
How to use checksums
8a903a7e1bd49e1c5965a6cd394cd2e2558bdc7763d99f97f30b34b03292817a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

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