Library / SDK
pyinstxtractor/pyinstxtractor-ng avatar
pyinstxtractor/pyinstxtractor-ng

pyinstxtractor-ng unpacks a PyInstaller executable without matching Python

PyInstaller Extractor Next Generation

744 stars74 forksPythonGPL-3.0

At a glance

What is it?
pyinstxtractor-ng is a Python tool that extracts the contents of PyInstaller generated executables, both Linux ELF and Windows PE, and unlike the original pyinstxtractor it unmarshals bytecode through xdis, so the Python version used to build the target does not matter. It can also decrypt encrypted PyInstaller payloads.
Who is it for?
pyinstxtractor-ng suits a reverse engineer or malware analyst who receives a PyInstaller bundle and needs the original Python source or bytecode out of it, since it handles both Linux and Windows artefacts, decrypts encrypted payloads and can inspect an archive without writing anything to disk.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Unpacking a bundle, not decompiling a program

pyinstxtractor-ng is a tool to extract the contents of a PyInstaller generated executable file, and both Linux ELF and Windows PE executables are supported. The project is a fork of pyinstxtractor.

The distinction between extraction and decompilation matters for setting expectations. The tool gets the payload of the archive out of the executable: the embedded Python modules, the compiled bytecode, the data files, the bundled libraries. Turning that bytecode back into readable Python source is a separate step that this tool does not perform, even though its topics list includes decompiler and python-decompiler.

That is the right scope for the job. PyInstaller packages a Python application into a single executable by appending an archive to a bootloader, and the archive has its own format. Unpacking it is a matter of locating the archive, walking its table of contents and writing the entries out, and doing that reliably across build versions is the tedious part that a maintained fork handles better than a script you find in a forum post.

The licence is GNU General Public License v3.0, the primary language is Python, and the last push was on 2026-10-08 with release tags dated 2026.07.03, 2026.04.07 and 2025.01.05.

xdis is what removes the Python version constraint

The technical decision that distinguishes this fork from the original is the use of the xdis library to unmarshal Python bytecode. The consequence is stated in the README as a flat requirement: there is no requirement to use the same Python version which was used to build the executable.

That sounds like a small thing until you have an executable in front of you. The bytecode format changes between Python versions, and a tool that unmarshals bytecode with the running interpreter's own marshal module can only read archives built for that interpreter. An analyst on a modern Python would simply fail on a bundle built years ago, with an error that says nothing useful.

Unmarshalling through xdis instead means the version awareness is data rather than an ambient property of the tool.

The dependency list is short and pinned. The manifest declares xdis==6.3.0 and pycryptodome>=3.19.1,<4, and the requirements file names the same two, with PyCryptoDome>=3.19.1,<4. The project requires Python 3.8 or later, and the poetry dependency block narrows that to >=3.8,<3.13, which is a hint that the project is tested up to Python 3.12 and not beyond.

The console entry point is registered as pyinstxtractor-ng, mapped to the main function of the pyinstxtractor_ng module, and the package ships that module as a single file rather than a package directory.

Running it as a binary, without a Python install

The distribution model is the other thing that sets this tool apart. Precompiled binaries for Linux and Windows are provided in the releases, and they are generated using PyInstaller itself, so you do not even need a Python installation to run pyinstxtractor-ng.

That is a deliberate choice for an analysis tool. The person most likely to need it is looking at a suspicious file on a machine that is not their own development box, and asking them to set up a Python environment first is a good way to lose them.

The command line is three options and one positional argument:

code
PyInstaller Extractor NG

positional arguments:
  filename       Path to the file to extract

optional arguments:
  -h, --help     show this help message and exit
  -d, --one-dir  One directory mode, extracts the pyz to the same directory
  -i, --info      Display PyInstaller archive information without extracting files

On Windows you can also drag and drop the PyInstaller executable over the pyinstxtractor.ng icon, which saves typing a path into a shell prompt.

The two modes do different jobs and the distinction is worth holding on to. The --one-dir mode extracts the pyz in the same directory as the executable, which the README says is useful if you want to run the extracted files straight-away:

