presidio-audit
Presidio tells you what it found and hands you the redacted text. It does not keep
a record. presidio-audit is a drop-in wrapper that logs every anonymization
decision to a tamper-evident local file and exports it as a compliance artifact.
Country-neutral: the evidence problem is the same under GDPR, HIPAA, CCPA or Malaysia's PDPA, and nothing in this package is Malaysia-specific.
pip install presidio-audit
Use
from presidio_analyzer import AnalyzerEngine
from presidio_audit import AuditedAnonymizerEngine, JsonlAuditStore, export_report
analyzer = AnalyzerEngine()
store = JsonlAuditStore("./audit.jsonl")
engine = AuditedAnonymizerEngine(store)
results = analyzer.analyze(text=text, language="en")
safe = engine.anonymize(text, results, source_ref="ticket-42")
export_report(store, start="2026-07-01", end="2026-07-31", fmt="md", out_path="july.md")
anonymize() takes and returns exactly what Presidio's AnonymizerEngine.anonymize()
does. The only new argument is source_ref, your identifier for the document or
request being processed.
Reversible pseudonymization
Encrypt instead of destroy, so an external service's reply can be rehydrated locally:
from presidio_audit import AuditedDeanonymizeEngine, reversible_operators
safe = engine.anonymize(text, results, operators=reversible_operators(key, ["MY_NRIC"]))
reply = call_your_llm(safe.text)
restored = AuditedDeanonymizeEngine(store).deanonymize(reply, key=key)
By default deanonymize() scans for ciphertext rather than requiring you to have
kept the spans: tokens that decrypt cleanly are restored, everything else is left
untouched. Pass entities= if you did keep them. Both directions are audited —
re-identification is a compliance event in its own right.
CLI
presidio-audit export --store ./audit.jsonl --from 2026-07-01 --to 2026-07-31 \
--format md --out july.md
presidio-audit export --store ./audit.jsonl # whole store, JSON to stdout
presidio-audit verify --store ./audit.jsonl # chain check only
Exit codes: 0 fine, 1 bad arguments or unreadable store, 2 some lines were
unreadable (report still produced), 3 hash chain broken (report still produced).
Run verify from cron — tamper evidence nobody looks at is not evidence.
What the store guarantees
Records hold offsets and metadata, never the matched value, the ciphertext or
the key. Each record hashes its own fields plus the previous record's hash, so an
in-place edit or a mid-file deletion is detectable and verify_chain() says where.
Appends are atomic per record (O_APPEND on POSIX, a FILE_APPEND_DATA handle on
Windows, where the C runtime's O_APPEND is not atomic between processes).
Read COMPLIANCE.md for the explicit non-claims — particularly that the chain does not detect tail truncation and does not prevent anything.
Dependency note
presidio-anonymizer pulls in cryptography, and its version bounds have moved
repeatedly (<44.1 → >=46.0.4 → <47 → <49 inside two months). If you pin
cryptography yourself you can hit a resolver conflict that looks like it comes
from this package but does not: it comes from the bounds presidio-anonymizer
declares. presidio-audit adds no crypto dependency of its own.
Floor is presidio-anonymizer>=2.2.363, not lower: Presidio swapped pycryptodome
for cryptography in 2.2.358, and supporting both sides of that change would mean
claiming support for an Encrypt operator implementation nobody tested here.
Release history: CHANGELOG.md.
Apache-2.0 licensed.
Metadata
Release files for presidio-audit 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| presidio_audit-1.0.0.tar.gz | 23.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| presidio_audit-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.4 kB
Release files / presidio_audit-1.0.0.tar.gz
| Download URL | presidio_audit-1.0.0.tar.gz |
|---|---|
| Size | 23.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6635788f820e29f93a345f911c19f24569032e07a09c584e44289b74c39659c
|
|
BLAKE2b-256 checksum How to use checksums |
ff96a6f46373daf5e6e59ef7244f0fa4aadb9ed4d2642a4830cc63c0e1f624e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 22, 2026.
Transparency logRelease files / presidio_audit-1.0.0-py3-none-any.whl
| Download URL | presidio_audit-1.0.0-py3-none-any.whl |
|---|---|
| Size | 26.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3f8ad5b888fd8b0f29ca2551bd80c4f881a0313730922d2b5a5f2a8933f5230b
|
|
BLAKE2b-256 checksum How to use checksums |
c82858baaa7f2ecc6671ae022d023fd1732e53e58687c44cfaa83deddeb45b00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 22, 2026.
Transparency log