
Research
/Security News
Fake imToken Chrome Extension Steals Seed Phrases via Phishing Redirects
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.
pyobfus
Advanced tools
Modern Python Code Obfuscator
A Python code obfuscator built with AST-based transformations for Python 3.8+. Provides reliable name mangling, string encoding, and code protection features.
The following features are fully implemented and available in the current version:
🆕 Cross-File Obfuscation (v0.2.0): Consistent name obfuscation across multiple files
__all__ list updates with obfuscated names--dry-run flagName Mangling: Rename variables, functions, classes, and class attributes to obfuscated names (I0, I1, I2...)
Comment Removal: Strip comments and docstrings
String Encoding: Base64 encoding for string literals with automatic decoder injection
Parameter Preservation: Preserve function parameter names for keyword argument compatibility (--preserve-param-names)
Multi-file Support: Obfuscate entire projects with preserved import relationships
File Filtering: Exclude files using glob patterns (test files, config files, etc.)
Configuration Files: YAML-based configuration for repeatable builds
Selective Obfuscation: Preserve specific names (builtins, magic methods, custom exclusions)
The following advanced features are available with a Pro license:
String Encryption (v0.1.6+)
Anti-Debugging (v0.1.6+)
Control Flow Flattening (v0.3.0+)
--control-flowDead Code Injection (v0.3.0+)
--dead-codeLicense Embedding (v0.3.0+)
--expire 2025-12-31--bind-machine--max-runs 100Configuration Presets (v0.3.0+)
--preset trial - 30-day time-limited version--preset commercial - Maximum protection with machine binding--preset library - For pip-distributable libraries--preset maximum - Highest security with all protections--list-presets - View all presetsSee ROADMAP.md for the full feature timeline.
Try all Pro features for 5 days - no registration or credit card required!
# Start your free trial
pyobfus-trial start
# Check trial status
pyobfus-trial status
# Use Pro features during trial
pyobfus input.py -o output.py --level pro
What's included in the trial:
--control-flow)--string-encryption)--anti-debug)--dead-code)--expire, --bind-machine, --max-runs)--preset trial/commercial/library/maximum)After your trial, purchase a license to continue using Pro features.
Pro Edition Features:
Price: $45.00 USD (one-time payment)
Visit our purchase page: pyobfus.github.io/purchase for detailed information and secure checkout.
Quick purchase: 🚀 Buy Now - Direct checkout link (Instant delivery • 30-day money-back guarantee)
3-Step Purchase Process:
Complete Secure Checkout (Stripe)
Receive License Key
PYOB-XXXX-XXXX-XXXX-XXXXActivate License
pip install --upgrade pyobfus
pyobfus-license register PYOB-XXXX-XXXX-XXXX-XXXX
pyobfus-license status
Start Using Pro Features
# Quick start with presets
pyobfus src/ -o dist/ --preset commercial # Maximum protection
pyobfus src/ -o dist/ --preset trial # 30-day trial version
pyobfus src/ -o dist/ --preset library # For pip distribution
# Individual features
pyobfus input.py -o output.py --string-encryption
pyobfus input.py -o output.py --anti-debug
pyobfus input.py -o output.py --control-flow
pyobfus input.py -o output.py --dead-code
# License restrictions
pyobfus src/ -o dist/ --expire 2025-12-31 --bind-machine --max-runs 100
# All Pro features
pyobfus input.py -o output.py --string-encryption --anti-debug --control-flow --dead-code
Support: If you encounter any issues, contact zhurong0525@gmail.com with your license key.
By purchasing pyobfus Professional Edition, you agree to our:
From PyPI (recommended):
pip install pyobfus
From source (for development):
git clone https://github.com/zhurong2020/pyobfus.git
cd pyobfus
pip install -e .
# Obfuscate a single file
pyobfus input.py -o output.py
# Obfuscate a directory (cross-file mode - default in v0.2.0+)
pyobfus src/ -o dist/
# Preview obfuscation without writing files (v0.2.0+)
pyobfus src/ -o dist/ --dry-run
# Legacy single-file mode (v0.2.0+)
pyobfus src/ -o dist/ --no-cross-file
# With configuration file
pyobfus src/ -o dist/ --config pyobfus.yaml
# Preserve parameter names for keyword arguments (v0.1.6+)
pyobfus src/ -o dist/ --preserve-param-names
# Verbose output with progress indicators (v0.2.0+)
pyobfus src/ -o dist/ --verbose
Before obfuscation:
def calculate_risk(age, score):
"""Calculate risk factor."""
risk_factor = 0.1
if score > 100:
risk_factor = 0.5
return age * risk_factor
patient_age = 55
patient_score = 150
risk = calculate_risk(patient_age, patient_score)
print(f"Risk score: {risk}")
After obfuscation:
def I0(I1, I2):
I3 = 0.1
if I2 > 100:
I3 = 0.5
return I1 * I3
I4 = 55
I5 = 150
I6 = I0(I4, I5)
print(f'Risk score: {I6}')
Note: Variable names (I0, I1, etc.) may vary slightly depending on code structure, but functionality is preserved.
Generate a configuration template for your project type:
# For Django projects
pyobfus --init-config django
# For Flask projects
pyobfus --init-config flask
# For Python libraries
pyobfus --init-config library
# For general projects
pyobfus --init-config general
This creates a pyobfus.yaml file with sensible defaults for your project type.
Check your configuration file for errors before use:
pyobfus --validate-config pyobfus.yaml
The validator checks for:
exclude_pattern -> exclude_patterns)When you run pyobfus without -c, it automatically searches for:
pyobfus.yamlpyobfus.yml.pyobfus.yaml.pyobfus.ymlCreate pyobfus.yaml:
obfuscation:
level: community
exclude_patterns:
- "test_*.py"
- "**/tests/**"
- "__init__.py"
exclude_names:
- "logger"
- "config"
- "main"
remove_docstrings: true
remove_comments: true
The exclude_names option preserves specified names from being renamed during obfuscation:
obfuscation:
exclude_names:
- MyPublicClass # Name preserved, but strings inside are still encoded
- exported_function # Name preserved for external callers
Important: exclude_names only affects name obfuscation, not string encoding:
# Original
SECRET_KEY = "admin-password-123"
# With exclude_names: [SECRET_KEY] and string_encoding: true
SECRET_KEY = _decode_str('YWRtaW4tcGFzc3dvcmQtMTIz')
# ✅ Name 'SECRET_KEY' is preserved
# ✅ String content is still encoded (Base64)
Use cases:
Exclude patterns support glob syntax:
test_*.py - Exclude files starting with "test_"**/tests/** - Exclude all files in "tests" directories**/__init__.py - Exclude all __init__.py filessetup.py - Exclude specific filesSee pyobfus.yaml.example for more configuration examples.
pyobfus uses Python's ast module for syntax-aware transformations:
This approach ensures:
git clone https://github.com/zhurong2020/pyobfus.git
cd pyobfus
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -e ".[dev]"
# Run unit tests
pytest tests/ -v
# With coverage
pytest tests/ -v --cov=pyobfus --cov-report=html
# Run integration tests
pytest integration_tests/ -v
Integration Testing Framework (v0.1.6+): Test pyobfus on real-world code without uploading to PyPI. See INTEGRATION_TESTING.md for details.
# Format code
black pyobfus/
# Type checking
mypy pyobfus/
# Linting
ruff check pyobfus/
Obfuscate sensitive business logic before distributing Python applications.
Demonstrate code protection concepts and obfuscation techniques.
Add an additional layer of protection for commercial Python software.
Keyword Arguments (✅ Resolved in v0.1.6): By default, parameter names are obfuscated, which breaks keyword arguments. Solution: Use the --preserve-param-names flag to preserve parameter names while still obfuscating function bodies.
Example:
# Before obfuscation
def process(data_path, output_dir):
temp_file = data_path + ".tmp"
return temp_file
result = process(data_path='./data', output_dir='./output') # ✅ Works
# After obfuscation (default behavior)
def I0(I1, I2):
I3 = I1 + ".tmp"
return I3
result = process(data_path='./data', output_dir='./output') # ❌ TypeError!
# After obfuscation (with --preserve-param-names)
def I0(data_path, output_dir):
I3 = data_path + ".tmp"
return I3
result = I0(data_path='./data', output_dir='./output') # ✅ Works!
When to use --preserve-param-names:
def func(*, kwonly))Trade-off: Parameter names reveal some information about the function's interface, but function bodies and local variables are still fully obfuscated.
Cross-file imports: ✅ Resolved in v0.2.0 with full cross-file obfuscation support
Dynamic code: eval(), exec() with obfuscated code may require adjustments
Debugging: Obfuscated code is harder to debug (by design)
Performance: Some obfuscation techniques may impact runtime performance
--preserve-param-names to maintain keyword argument compatibilityUse pyobfus if you:
# Install
pip install pyobfus
# Obfuscate a single file
pyobfus script.py -o script_obf.py
# Obfuscate an entire project
pyobfus src/ -o dist/
# Preview without writing files
pyobfus src/ -o dist/ --dry-run
Yes, pyobfus guarantees 100% functional equivalence. The obfuscated code produces identical outputs to your original code. We use Python's AST (Abstract Syntax Tree) for syntax-aware transformations, ensuring syntactically correct output.
Minimal impact:
Yes! Use our built-in templates:
# Django
pyobfus --init-config django
# Flask
pyobfus --init-config flask
# Then run obfuscation
pyobfus src/ -o dist/ -c pyobfus.yaml
pyobfus supports Python 3.8, 3.9, 3.10, 3.11, and 3.12. Generated code is compatible with all these versions regardless of which version you use to run pyobfus.
| Feature | pyobfus | PyArmor |
|---|---|---|
| Price | $45 (Pro) | $89 (Pro) |
| Free tier | Clear limits (5 files/1000 LOC) | Vague "trial" limitations |
| Open source | Yes (Core: Apache 2.0, Pro: Proprietary) | No |
| Native dependencies | None (pure Python output) | Requires runtime library |
| Python 3.12 support | Yes | Yes |
Choose pyobfus if: You want transparent pricing, open-source trust, and simpler deployment without native dependencies.
See our detailed comparison for more information.
--dry-run to preview changes before writing files--preserve-param-names if you rely on keyword argumentspyobfus.yaml for names that must stay unchangedName mangling is irreversible - original variable names cannot be recovered. However, code logic remains intact (this is true for all obfuscators). For stronger protection, use Pro features:
Important: String encryption (AES-256) is designed as a deterrent against casual reverse engineering, not as cryptographic security.
Because obfuscated code must decrypt strings at runtime, the encryption key is necessarily embedded in the output. A determined attacker with access to the obfuscated code can:
This is a fundamental limitation of ALL client-side obfuscators (including PyArmor, Nuitka, etc.) - true cryptographic security would require server-side decryption, which is impractical for most use cases.
What string encryption DOES provide:
strings or grep searches from revealing sensitive textWhat string encryption does NOT provide:
Recommendation: For sensitive credentials (API keys, passwords), use environment variables or external secret management systems rather than embedding them in code.
| Tool | Approach | Output |
|---|---|---|
| pyobfus | AST transformation | .py files (pure Python) |
| Cython | Compile to C | .so/.pyd (platform-specific) |
| Nuitka | Compile to executable | Binary (platform-specific) |
Choose pyobfus if: You need cross-platform .py files without compilation overhead.
If you find pyobfus helpful, consider supporting its development:
Your support helps maintain and improve pyobfus. Thank you!
FAQs
Modern Python Code Obfuscator with AST-based Transformations
We found that pyobfus demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.

Security News
Latio’s 2026 report recognizes Socket as a Supply Chain Innovator and highlights our work in 0-day malware detection, SCA, and auto-patching.

Company News
Join Socket for live demos, rooftop happy hours, and one-on-one meetings during BSidesSF and RSA 2026 in San Francisco.