This page follows the format description in the
README of
Hugging Face’s safetensors repository and the data types in its
safetensors/src/tensor.rs, both read 2026-11-12.
Layout
| Offset | Size | Field |
|---|---|---|
0 | 8 | N: size of the header, unsigned 64-bit little-endian. |
8 | N | The header: a UTF-8 JSON object that must start with {. It may be padded at the end with spaces (20). |
| 8 + N | rest | The byte buffer holding every tensor. |
Header
Each key is a tensor name; its value is an object:
| Key | Value |
|---|---|
dtype | A data type string. |
shape | Array of dimension sizes; [] is a single value, and a 0 in the shape is an empty tensor, which takes no bytes in the buffer. |
data_offsets | [begin, end]: byte positions within the byte buffer, end exclusive. |
The special key __metadata__ may hold a free-form object whose keys
and values are all strings; other JSON values are not allowed there. An example
(the metadata content is made up):
{"__metadata__":{"note":"example"},
"weight":{"dtype":"F16","shape":[2,3],"data_offsets":[0,12]}}
Data types
| dtype | Type | Bytes |
|---|---|---|
BOOL | Boolean | 1 |
U8, I8 | 8-bit integers | 1 |
F4 | 4-bit float | ½ |
F6_E2M3, F6_E3M2 | 6-bit floats | ¾ |
F8_E5M2, F8_E4M3, F8_E8M0, F8_E4M3FNUZ, F8_E5M2FNUZ | 8-bit floats | 1 |
U16, I16 | 16-bit integers | 2 |
F16 | IEEE half precision | 2 |
BF16 | bfloat16 | 2 |
U32, I32 | 32-bit integers | 4 |
F32 | IEEE single precision | 4 |
U64, I64 | 64-bit integers | 8 |
F64 | IEEE double precision | 8 |
C64 | 64-bit complex | 8 |
The library counts sizes in bits, so the sub-byte types pack several values per byte; the README notes they make alignment tricky. Values are little-endian, in row-major (C) order. NaN and infinities are not checked for.
Validity rules
- The library limits the header to 100 MB, so a huge JSON cannot be used for a denial-of-service attack.
- No duplicate keys (the README notes not all parsers check this).
- The byte buffer must be entirely indexed, with no holes (which prevents polyglot files), and the tensors’ ranges must not overlap.
- The library rejects a tensor whose range length differs from its element count times the dtype’s size.
The README describes the format as a way to store tensors safely, as opposed to pickle.