PELock.PythonObfuscator 1.0.0

dotnet add package PELock.PythonObfuscator --version 1.0.0
                    
NuGet\Install-Package PELock.PythonObfuscator -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PELock.PythonObfuscator" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PELock.PythonObfuscator" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="PELock.PythonObfuscator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PELock.PythonObfuscator --version 1.0.0
                    
#r "nuget: PELock.PythonObfuscator, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PELock.PythonObfuscator@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PELock.PythonObfuscator&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=PELock.PythonObfuscator&version=1.0.0
                    
Install as a Cake Tool

Python Obfuscator — Obfuscate, Virtualize & Protect Python Code

Python Obfuscator is a tool to obfuscate, virtualize & protect Python .py scripts against reverse engineering with a VM engine (or finite-state automata machine), self-defending integrity checks, polymorphic string encryption, anti-debugging, anti-vm, anti-emulation and 50+ total obfuscation strategies!

This repository contains the C# / .NET WebApi client SDK, distributed as the PELock.PythonObfuscator NuGet package.

It's available for Windows & Linux, plus VSCode/Cursor extension:

Multiple programming APIs available:

An online obfuscator interface:

Why Python scripts need obfuscation?

Scripts are typically distributed as plain .py files or bundled inside packages. That convenience means anyone with file access can read the full logic, hunt for credentials or API keys in strings, and steal your algorithms unless you take extra steps to hide intent.

Python is one of the most popular general-purpose scripting languages. It is widely used for automation, backend services, data processing, tooling, and licensing/agent code that customers run on their own machines.

Obfuscation strategies

Python Obfuscator comes with many advanced obfuscation, virtualization & protection strategies. You can easily tune protection versus size and performance.

Python Obfuscation options

Obfuscation Powerful obfuscation

Polymorphic string encryption is the core of the string pipeline: each build generates a fresh decryptor so literals never share one static algorithm. Integers, floats, and decoy noise join that layer. The result conceals literals and structure while preserving tested runtime behaviour.

Processor Code virtualization

Code virtualization is the main control-flow defense. Selected statements are lifted into a randomly generated VM engine (or FSA / flattened dispatcher) with shuffled dispatch tables, decoy opcodes, and an obfuscated dispatcher loop. Analysts must interpret the virtual machine instead of reading plain Python.

Node Finite-state automata (FSA)

Finite-state automata (FSA) obfuscation rewrites linear Python statement blocks into dual-state automata with opaque schedulers and shuffled dispatch handlers. Instead of reading code top to bottom, analysts must follow numeric states, transition tables, and decoy paths to reconstruct the original order.

Bug Anti-debugging

Anti-debugging protection inserts polymorphic probes that detect attached debuggers, tracing hooks, and related host signals, together with anti-VM, anti-sandbox and anti-emulator checks. When a check fires, the obfuscated script exits silently instead of revealing protected logic under interactive analysis.

System monitor Self-integrity checks

Self-defending integrity checks verify that the obfuscated file has not been patched. A bootstrap probe hashes the on-disk script and sets a tamper key when it no longer matches the obfuscated build. String decryptors consume that key, so edited scripts return garbage instead of plaintext.

The protection linker adds decoy functions and fake calls so a copied fragment still looks like real program code. Hidden traps fire only if someone edits the file or runs a piece of it on its own. When the script starts normally, those extras stay silent and the program runs as usual.

Before and after obfuscation

Look at this example — the same script becomes harder to read at a glance after obfuscation.

Sample Python script before obfuscation

label = 'SecretKey'
port = 443

def get_sum(a, b):
    return a + b

print(label, port)
r = get_sum(11, 31)
print(r)

After obfuscation

Obfuscated Python script

Would you still recognise the original intent if you only had the obfuscated text and no prior copy of the script?

How does Python Obfuscator work?

The engine parses Python source into an AST tree, then applies selectable transforms. Code virtualization (VM, FSA, or flattening) rewrites execution so analysts cannot read the script top to bottom. Polymorphic string encryption hides literals; self-defending integrity probes detect patched files. Also available: identifier renaming, numeric encryption, noise and decoy insertion, the protection linker, and anti-debugging checks. Many techniques are specific to this product; some ideas are shared with our other protection tools.

Python Obfuscator Pipeline

When all passes finish, the engine emits a new .py file. Edge cases in the Python grammar and hosting environments mean you should always test the output in your target runtime.

Protect your Python scripts & algorithms

Take no chances, use Python Obfuscator to obfuscate, virtualize and protect your Python scripts and algorithms.

Our company has a long history in obfuscation technologies and code obfuscators (see our PowerShell, Java, AutoIt, x86 Assembly & obfuscators).

We actively bugfix, research and develop new obfuscation strategies for our tools.

You can count on our expertise and support in this field.

Installation

