TXT · Text & Data tools

Binary Format Decoder

Format
Input encoding
Indent
Or load a file
Encoded bytes
Decoded
autoformat0 Binput0lines out0chars out

Shareable link

Settings are written to the URL as you change them. Nothing differs from the defaults yet.

Decode a payload

Paste the bytes as hex or Base64 and the decoded structure appears as JSON. Detect automatically runs all eight decoders and keeps the one that reaches the end of the buffer. Most payloads are unambiguous: BSON starts with its own length, bencode starts with an ASCII letter, a plist starts with bplist00, DER starts with a tag byte, and the rest are separated by their type bytes.

Short payloads are the exception. 1a03089601 is a nested protobuf message and also a valid CBOR integer, and both readings consume all 5 bytes. When decoders tie, a map or an array wins over a bare number. Choose the format explicitly when the guess is wrong.

Loading a file skips the encoding step entirely. A .torrent, a captured request body, a .plist from an app bundle, a .der certificate, or a MongoDB export can be dropped in as it is. A PEM block pasted with its -----BEGIN----- lines is unwrapped before decoding, so a certificate or private key can go straight from a terminal into the input pane.

The bytes behind the line

Every decoded value keeps the byte range it was read from. Click a line in the decoded pane and those bytes light up in the hex dump, labelled with the format’s own type name: fixstr, int32, SEQUENCE, UTF-16 string. Click a byte in the dump and the line that owns it is selected instead.

This is the fastest way to answer the question a hex editor cannot: which four bytes are the length prefix, and which one is the type tag. It also makes a partial decode legible, since the last highlighted range sits directly before the byte that failed.

Streams of documents

A mongodump output file is not one BSON document, it is thousands of them end to end. MessagePack and CBOR logs are the same shape. Consecutive top-level values are decoded until the buffer runs out and returned as an array, with the count shown as documents below the panes. Reading stops after 2000.

The counters still report how many bytes were left over. A non-zero count now means the remaining bytes could not be parsed at all, which usually points at a truncated file or a length field that disagrees with reality. A decode that stops early names the byte offset it could not read past, and that offset is the fastest place to start comparing against the dump.

What JSON cannot hold

Every one of these formats carries types JSON does not have, so they are rendered rather than dropped.

Byte strings become <bytes 0a1b2c3d> with the length noted past 64 bytes. Integers outside the safe range for a JavaScript number become strings, because parsing 9007199254740993 as a number loses the last digit. MessagePack extension types keep their type number, CBOR tags keep the tag, BSON ObjectIds keep their 12-byte hex, and plist UIDs keep their reference number.

Turning off Annotate types drops the labels and leaves the plain value, which is closer to what an application would see after decoding.

Protobuf without a schema

The wire format stores field numbers, not names. Each key here is written as 3:bytes, meaning field 3 with a length-delimited value.

Length-delimited fields are ambiguous by design: the same bytes can be a nested message, a UTF-8 string, or raw bytes. The decoder tries them in that order, so a short string of printable characters occasionally shows up as a nested message with plausible field numbers. Check the schema when the interpretation matters.

ASN.1 structure, not just bytes

DER is tag, length, value, nested as deep as the document needs. Constructed values keep their name in the output, so a certificate reads as SEQUENCE, SET, and [0] rather than as anonymous arrays. Object identifiers are resolved where the name is well known: 1.2.840.113549.1.1.11 prints as sha256WithRSAEncryption, 2.5.4.3 as commonName.

A BIT STRING or OCTET STRING whose contents parse as DER is expanded in place, which is what makes a PKCS#8 private key readable down to its RSA modulus. Integers wider than 8 bytes print as hex with their bit length, since a 2048-bit modulus is not a number anyone reads in decimal.

Write JSON back out

Encode takes the other direction. Paste JSON, pick MessagePack, CBOR, BSON, or bencode, and the bytes come back as hex or Base64 with a download button for the raw file.

The size comparison under the output is the reason to use it: the same payload measured in every writable format next to its JSON length, with the smallest marked. A 300-byte JSON object with short keys and small integers typically lands near 200 bytes in MessagePack and CBOR, and larger in BSON, which stores a length prefix and a null terminator for every element.

Bencode refuses what it cannot store. There is no type for null, for true, or for a fractional number, so the encoder names the path that failed instead of writing something the reader would misparse. BSON needs an object or an array at the top level, because a BSON file is a document.

Where these formats are used

MessagePack and CBOR are compact self-describing formats, used in caches, IoT payloads, and WebAuthn attestation objects. BSON is what MongoDB stores and what its wire protocol carries. Bencode holds the metadata inside every .torrent file. Binary plists hold preferences, Info.plist files, and NSKeyedArchiver output across macOS and iOS. DER carries certificates, keys, CSRs, and OCSP responses. RLP encodes every Ethereum transaction and receipt. Protobuf is the schema-driven one, which is why its output looks different from the rest.

Frequently Asked Questions

MessagePack, CBOR, BSON, the protobuf wire format, bencode, Apple binary property lists, ASN.1/DER, and Ethereum RLP. Detect automatically runs all eight and keeps the reading that consumes the whole buffer, preferring a map or an array when more than one decoder succeeds.

Click any line in the decoded pane and its byte range lights up in the hex dump below, with the format's own type name for that value. Clicking a byte in the dump works the other way and selects the line that owns it.

Switch to Encode and paste JSON to write MessagePack, CBOR, BSON, or bencode. The size comparison shows the same payload in every writable format next to its JSON length. Protobuf, DER, RLP, and plists are decode only, because writing them from bare JSON would mean guessing at a schema.

Hex or Base64 pasted into the input pane, or a file loaded with the file picker, up to 16 MB. Hex may contain spaces, commas, and 0x prefixes, and a pasted PEM block has its armour stripped before decoding.

It reads the wire format, so you get field numbers, wire types, and values. Field names and enum labels live in the schema and cannot be recovered from the bytes.

JSON has no type for either. Byte strings render as hex inside angle brackets, and integers outside the safe range render as strings so no digits are lost.

Reading the same format every day?

Pages locked to one format

Explore Our Tools

Browse all tools