Containers · .safetensors
safetensors
Hugging Face's safe, mmap-friendly tensor container. An 8-byte little-endian header length N, an N-byte UTF-8 JSON header mapping tensor names to {dtype, shape, data_offsets}, plus an optional "__metadata__" string->string map, then one contiguous byte buffer. Tensors are dense, little-endian, C-order, with no strides. Loading cannot execute code. It is the default format for HF Transformers / Diffusers checkpoints; large models are sharded with a JSON index file.
.safetensors
- What it is
- many tensors
- Byte order
- little
- Dimension order
- row major
- Compression
- none
- Metadata
- string map
- Loading
- Loading it into a library does not execute code.
How to read it
[N: u64 LE][header: N bytes UTF-8 JSON, space padded][byte buffer]. File size = 8 + N + buffer length.
- N
- u64le. header length in bytes
- header
- utf8[N]. JSON Header object, optionally followed by 0x20 padding
- buffer
- bytes[*]. tensor bytes back to back, in data_offsets order, without gaps
0 8 8+N EOF
+--------+--------------------+--------------------------------------+
| N u64 | {"__metadata__":..,| t0 bytes | t1 bytes | ... | tk bytes |
| LE | "t0":{...},...} | |
| | + ' ' padding | offsets are relative to byte 8+N |
+--------+--------------------+--------------------------------------+One tensor
- name
- header key
- dtype
- TensorInfo.dtype -> dtypes[].canonical
- shape
- TensorInfo.shape (already row-major, outermost first)
- data_offset
- 8 + N + data_offsets[0] (absolute in file)
- nbytes
- data_offsets[1] - data_offsets[0]
- order
- always C
- strides
- implicit C-contiguous
Example
The specs test vector. The header is one JSON object. The header below is spaced for reading; the file pads that JSON with spaces out to a multiple of 8.
small.safetensors1,464 bytes
| Name | Dtype | Shape | Bytes |
|---|---|---|---|
| s_f32 | F32float32 | [] | 4 |
| w_f32 | F32float32 | 4 × 64 | 1,024 |
| i_i32 | I32int32 | 3 × 2 | 24 |
| e_bf16 | BF16bfloat16 | 2 × 3 | 12 |
| b_f16 | F16float16 | 8 | 16 |
Header
{
"__metadata__": {
"source": "tensor-format-specs test vector"
},
"s_f32": {
"dtype": "F32",
"shape": [],
"data_offsets": [
0,
4
]
},
"w_f32": {
"dtype": "F32",
"shape": [
4,
64
],
"data_offsets": [
4,
1028
]
},
"i_i32": {
"dtype": "I32",
"shape": [
3,
2
],
"data_offsets": [
1028,
1052
]
},
"e_bf16": {
"dtype": "BF16",
"shape": [
2,
3
],
"data_offsets": [
1052,
1064
]
},
"b_f16": {
"dtype": "F16",
"shape": [
8
],
"data_offsets": [
1064,
1080
]
}
}Number formats
The name in the file, and the canonical dtype it maps to.
| In the file | Canonical | Bits |
|---|---|---|
| BOOL | bool | 8 |
| F4 | float4_e2m1fn | 4 |
| F6_E2M3 | float6_e2m3fn | 6 |
| F6_E3M2 | float6_e3m2fn | 6 |
| U8 | uint8 | 8 |
| I8 | int8 | 8 |
| F8_E5M2 | float8_e5m2 | 8 |
| F8_E4M3 | float8_e4m3fn | 8 |
| F8_E8M0 | float8_e8m0fnu | 8 |
| F8_E4M3FNUZ | float8_e4m3fnuz | 8 |
| F8_E5M2FNUZ | float8_e5m2fnuz | 8 |
| I16 | int16 | 16 |
| U16 | uint16 | 16 |
| F16 | float16 | 16 |
| BF16 | bfloat16 | 16 |
| I32 | int32 | 32 |
| U32 | uint32 | 32 |
| F32 | float32 | 32 |
| C64 | complex64 | 64 |
| F64 | float64 | 64 |
| I64 | int64 | 64 |
| U64 | uint64 | 64 |
Sources
- huggingface/safetensors README.md, section "Format" (normative prose)
- safetensors/src/tensor.rs (reference Rust implementation; serialize/deserialize/validate, Dtype enum)
- bindings/python/py_src/safetensors/torch.py (torch dtype mapping, shared-tensor handling)
- transformers modeling_utils / huggingface_hub split_torch_state_dict_into_shards (model.safetensors.index.json)