The preferred way of WebApi interface installation is via NuGet (targets .NET 8). Package id: PELock.PythonObfuscator.

Run:

dotnet add package PELock.PythonObfuscator

From Visual Studio NuGet Package Manager Console:

Install-Package PELock.PythonObfuscator

Or add this entry directly to your .csproj file in ItemGroup / PackageReference:

<ItemGroup>
  <PackageReference Include="PELock.PythonObfuscator" Version="1.0.0" />
</ItemGroup>

Then import the client namespace and create an instance:

using PELock.PythonObfuscator;

var myPythonObfuscator = new PythonObfuscator("ABCD-ABCD-ABCD-ABCD");

The package is available at https://www.nuget.org/packages/PELock.PythonObfuscator/. To run the included samples from this repository, use each example project alongside python-obfuscator-example*.cs:

dotnet run --project examples/python-obfuscator-example-simple.csproj

Example of obfuscating Python script source code using default options

/******************************************************************************
 * Python Obfuscator WebApi interface usage example.
 *
 * In this example we will obfuscate sample source with default options.
 *
 * Version        : v1.0.0
 * Language       : C#
 * Author         : Bartosz Wójcik
 * Web page       : https://www.pelock.com
 *
 *****************************************************************************/

using PELock.PythonObfuscator;

//
// create Python Obfuscator class instance (we are using our activation key)
//
var myPythonObfuscator = new PythonObfuscator("ABCD-ABCD-ABCD-ABCD");

//
// source code in Python format
//
const string ScriptSourceCode =
    """
    label = 'SecretKey'
    port = 443

    def get_sum(a, b):
        return a + b

    print(label, port)
    r = get_sum(11, 31)
    print(r)
    """;

//
// by default all obfuscation options are enabled, so we can just simply call:
//
var result = await myPythonObfuscator.ObfuscateScriptSourceAsync(ScriptSourceCode);

//
// it's also possible to pass a Python script file path instead of a string e.g.
//
// var result = await myPythonObfuscator.ObfuscateScriptFileAsync("/path/to/project/script.py");

//
// result object holds the obfuscation results as well as other information
//
// result?.Error           - error code (see PythonObfuscator.Error*)
// result?.Output          - obfuscated code
// result?.Demo             - demo mode (empty/invalid key); strategy flags ignored; always integers_to_arrays, mba_binops, encrypt_strings (no virt; 1000 char limit)
// result?.LicenseExpiration - license end date (Y-m-d), empty if none
// result?.UsagesTotal     - total obfuscations for this activation code
//
if (result is not null)
{
    //
    // display obfuscated code
    //
    if (result.Error == PythonObfuscator.ErrorSuccess && result.Output is not null)
        Console.WriteLine(result.Output);
    else
        throw new InvalidOperationException("An error occurred, error code: " + result.Error);
}
else
{
    throw new InvalidOperationException("Something unexpected happen while trying to obfuscate the code.");
}

An example of obfuscating Python script source code with customized obfuscation strategies

/******************************************************************************
 * Python Obfuscator WebApi interface usage example.
 *
 * In this example we will obfuscate sample source with every public option
 * set, so you can see the full client surface and turn flags on or off.
 *
 * Version        : v1.0.0
 * Language       : C#
 * Author         : Bartosz Wójcik
 * Web page       : https://www.pelock.com
 *
 *****************************************************************************/

using PELock.PythonObfuscator;

//
// create Python Obfuscator class instance (we are using our activation key)
//
var myPythonObfuscator = new PythonObfuscator("ABCD-ABCD-ABCD-ABCD");

//
// should the source code be compressed (both input & compressed)
//
myPythonObfuscator.EnableCompression = false;

//
// globals
//
// fixed random seed for reproducible obfuscation output (optional)
//
myPythonObfuscator.Seed = null;

//
// randomization density / intensity (0-100)
//
myPythonObfuscator.RandomizationDensity = null;

//
// identifier renaming style: RenameStyle.Il, O0, Confusable, Hex, Homoglyph, or Mangled
//
myPythonObfuscator.RenameStyle = RenameStyle.Il;

//
// code virtualization (exactly one): VM, FSA, or FLAT
// set to null to skip virtualization
//
myPythonObfuscator.CodeVirtualization = CodeVirtualization.VM;

//
// protection (opt-in on the service for --all; shown enabled here so every flag is visible)
//
// protection against tampering with protected code (integrity verification)
//
myPythonObfuscator.SelfDefending = true;

//
// protection linker (decoy call graph; requires SelfDefending)
//
myPythonObfuscator.ProtectionLinker = true;

//
// insert anti-debugging detections
//
myPythonObfuscator.DetectDebugger = true;

//
// insert virtual machine (anti-VM) detections
//
myPythonObfuscator.AntiVm = true;

//
// insert anti-sandbox detections
//
myPythonObfuscator.AntiSandbox = true;

