A pickle is a program for a small stack machine: each opcode is one byte, followed
by its argument. The machine has two data areas, a stack and a memo (numbered saved
objects); MARK pushes a special mark object onto the stack, which later
opcodes look back to. This page follows CPython’s
Lib/pickletools.py,
which documents every opcode, and
Lib/pickle.py,
both read 2026-11-12 from the main branch. Loading a pickle can call any callable
named by GLOBAL/STACK_GLOBAL and applied by
REDUCE; the
pickle module documentation,
read 2026-11-12, warns that it is not secure and that data that could have come from an
untrusted source must never be unpickled.
Arguments
Text arguments end with a line feed. Binary numbers are little-endian, except
BINFLOAT, which is a big-endian double. “Length + bytes” means the length
in the stated size, then that many bytes. A pickle does not record its protocol
number except through PROTO, which protocol 2 and later must start
with.
Opcodes
| Byte | Name | Proto | Argument and effect |
|---|---|---|---|
28 ( | MARK | 0 | Push the mark. |
2E . | STOP | 0 | End; the top of the stack is the result. |
30 0 | POP | 0 | Discard the top item. |
31 1 | POP_MARK | 1 | Discard everything down to the mark. |
32 2 | DUP | 0 | Duplicate the top item. |
46 F | FLOAT | 0 | Text float. |
49 I | INT | 0 | Text integer; 01 and 00 mean True and False. |
4A J | BININT | 1 | 4-byte signed integer. |
4B K | BININT1 | 1 | 1-byte unsigned integer. |
4C L | LONG | 0 | Text integer ending in L. |
4D M | BININT2 | 1 | 2-byte unsigned integer. |
4E N | NONE | 0 | Push None. |
50 P | PERSID | 0 | Text persistent ID, resolved by the unpickler. |
51 Q | BINPERSID | 1 | Persistent ID from the stack. |
52 R | REDUCE | 0 | Call the callable below the top with the argument tuple on top. |
53 S | STRING | 0 | Repr-style string with quotes and escapes; decoded with the unpickler’s encoding (default ASCII), or kept as bytes if that is 'bytes'. |
54 T | BINSTRING | 1 | 4-byte signed length + bytes, decoded as for STRING. |
55 U | SHORT_BINSTRING | 1 | 1-byte length + bytes, decoded as for STRING. |
56 V | UNICODE | 0 | Text in raw-unicode-escape form. |
58 X | BINUNICODE | 1 | 4-byte length + UTF-8. |
42 B | BINBYTES | 3 | 4-byte length + bytes. |
43 C | SHORT_BINBYTES | 3 | 1-byte length + bytes. |
47 G | BINFLOAT | 1 | 8-byte big-endian double. |
29 ) | EMPTY_TUPLE | 1 | Push (). |
5D ] | EMPTY_LIST | 1 | Push []. |
7D } | EMPTY_DICT | 1 | Push {}. |
61 a | APPEND | 0 | Append the top item to the list below it. |
65 e | APPENDS | 1 | Append all items above the mark. |
62 b | BUILD | 0 | Set an object’s state (__setstate__ or its __dict__). |
63 c | GLOBAL | 0 | Text module\nname\n: push that object. |
64 d | DICT | 0 | Build a dict from key, value pairs above the mark. |
67 g | GET | 0 | Text memo index: push that memo item. |
68 h | BINGET | 1 | 1-byte memo index. |
6A j | LONG_BINGET | 1 | 4-byte memo index. |
69 i | INST | 0 | Text module\nname\n: create an instance from the items above the mark. |
6F o | OBJ | 1 | The same, with the class on the stack. |
6C l | LIST | 0 | Build a list from the items above the mark. |
70 p | PUT | 0 | Text memo index: store the top item. |
71 q | BINPUT | 1 | 1-byte memo index. |
72 r | LONG_BINPUT | 1 | 4-byte memo index. |
73 s | SETITEM | 0 | Set dict[key] = value from the top two items. |
75 u | SETITEMS | 1 | Set all pairs above the mark. |
74 t | TUPLE | 0 | Build a tuple from the items above the mark. |
80 | PROTO | 2 | 1 byte: the protocol number; first opcode from protocol 2. |
81 | NEWOBJ | 2 | cls.__new__(cls, *args). |
82, 83, 84 | EXT1, EXT2, EXT4 | 2 | 1-byte unsigned, 2-byte unsigned or 4-byte signed extension code; pushes that entry of the extension registry. |
85, 86, 87 | TUPLE1, TUPLE2, TUPLE3 | 2 | Build a tuple from the top 1, 2 or 3 items. |
88, 89 | NEWTRUE, NEWFALSE | 2 | Push True, False. |
8A | LONG1 | 2 | 1-byte length + little-endian two’s complement integer. |
8B | LONG4 | 2 | 4-byte signed length (must not be negative) + little-endian two’s complement integer. |
8C | SHORT_BINUNICODE | 4 | 1-byte length + UTF-8. |
8D | BINUNICODE8 | 4 | 8-byte length + UTF-8. |
8E | BINBYTES8 | 4 | 8-byte length + bytes. |
8F | EMPTY_SET | 4 | Push an empty set. |
90 | ADDITEMS | 4 | Add the items above the mark to the set. |
91 | FROZENSET | 4 | Build a frozenset from the items above the mark. |
92 | NEWOBJ_EX | 4 | cls.__new__(cls, *args, **kwargs). |
93 | STACK_GLOBAL | 4 | Push the object named by the module and name strings on the stack. |
94 | MEMOIZE | 4 | Store the top item at the next memo index. |
95 | FRAME | 4 | 8-byte unsigned length of the frame that follows; the unpickler may use it to prefetch data. pickle.py writes no FRAME for a frame under 4 bytes. |
96 | BYTEARRAY8 | 5 | 8-byte length + bytes, as a bytearray. |
97 | NEXT_BUFFER | 5 | Push the next out-of-band buffer given to the unpickler. |
98 | READONLY_BUFFER | 5 | Make the buffer on top read-only. |
Example
pickle.dumps([1, "a"], protocol=4):
80 04 PROTO 4
95 0B 00 00 00 00 00 00 00 FRAME 11
5D EMPTY_LIST
94 MEMOIZE
28 MARK
4B 01 BININT1 1
8C 01 61 SHORT_BINUNICODE "a"
94 MEMOIZE
65 APPENDS
2E STOP