Library / SDK
ssut/payload-dumper-go avatar
ssut/payload-dumper-go

payload-dumper-go: extracting Android OTA payloads from the command line

an android OTA payload dumper written in Go

3,531 stars295 forksGoApache-2.0

At a glance

What is it?
A Go rewrite of the classic Python payload dumper that parallelises decompression, handles incremental OTA delta payloads, and regenerates the dm-verity metadata that delta payloads omit. It is a CLI for people who need the raw partition images out of an OTA, not a flashing tool.
Who is it for?
Adopt payload-dumper-go if you routinely pull partition images out of full or incremental Android OTAs and want the dm-verity hash tree and FEC parity rebuilt without avbtool or fec in the loop. Skip it if your target payload uses PUFFDIFF, ZUCCHINI or LZ4DIFF_* delta operations, since the README states those are unsupported and the affected partitions fail with an error; you can still extract the rest with -p.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

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

Editorial analysis

The problem: an OTA zip is not a set of images

Android OTA packages do not ship as ready-to-flash partition images. A full OTA carries a payload.bin whose operations describe how each partition is assembled from compressed blocks, and an incremental OTA carries only the difference against a previous build. Getting a boot.img or a system.img out of that means parsing the update engine metadata, decompressing every operation, and stitching the pieces back together in the right order. The README frames the project as an android OTA payload dumper written in Go, and that is exactly the job: turn payload.bin, or an OTA zip containing one, into individual image files on disk. The audience is narrow but real. ROM builders, people inspecting vendor blobs, and anyone who needs a partition image rather than a flashable package. It is not a fastboot replacement, and the README never presents it as one.

How the dumper turns payload operations into image files

The input is detected by content, so the same command accepts a raw payload.bin or the OTA zip that contains it. The README notes that a zip is read in place without a temp copy, which matters when a full OTA runs to several gigabytes. From there the tool parses the update engine manifest, which is why the repository carries chromeos_update_engine/ and update_metadata.proto, and lists the partitions it found. Decompression is where the Go rewrite differs from the older Python dumper: the README states that all decompression progresses are executed in parallel, and the -c flag sets the number of workers, defaulting to the number of CPUs. The dependency list in go.mod shows brotli, zstd, xz and dsnet/compress, so the block formats the payload can use are covered by Go libraries, with one exception. The README is explicit that xz remains a system dependency and that the pure Go implementation was rejected on performance grounds. For incremental payloads the flow changes: base images are supplied with -old, delta operations are applied on top, and the README claims bit-exact output. Delta payloads omit the dm-verity hash tree and FEC parity for partitions such as system and vendor, so the dumper computes both itself, which is why avbtool and the fec tooling are not needed. Verification runs throughout: operation data, source images and final images are checked with sha256, and failures exit non-zero.

Installing payload-dumper-go and dumping a first payload

The README recommends the release binaries for Linux and macOS. Download the archive for your platform, extract it, then make the binary executable and put its directory on PATH for the current shell. The README warns that the export only lasts for the session and that making it permanent means editing a profile file such as .bashrc or .zshrc.

bash
chmod +x payload-dumper-go
export PATH=$PATH:/path/to/payload-dumper-go

On macOS there is a Homebrew formula, so installation is a single command and no manual PATH work.

bash
brew install payload-dumper-go

Windows users download the same release archive and add the extracted directory to the system Path variable through the Environment Variables dialog, as the README describes step by step. Before running anything, install xz on the system; the README calls it the one dependency you need. A first run takes the path to a payload.bin or an OTA zip and writes images to the working directory.

bash
payload-dumper-go /path/to/payload.bin

If you only want to know what is inside before committing disk space, -l prints the partition list. To pull specific partitions and direct the output elsewhere, combine -p with -o.

bash
payload-dumper-go -l /path/to/payload.bin
payload-dumper-go -p boot,vendor_boot -o out /path/to/payload.bin

For an incremental OTA, extract the base build first and pass that directory with -old. The README gives this two-step example.

bash
payload-dumper-go -o base_images base_full_ota.zip
payload-dumper-go -old base_images -o new_images incremental_ota.zip

The README also documents -q for quiet mode and -m for machine-readable output, which is what you would parse from a script. The project can also be imported as a Go library from github.com/ssut/payload-dumper-go/payload, with payload.Open and an ExtractOptions struct taking OutputDir and SourceDir.

Where payload-dumper-go stops: delta formats and FEC verification