//
// insert anti-emulators (CPU) detections
//
myPythonObfuscator.AntiEmulator = true;

//
// renaming
//
// rename variable names to random string values
//
myPythonObfuscator.RenameVariables = true;

//
// rename parameter names to random string values
//
myPythonObfuscator.RenameParameters = true;

//
// rename function names to random string values
//
myPythonObfuscator.RenameFunctions = true;

//
// rename function call references consistently with renamed functions
//
myPythonObfuscator.RenameFunctionCalls = true;

//
// shuffle function order in the output source
//
myPythonObfuscator.ShuffleFunctions = true;

//
// fold/resolve constant expressions at obfuscation time
//
myPythonObfuscator.ResolveConstants = true;

//
// strings
//
// split strings into concatenated chunks
//
myPythonObfuscator.SplitStrings = true;

//
// apply light transformations/mutations to string literals
//
myPythonObfuscator.ModifyStrings = true;

//
// encrypt strings using randomly generated polymorphic encryption algorithms
//
myPythonObfuscator.EncryptStrings = true;

//
// store string fragments in char-code array vaults
//
myPythonObfuscator.StringCharArrayVault = true;

//
// numeric
//
// encrypt integers
//
myPythonObfuscator.EncryptIntegers = true;

//
// encrypt floating point numbers
//
myPythonObfuscator.EncryptFloating = true;

//
// replace binary operators with mixed boolean-arithmetic (MBA) equivalents
//
myPythonObfuscator.MbaBinops = true;

//
// represent integers via floating-point math
//
myPythonObfuscator.IntegersToFloating = true;

//
// move integers to arrays
//
myPythonObfuscator.IntegersToArrays = true;

//
// move floats to arrays
//
myPythonObfuscator.FloatsToArrays = true;

//
// apply redundant xor / affine integer masks
//
myPythonObfuscator.AffineIntegerMask = true;

//
// encrypted array literals
//
// encrypt integer array literals
//
myPythonObfuscator.ArrayIntCrypt = true;

//
// encrypt character array literals
//
myPythonObfuscator.ArrayCharCrypt = true;

//
// encrypt floating-point array literals
//
myPythonObfuscator.ArrayDoubleCrypt = true;

//
// encrypt string array literals
//
myPythonObfuscator.ArrayStringCrypt = true;

//
// decoy value pools
//
// insert a shared bucket of random noise values used by other strategies
//
myPythonObfuscator.InsertRandomValueBucket = true;

//
// populate the random value bucket with decoy integers
//
myPythonObfuscator.RandomBucketIntegers = true;

//
// populate the random value bucket with decoy arrays
//
myPythonObfuscator.RandomBucketArrays = true;

//
// populate the random value bucket with decoy functions
//
myPythonObfuscator.RandomBucketFunctions = true;

//
// populate the random value bucket with decoy characters
//
myPythonObfuscator.RandomBucketCharacters = true;

//
// populate the random value bucket with anti-regex decoy noise
//
myPythonObfuscator.RandomBucketAntiRegex = true;

//
// populate the random value bucket with autostart decoy stubs
//
myPythonObfuscator.RandomBucketAutostart = true;

//
// opaque predicates & noise
//
// rewrite selected statements using ternary operators
//
myPythonObfuscator.InsertTernaryOperators = true;

//
// replace boolean conditions with equivalent complex expressions
//
myPythonObfuscator.ComplexifyBooleans = true;

//
// insert opaque predicate branches
//
myPythonObfuscator.OpaqueBranches = true;

//
// insert opaque mixer chains into control flow
//
myPythonObfuscator.OpaqueMixerChain = true;

//
// insert dead code
//
myPythonObfuscator.InsertDeadCode = true;

//
// wrap code in try/finally blocks with dead noise
//
myPythonObfuscator.TryFinallyNoise = true;

//
// decoys
//
// insert decoy functions
//
myPythonObfuscator.DecoyFunctions = true;

//
// insert decoy lambda expressions
//
myPythonObfuscator.LambdaDecoys = true;

//
// insert literal padding noise
//
myPythonObfuscator.LiteralPadding = true;

//
// insert fake import statement markers
//
myPythonObfuscator.FakeImportMarkers = true;

//
// use dynamic getattr()-based indirect calls
//
myPythonObfuscator.DynamicGetattrCalls = true;

//
// rewrite absolute imports into __import__ / getattr
//
myPythonObfuscator.ObfuscateImports = true;

//
// insert dead callback/event registration stubs
//
myPythonObfuscator.CallbackRegistrationStubs = true;

//
// other
//
// strip comments from the output source
//
myPythonObfuscator.RemoveComments = true;

//
// source code in Python format
//
const string ScriptSourceCode =
    """
    label = 'SecretKey'
    port = 443

    def get_sum(a, b):
        return a + b

    print(label, port)
    r = get_sum(11, 31)
    print(r)
    """;

