Skip to content

Binary Format Specification

pysafe-pickle uses a compact, hand-written binary format designed for high-speed serialization without invoking arbitrary execution hooks.


Header Layout

text
[4 bytes]  Magic: b"PSPK" (new) or b"PYGR" (v1.0.x legacy)
[2 bytes]  Format Version: 1 (u16 LE)
[4 bytes]  Flags: 0 (u32 LE) - bit 0: HMAC enabled
[4 bytes]  String Table Count (u32 LE)
  For each string:
    [4 bytes]  Length (u32 LE)
    [N bytes]  UTF-8 bytes
[4 bytes]  Type Table Count (u32 LE)
  For each type:
    [2 bytes]  Type ID (u16 LE)
    [4 bytes]  Name string index (u32 LE)
    [4 bytes]  Schema version (u32 LE)
    [2 bytes]  Field count (u16 LE)
      For each field:
        [4 bytes]  Field name string index (u32 LE)
[4 bytes]  Record Count (u32 LE)
  For each record:
    [1 byte]   Tag byte
    [variable] Payload

14 Tag Definitions

TagBytePayload Structure
None0x01No payload
True0x02No payload
False0x03No payload
Int0x04Zigzag-encoded variable-length 64-bit integer (u64 varint)
Float0x058-byte IEEE 754 little-endian f64
String0x06String table index (u32 LE)
Bytes0x07Length (u32 LE) + raw bytes
List0x08Count (u32 LE) + child record IDs (u32 LE each)
Tuple0x09Count (u32 LE) + child record IDs (u32 LE each)
Dict0x0ACount (u32 LE) + key/value record ID pairs (u32 LE each)
Set0x0BCount (u32 LE) + child record IDs (u32 LE each)
FrozenSet0x0CCount (u32 LE) + child record IDs (u32 LE each)
Dataclass0x0DType ID (u16 LE) + field count (u16 LE) + field record IDs (u32 LE each)
Reference0x0ERecord ID (u32 LE) — handles cycles and shared object pointers

String Interning

All dictionary keys, field names, and string values are interned into a deduplicated string table at the front of the binary payload. This dramatically reduces payload sizes for tabular datasets and dataclasses with repeating field keys.

Released under the AGPL-3.0 License.