gRPC Frame Parser
Paste a captured gRPC message stream as base64 or hex and see each length-prefixed frame split out — compressed flag, length, and the embedded protobuf decoded field by field. No .proto schema required. Runs entirely in your browser, no server, no sign-up.
What this tool does
gRPC doesn't send a protobuf message as bare bytes. On the wire it wraps every message in a tiny length-prefixed frame: a 1-byte compressed flag, a 4-byte big-endian length, then exactly that many payload bytes. A single HTTP/2 DATA body — or a streaming RPC — can carry several of these frames back to back.
Paste a captured stream (as base64 or hex) and this tool walks it frame by
frame: it shows each frame's compressed flag and declared length, then decodes the
embedded protobuf payload into a field-number / wire-type tree — no .proto
schema required. Everything runs locally in your browser; nothing is uploaded.
The gRPC frame layout
Each Length-Prefixed-Message is:
+--------------------+----------------------------+----------------------+
| Compressed-Flag | Message-Length | Message |
| 1 byte (0 or 1) | 4 bytes, big-endian uint32 | <Message-Length> |
+--------------------+----------------------------+----------------------+
- Compressed-Flag —
0means the payload is raw protobuf;1means it was compressed with the codec named in thegrpc-encodingheader (commonly gzip). - Message-Length — the byte length of the payload that follows.
- Message — the protobuf bytes (when uncompressed).
Frames repeat until the bytes run out. This parser validates the framing, splits the frames, and decodes each uncompressed payload.
How the payload is decoded
The protobuf wire format is self-describing only at the level of field numbers
and wire types — without the original .proto you can't know whether a varint
was an int32, an enum, or a bool. So for every field the decoder reports the
field number, the raw wire type, and every plausible interpretation:
- varint →
uint,int, zig-zagsint, andboolwhen the value is 0 or 1 - fixed32 →
uint32,int32,float - fixed64 →
uint64,int64,double - length-delimited → recursively parsed as a nested message when it parses
cleanly, plus shown as a UTF-8
stringand as rawhexbytes
Choose JSON for a structured tree you can drill into, or text for a compact indented outline.
Example
The hex stream 00 00 00 00 03 08 96 01 is one frame: flag 0, length 3,
payload 08 96 01 — which decodes to the protobuf message { field 1: 150 }.
Concatenate another frame after it and both are split out and decoded
independently.
Good for
- Reverse-engineering an undocumented gRPC API from a captured request/response
- Debugging a gRPC call from a Wireshark / Charles / browser-devtools byte dump
- Confirming the framing and message boundaries of a streaming RPC
- Inspecting a protobuf payload when you only have the bytes, not the schema
Notes & limits
- Compressed frames (flag = 1) are reported but not decompressed — decode
the payload after decompressing it with the codec from the
grpc-encodingheader (try the matching decompress tool, then the protobuf decoder). - If a frame's payload isn't valid protobuf, the tool still surfaces the frame (flag, length, hex) and notes the decode error — the framing parsed, the payload just isn't protobuf.
- The bytes must start at a frame boundary. If you paste a bare protobuf message (no 5-byte prefix), use the dedicated protobuf decoder instead.
Is this the same as a protobuf decoder?
No — a protobuf decoder expects a single bare message. gRPC adds the length-prefixed framing layer (compressed flag + 4-byte length) on top, and a stream can hold many messages. This tool peels off that framing first, then hands each uncompressed payload to the protobuf decoder.
Why are there multiple interpretations per field?
Without the original .proto schema the wire bytes are ambiguous: a
varint could be an integer, a signed zig-zag value, an enum, or a bool. The
decoder shows every reading so you can pick the one that matches your API.
Does anything get uploaded?
No. The parser is compiled to WebAssembly and runs entirely in your browser — the bytes you paste never leave your device.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool parse-grpc-frame "00 00 00 00 03 08 96 01"New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
https://gizza.ai/tools/parse-grpc-frame/?input=00%2000%2000%2000%2003%2008%2096%2001&encoding=auto&format=jsonMachine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