//
// obfuscate the source code with the options set above
//
var result = await myPythonObfuscator.ObfuscateScriptSourceAsync(ScriptSourceCode);

//
// it's also possible to pass a Python script file path instead of a string e.g.
//
// var result = await myPythonObfuscator.ObfuscateScriptFileAsync("/path/to/project/script.py");

//
// result object holds the obfuscation results as well as other information
//
// result?.Error           - error code (see PythonObfuscator.Error*)
// result?.Output          - obfuscated code
// result?.Demo             - demo mode (empty/invalid key); strategy flags ignored; always integers_to_arrays, mba_binops, encrypt_strings (no virt; 1000 char limit)
// result?.LicenseExpiration - license end date (Y-m-d), empty if none
// result?.UsagesTotal     - total obfuscations for this activation code
//
if (result is not null)
{
    //
    // display obfuscated code
    //
    if (result.Error == PythonObfuscator.ErrorSuccess && result.Output is not null)
        Console.WriteLine(result.Output);
    else
        throw new InvalidOperationException("An error occurred, error code: " + result.Error);
}
else
{
    throw new InvalidOperationException("Something unexpected happen while trying to obfuscate the code.");
}

Check activation key status

/******************************************************************************
 * Python Obfuscator WebApi interface usage example.
 *
 * In this example we will verify our activation key status.
 *
 * Version        : v1.0.0
 * Language       : C#
 * Author         : Bartosz Wójcik
 * Web page       : https://www.pelock.com
 *
 *****************************************************************************/

using PELock.PythonObfuscator;

//
// create Python Obfuscator class instance (we are using our activation key)
//
var myPythonObfuscator = new PythonObfuscator("ABCD-ABCD-ABCD-ABCD");

//
// login to the service
//
var result = await myPythonObfuscator.LoginAsync();

//
// result object holds the information about the license
//
// result?.Demo           - demo mode (empty/invalid key); strategy flags ignored; always integers_to_arrays, mba_binops, encrypt_strings (no virt; 1000 char limit)
// result?.LicenseExpiration - license end date (Y-m-d), empty if none
// result?.UsagesTotal     - total obfuscations for this activation code
// result?.StringLimit     - Max. source code size allowed (it's 1000 bytes for demo mode)
//
if (result is not null)
{
    Console.WriteLine("Demo version status - " + (result.Demo == true ? "true" : "false"));
    Console.WriteLine("License expiration - " + result.LicenseExpiration);
    Console.WriteLine("Total obfuscations - " + result.UsagesTotal);
    Console.WriteLine("Max. source code size - " + result.StringLimit);
}
else
{
    throw new InvalidOperationException("Something unexpected happen while trying to login to the service.");
}

Skip selected functions and classes

Use the Python Obfuscator Decorator package to mark functions and classes that should skip chosen strategies. You need it only to run original source. The obfuscator reads @obfuscator.skip from the AST, applies the skip, then strips the decorator and unused import obfuscator lines. Obfuscated output has no runtime dependency on this package.

Package on PyPI: https://pypi.org/project/python-obfuscator-decorator/

Installation

pip install python-obfuscator-decorator

or

python3 -m pip install python-obfuscator-decorator

Import package name: obfuscator. PyPI distribution name: python-obfuscator-decorator.

Simple usage

import obfuscator


@obfuscator.skip()
def handshake(secret: str) -> str:
    """Skip every mutating strategy on this function."""
    return secret

Also valid:

  • @obfuscator.skip(obfuscator.ENCRYPT_STRINGS, obfuscator.CODE_VIRTUALIZATION) — skip listed strategies
  • @obfuscator.skip("encrypt_strings") — string keys match engine strategy names
  • @obfuscator.skip (bare, no call) — skip every mutating strategy on that construct
  • import obfuscator as alias then @alias.skip(...)

CODE_VIRTUALIZATION skips all virtualization modes (VM, FSA, flatten) on that function or class.

Use Python Obfuscator Online

Online interface for Python Obfuscator is available at:

https://www.pelock.com/python-obfuscator/

Windows GUI client and command line version

You can download it at:

https://www.pelock.com/products/python-obfuscator/download

Python Obfuscator comes also with full GUI version for Windows

Python Obfuscator Windows Client

Obfuscation options

Python Obfuscation options

Command line interface aka CLI

Python Obfuscator ships with a command-line interface for Windows and Linux automation. Use it to integrate obfuscation into build servers, CI jobs, or batch packaging.

Python Obfuscator command-line interface

Demo mode limitations

In demo mode the obfuscator always applies integers_to_arrays, mba_binops, and encrypt_strings (no code virtualization). Source size is limited to 1000 characters.

Bartosz Wójcik

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 20 9/17/2026