code
X:\> pyinstxtractor-ng --one-dir main.exe
X:\> cd main.exe_extracted
X:\main.exe_extracted\> python main.py

The --info or -i option prints metadata about the PyInstaller archive without writing any extracted files to disk, which the README calls useful for quick inspection and debugging.

Encrypted PyInstaller bundles are handled too

pyinstxtractor-ng also supports automatic decryption of encrypted PyInstaller executables, and that is a significant capability rather than a footnote.

PyInstaller can encrypt the contents of the bundled archive with a key derived from the executable itself, and a tool that cannot decrypt produces a directory of unreadable blobs. Being able to take an encrypted payload and land on the same view of the archive as an unencrypted one removes a step that otherwise requires a separate script and some knowledge of the bootloader.

The pycryptodome dependency is what does that work, which is why it is pinned at a specific minor range rather than left open.

The practical sequence for an analyst is therefore short. Run the tool with --info to see the archive layout without touching the disk, then extract, then look at what came out. Doing the inspection first is worth the extra second because it tells you whether the bundle is what you think it is, for example whether the module list matches the application's dependencies or whether something else has been added.

There is a related project worth knowing about, pyinstxtractor-web, which runs pyinstxtractor in the web browser and is powered by Go and GopherJS. That is a different deployment for the same idea, and it matters for cases where you do not want to move a suspicious file off the machine you are analysing it on.

What it will not give you

The boundary of the tool is worth stating plainly, because the name suggests more than it does.

It does not decompile. The output is Python bytecode in the form PyInstaller stored it, and reading that bytecode requires a decompiler such as a Python specific one, or the disassembly tools that come with a matching interpreter. If the goal is source code, extraction is the first step rather than the last one.

It is also not a general archive tool. The format it understands is the one PyInstaller produces, and the executable has to be a PyInstaller bundle in the first place. An Electron app packaged with asar, or a Go binary, or a .NET single file publish, will not be understood by it.

The decrypted payload case has a second limitation that follows from the first. Decrypting gets you the archive, and the archive gets you the modules, but a malicious bundle may contain anti analysis behaviour in its own bootstrap code, and the extraction happens before any of that runs, so the recovered files are what the packer decided to include rather than a guarantee about what the program would do.

For the common case, a legitimate application distributed as a single file that somebody else needs to read, the tool is the right size for the job.

Editorial conclusion

pyinstxtractor-ng suits a reverse engineer or malware analyst who receives a PyInstaller bundle and needs the original Python source or bytecode out of it, since it handles both Linux and Windows artefacts, decrypts encrypted payloads and can inspect an archive without writing anything to disk. It is the wrong tool for a PyInstaller build you control, where the source is already on disk, and it does not decompile the recovered bytecode into readable Python, it only unpacks it. Before relying on it, run the --info mode first to see what the archive contains, and check that the recovered files are what you expect rather than assuming the extraction is complete.

Frequently asked questions

Do I need the same Python version as the target executable to run pyinstxtractor-ng?

No. pyinstxtractor-ng uses the xdis library to unmarshal Python bytecode, and the README states that as a result there is no requirement to use the same Python version which was used to build the executable. The project itself requires Python 3.8 or later, with the poetry block narrowing that to >=3.8,<3.13.

How do I inspect a PyInstaller archive without extracting it?

Use the --info or -i option, which prints metadata about the PyInstaller archive without writing any extracted files to disk. The README describes that as useful for quick inspection and debugging.

Does pyinstxtractor-ng handle encrypted PyInstaller executables?

Yes. The README states that pyinstxtractor-ng supports automatic decryption of encrypted PyInstaller executables, which is what the pycryptodome dependency is there for. Note that the tool extracts the archive contents rather than decompiling the recovered bytecode into readable Python.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. pyinstxtractor/pyinstxtractor-ng on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pyinstxtractor-pyinstxtractor-ng.svg)](https://hysenlabs.com/projects/pyinstxtractor-pyinstxtractor-ng)

Was this useful?