pyobfus: the Python obfuscator
Obfuscate Python before you ship it—and still debug what you shipped.
简体中文 · Product · Documentation · PyPI
pyobfus is a local-first, AST-based Python obfuscator for Python 3.9–3.14. It
obfuscates multi-file projects and packages as a whole: names are renamed
consistently across modules and imports are rewritten to match, so the output
is still ordinary .py that runs without pyobfus installed. It can also
reverse-map protected production tracebacks for developers and AI coding
agents. Community is Apache-2.0, has no file or line limits, and requires no
trial.
What's new in v0.7.3: directory builds keep
enum.global_enummembers (such ascalendar.JANUARYorre.IGNORECASE) under their original names, so they no longer break at runtime, and a module that re-exports another project module withfrom .core import *now works when other modules import from it. Enums that cannot be analysed statically keep that module's names with a warning instead of failing the build. Rebuild and rerun your tests; see the changelog.
Why pyobfus
| Advantage | What it means in practice |
|---|---|
| Complete Community edition | Obfuscate real projects without a file/line cap or trial clock. Optional limits are your CI safety rails, not an upgrade gate. |
| Diagnosable protection | Keep the private mapping and restore identifiers in production tracebacks without giving customers the original source. |
| Evidence, not a black box | Scan, preview, verify syntax, retain provenance and compare reproducible build reports. |
| Portable and local-first | Source stays local and there is no telemetry (what goes over the network); Community emits ordinary cross-platform Python without a native build matrix. |
| Explicit security claims | Tested, verified-once and advisory-only claims are separated; deterrents are not presented as irreversible security. |
Quick start
pip install pyobfus
# Check compatibility, preview, then build
pyobfus --check src/
pyobfus src/ -o dist/ --dry-run --json
pyobfus src/ -o dist/ --save-mapping mapping.json --verify-syntax
# --verify-syntax only compiles the output; run your own tests against dist/
# Restore names when a production traceback arrives
pyobfus --unmap --trace error.log --mapping mapping.json
Since 0.7.1, add opt-in --verify-names to check newly unbound globals
without execution. Success JSON reports partial coverage explicitly; see
name verification
for usage and limits. Check the final directory or wheel with
pyobfus --check-delivery dist/ --json before shipping.
For framework presets, configuration discovery, packaging and verification, start at the task-oriented documentation.
Minimal example
Input:
def greet(name):
message = f"Hello, {name}!"
return message
print(greet("world"))
Run pyobfus input.py -o output.py. Representative Community output:
def I0(I1):
I2 = f"Hello, {I1}!"
return I2
print(I0("world"))
Both print Hello, world!. Generated identifiers can differ with input and
configuration; verify the exact output with your own tests. Keep a mapping when
you need to restore names from a shipped traceback.
Parameter names are preserved by default in every preset. Explicit
--no-preserve-param-names or YAML preserve_param_names: false keeps legacy
renaming with a warning: keyword calls may raise TypeError or silently bind
incorrectly. Rebuild from original source and keep the new mapping with the
new artifact; mapping numbers can change and old mappings cannot decode
rebuilt output. Cross-file directory builds (the default) still preserve parameters; legacy
--no-cross-file directory builds follow the option.
Features at a glance
Community includes name mangling with import rewriting across a project (directories also rename function locals; parameters and methods remain unchanged there; single files also rename methods and preserve parameters by default, see the guide), string and numeric transforms, framework-aware presets, config-aware pre-flight scanning (including coarse hardcoded-secret screening without displaying values), SARIF, structured dry-run, reverse traceback mapping, syntax verification, provenance, reproducible output and verifiable build reports.
Professional adds four kinds of commercial value:
- Protection strength: AES encryption, control-flow flattening, dead-code injection, anti-debugging, Selective Opacity and sealing.
- Protected assets: import strings, embedded data, Runtime String Vault and protected tracebacks.
- Distribution control: device, expiry, run-count, platform and application-supplied-key policies.
- Accountability: forensic watermarking and buyer-specific builds.
The durable classification rule is documented in the Community / Pro boundary policy.
🔌 Companion MCP server: pyobfus-mcp
Install the MCP server with no API key and no source upload:
uvx pyobfus-mcp
# or: pip install pyobfus-mcp
It exposes structured tools for scanning, configuration, protection, verification, preset explanation, tier recommendations and traceback mapping. See the MCP package guide and its registration in the official MCP Registry.
Agent and editor integrations
pyobfus-reviewandpyobfus-protectskills separate read-only review from build-producing work. See skills.- The VS Code extension provides inline risk diagnostics and traceback reversal; it is also on Open VSX.
zhurong2020/pyobfus-action@v1runs scans or verified builds in GitHub Actions with SARIF support.- The stable JSON CLI includes reason codes and an
ai_hintnext action. - Agent-readable project facts are published in
llms.txt, while contributor instructions live inAGENTS.md.
All Agent guidance is public and human-auditable. pyobfus does not serve hidden instructions or different facts based on User-Agent.
Configuration
Generate a starting configuration or use a named preset:
pyobfus --init src/
pyobfus src/ -o dist/ --preset django
pyobfus --list-presets
Community presets include safe, balanced, aggressive, fastapi, django,
flask, pydantic, click, sqlalchemy and ml. See the
documentation home and
pyobfus --help
for current options. Optional max_files and max_total_loc values are
user-selected safety limits at every tier.
How do I debug an obfuscated crash with an AI assistant?
Build with --save-mapping mapping.json, keep that file private, then run:
pyobfus --unmap --trace error.log --mapping mapping.json
The restored identifiers can be read by you or an AI assistant without giving
the customer your mapping or original source. --trace-marker can also stamp
generated files with the exact recovery command.
Purchase Professional Edition
Professional Edition is $45 USD, one time—not a subscription. A five-day trial requires no registration or card:
pyobfus-trial start
The trial is an honor-system convenience control, not a security boundary. Visit the product and purchase page for current payment methods, refund terms and purchase steps. After purchase, use the license activation guide.
Runtime-backed Pro artifacts depend on the separately redistributable,
pure-Python pyobfus-runtime package. Target machines do not need the complete
proprietary builder or a licence key.
Security and limitations
Obfuscation raises the cost of inspection; it does not make client-side Python irreversible. Runtime-decrypted material can be observed by a determined attacker. Keep credentials and authorization decisions behind environment, secret-manager or server boundaries.
Comparison and deployment guides
- Comparison overview
- vs PyArmor
- vs Nuitka
- PyInstaller cookbook
- Compiled-packaging cookbook
- Integration testing
Architecture and development
The product line separates the Apache-2.0 Core, proprietary Pro builder, redistributable runtime, MCP package, editor extension and GitHub Action. See:
Community and citation
Use GitHub Issues for bugs and
Discussions for questions
and ideas. Citation metadata is in
CITATION.cff,
with archival DOI 10.5281/zenodo.20846053.
Core is Apache-2.0; Professional implementation is proprietary. See
LICENSE-NOTICE.md.
Metadata
Release files for pyobfus 0.7.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyobfus-0.7.3.tar.gz | 459.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyobfus-0.7.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 766.4 kB
Release files / pyobfus-0.7.3.tar.gz
| Download URL | pyobfus-0.7.3.tar.gz |
|---|---|
| Size | 459.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a1b580bb596fe5633d8b11d80fd7bbe5ae58b934e2c532e3f290dd5a019956b7
|
|
BLAKE2b-256 checksum How to use checksums |
7f333c89b94dbce046ac2a3539ed879801e3097665a7c16e8e4e3450084d21ff
|
| 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 Oct 15, 2026.
Transparency logRelease files / pyobfus-0.7.3-py3-none-any.whl
| Download URL | pyobfus-0.7.3-py3-none-any.whl |
|---|---|
| Size | 307.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c5518f2965ae1e7130aa1ee97df3d1ceec7f65a84bf25943be0834651fb36d2e
|
|
BLAKE2b-256 checksum How to use checksums |
6b2c93d54133b7f84bb77f469c0f2ec6ffaba710c398e269dc4167cc74852d2c
|
| 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 Oct 15, 2026.
Transparency log