The limitations section is the most useful part of the README. PUFFDIFF, ZUCCHINI and LZ4DIFF_* delta operations are not supported yet. Partitions affected by those operations, usually system, product and system_ext, fail with a clear error, and the README's suggested workaround is to extract the remaining partitions with -p. That is a workable escape hatch for inspecting a modem or a boot image, and a dead end if the partition you actually need is the one that failed. The second constraint is -no-fec. It skips FEC generation and final image verification for partitions that require FEC, and the README states plainly that those images must not be flashed; the option exists for inspecting contents. There is a timing trap attached to it: -m reports 100% when the operations finish while FEC is still running, so a script that treats 100% as completion will read a half-finished output. The README says to wait for the process to exit. Hardware is a constraint too. The README recommends an SSD and notes that an HDD can be a bottleneck, which is a realistic warning given that a single payload in the documented performance example lists a 3.4 GB product partition.

payload-dumper-go against the Python payload_dumper and avbtool

The obvious comparison is the Python payload_dumper that this project replaces. The difference is not the interface, which is a positional payload path in both cases, but the execution model and the verification story. The README attributes the speed to parallel decompression across workers, and the Go build produces a single static binary, so there is no Python environment to assemble on the target machine. The Dockerfile shows the shape of that binary: a CGO_ENABLED=1 build against liblzma, copied into a scratch image, running as user 65534:65534 with /data as the working directory. That container is a legitimate way to run the dumper on a machine where you would rather not install xz system-wide. The other comparison is against the Android platform tooling. avbtool and the fec tools can regenerate dm-verity metadata, but they are separate programs with their own inputs, and the README's claim is that this dumper computes the hash tree and FEC parity as part of extraction, so a delta payload's output comes out bit-exact without a second toolchain. That is a real difference in approach, not a cosmetic one: the metadata generation is folded into the dump rather than bolted on afterwards.

Licence, releases and what maintenance costs you

The project is Apache-2.0. For most users that means you can use the binary and the library, including in commercial work, provided you keep the licence and notices intact; the usual caveat about patent grants and attribution applies, and this is not legal advice. The practical upgrade cost is low because the interface is a handful of flags and a positional path. The last push to the repository was on 2026-09-23, and release 2.1.0 is dated the same day, with 2.0.2 on 2026-08-20 and 2.0.1 on 2026-08-19. Anyone pinning a version should read CHANGELOG.md before moving, since the 2.x line is recent enough that flag behaviour could shift between point releases. The dependency surface is small and visible in go.mod, but note that the module declares go 1.27.0 and the Dockerfile builds on golang:1.27, so building from source demands a recent toolchain, and the CGO dependency on liblzma means a from-source build on Linux needs liblzma-dev present. Release binaries and the Homebrew formula are the paths that avoid that entirely.

Editorial conclusion

Adopt payload-dumper-go if you routinely pull partition images out of full or incremental Android OTAs and want the dm-verity hash tree and FEC parity rebuilt without avbtool or fec in the loop. Skip it if your target payload uses PUFFDIFF, ZUCCHINI or LZ4DIFF_* delta operations, since the README states those are unsupported and the affected partitions fail with an error; you can still extract the rest with -p. Skip it too if you want a flashing tool rather than a dumper. Before you rely on it, confirm that xz is installed on the host, that your working directory sits on an SSD, and that the release binary or Homebrew formula matches your platform.

Frequently asked questions

What is payload-dumper-go?

It is an Android OTA payload dumper written in Go. It reads a payload.bin or an OTA zip and writes out the individual partition images, with parallel decompression and sha256 verification.

How do I install payload-dumper-go?

On Linux and macOS the README recommends downloading the release binary for your platform, making it executable with chmod +x, and adding its directory to PATH. On macOS you can instead run brew install payload-dumper-go. On Windows you download the release archive and add the extracted directory to the system Path variable.

How do I use payload-dumper-go?

Run it with the path to a payload.bin or an OTA zip, for example payload-dumper-go /path/to/payload.bin. Useful flags include -l to list partitions, -p to select partitions, -o to set the output directory, and -old for incremental OTA payloads.

What is a payload dumper?

It is a tool that reads an Android OTA payload, either a raw payload.bin or the OTA zip containing one, and writes out the partition images inside it. payload-dumper-go is one such tool, written in Go.

How do I extract an OTA file with payload-dumper-go?

The README states the input can be a raw payload.bin or an OTA zip, detected by content, and that the zip is read in place without a temp copy. Passing the zip path to the command extracts its partitions.

How do I extract payload.bin on Android with payload-dumper-go?

Run payload-dumper-go with the path to payload.bin. The README's example is payload-dumper-go /path/to/payload.bin, and -l lists the partitions before you extract them.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. ssut/payload-dumper-go on GitHub
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/ssut-payload-dumper-go.svg)](https://hysenlabs.com/projects/ssut-payload-dumper-go)