Skip to content

yibiner/ProtoDecodeX

 
 

Repository files navigation

ProtoDecodeX

License

English | 简体中文 | Live demo

ProtoDecodeX is a Protobuf wire-format decoder that runs in the browser.

It is built for the annoying cases: you have raw bytes, maybe no .proto, maybe only a log dump or a copied payload from a proxy, and you still need to figure out what is inside.

ProtoDecodeX screenshot

What this tool is for

This is not a big all-in-one Protobuf tool. It is closer to a workbench for the moments when you need to inspect Protobuf data quickly, without spinning up a backend service or dragging in a full code-generated setup.

It is useful when you want to answer questions like:

  • What fields are in this payload?
  • Is this hex, Base64, a Java byte array, or a Java escaped string?
  • Does this stream contain length-delimited messages?
  • Can I paste a small .proto snippet and map field numbers to names?
  • Is that bytes field XOR-encoded, and can I keep digging?

Everything runs locally in the browser. You can paste data, upload a file, inspect the wire structure in a table, and add a lightweight schema when it helps.

Use cases

  • Reverse engineering unknown Protobuf messages
  • Inspecting binary payloads pulled from logs, packet captures, or proxies
  • Looking at gRPC message bodies
  • Working with Java byte arrays or escaped strings from code and logs
  • Peeling through nested bytes fields one layer at a time

Why this exists

Most Protobuf tools assume you already know the schema. Real debugging is often messier than that.

Sometimes you only have:

  • a chunk of hex from a log
  • a Base64 blob from an API trace
  • a Java byte dump
  • a gRPC payload with framing still attached

ProtoDecodeX starts from that kind of raw input. First get the wire format in view, then add just enough context to make the data readable.

Features

  • Supports hex, Base64, Java decimal byte arrays, Java escaped strings, and local file upload
  • Detects the input format and normalizes it into readable hex
  • Decodes Protobuf wire data into a table with expandable content
  • Parses varint length-delimited message streams
  • Tries to skip gRPC framing headers when present
  • Lets you paste message definitions for schema-aware display
  • Includes Smart Decode for conditional XOR and manual XOR workflows
  • Lets you reuse decrypted bytes as the current decode input
  • Persists useful state in localStorage
  • The repo also includes tests, CI, Docker, and deployment config

Supported input formats

Format Example
Hex bytes 08 96 01
Base64 CJYB
Java decimal byte array 8, 150, 1
Java escaped string \010\226\001
Local file upload Any local binary file read by the browser

Quick start

Requirements

  • Node.js 20 is recommended to match CI
  • npm

Local development

npm install
npm start

Then open http://localhost:3000.

Build for production

npm run build

The build output goes to build/.

Run tests

npm test

How to use it

  1. Paste raw data or upload a file.
  2. ProtoDecodeX detects the input format and normalizes it into pretty hex.
  3. Click Decode to parse the payload into Protobuf wire parts.
  4. Inspect the result table, byte ranges, and nested byte fields.
  5. Optionally enable advanced tools such as schema-based display or Smart Decode.

A closer look

Wire-format inspection

The decoder shows the pieces that matter when you are staring at unknown payloads:

  • Field number
  • Wire type
  • Byte range
  • Raw value bytes
  • Nested message-like structures when applicable

That is usually enough to sketch the shape of the message even when the original .proto file is nowhere to be found.

Normalized hex view

Every supported input format ends up in the same normalized, read-only hex view. It is a simple idea, but it helps a lot when the original source came from logs, Java arrays, or escaped strings and you want one clean byte representation before you go further.

Length-delimited stream parsing

If your input contains multiple messages with varint length prefixes, enable parse varint length delimited input and the app will split the stream into message boundaries. This comes up more often than you would think in batched payload dumps and stream-oriented transports.

gRPC frame handling

If the payload looks like it starts with a gRPC frame header, the decoder tries to skip it before parsing. Small thing, but it saves an annoying manual step.

Schema-based display

You can paste lightweight message definitions in the advanced panel to map field numbers to names and types.

Example:

message User {
  string name = 1;
  uint32 age = 2;
  repeated string tags = 3;
}

With a schema in place, ProtoDecodeX can show:

  • Field names instead of only field numbers
  • Basic type-aware rendering such as string, bool, float, and double
  • Repeated and optional field hints

The parser is intentionally lightweight. Good enough for quick inspection, not meant to replace full .proto compilation.

Smart Decode and XOR workflows

Some payloads hide the useful part inside a bytes field and then add a simple XOR step on top. The Smart Decode panel supports two workflows:

  • Conditional XOR: decode one field with the value from another field, optionally gated by a varint field condition
  • Manual XOR: paste arbitrary input and apply a numeric XOR value

If the result looks like valid Protobuf, you can push those bytes back into the main decoder and keep going.

Privacy

ProtoDecodeX is local-first:

  • Decoding happens in the browser
  • The app does not require a backend decode API
  • Local files are read by the browser and turned into bytes locally

So you do not have to paste everything again every time, the app stores some state in localStorage, including:

  • Input text
  • Detected input format
  • The parseDelimited toggle
  • Pasted schema text
  • Selected message name
  • Whether a decode result existed

If you work with sensitive payloads on a shared machine, clear the app state or use a private browser profile.

Limits

ProtoDecodeX is a tool for debugging and inspection, not a full protoc replacement.

  • It focuses on wire-format decoding, not full schema compilation or validation
  • Schema parsing is intentionally lightweight and supports a subset of .proto syntax
  • Packed repeated detection is heuristic
  • Some malformed payloads may decode partially and leave leftOver bytes
  • There is no built-in export-to-file or share-by-URL workflow today
  • There is no backend storage or collaborative session model

Available scripts

Command Description
npm start Start the Vite development server on port 3000
npm run build Create a production build in build/
npm test Run the test suite with Vitest
npm run test:watch Run tests in watch/UI mode

The repository also includes convenience scripts:

  • scripts/local-build.sh
  • scripts/docker-build.sh

Docker and deployment

The repository already includes a multi-stage Dockerfile, docker-compose.yml, and nginx.conf, so containerized development and deployment are straightforward.

Development container

docker compose --profile dev up --build protobuf-decoder-dev

Production container

docker compose --profile prod up --build protobuf-decoder-prod

Tech stack

  • React 18
  • Vite 5
  • Semantic UI React
  • buffer for byte handling
  • jsbi for large integer support
  • Vitest + Testing Library + jsdom

Contributing

Issues and pull requests are welcome. The most useful contributions here are usually pretty concrete:

  • Decoder correctness improvements
  • Better schema parsing coverage
  • More type-aware rendering
  • UX polish for large payloads
  • Better documentation and examples

Before opening a PR, it is a good idea to run:

npm test
npm run build

License

MIT

About

ProtoDecodeX is a Protobuf wire-format decoder that runs in the browser.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • JavaScript 93.8%
  • Shell 4.9%
  • Other 1.3%