Monday, 24 August 2026 | Updating Daily AI insight, written for builders

Safetensors: Fast and Safe Model Weight Storage Format

TL;DR:

  • Safetensors is a file format for storing machine learning model weights that prevents arbitrary code execution vulnerabilities present in pickle-based formats
  • It loads 2-10× faster than PyTorch .bin files with zero-copy memory mapping and supports lazy loading for multi-GB models
  • Install with pip install safetensors and use safe_open() to load or save_file() to save tensors
  • Widely supported by Hugging Face, Ollama, LM Studio, ComfyUI, and all major ML frameworks

Safetensors is a binary file format for storing and loading machine learning model weights developed by Hugging Face. It addresses critical security vulnerabilities in pickle-based formats (PyTorch .bin, .pt files) by using a simple, statically parseable structure that cannot execute arbitrary code during deserialization. The format achieves significantly faster load times through memory mapping and zero-copy operations, making it the preferred format for distributing and loading AI models in 2026.

What Is Safetensors

Safetensors stores tensors (multi-dimensional arrays of numbers that represent neural network weights) in a plain binary format with a JSON header. Unlike pickle-based formats used historically in PyTorch, safetensors contains only raw tensor data and metadata—no Python code, no class definitions, no executable instructions.

The file structure consists of:

  • An 8-byte header containing the metadata length
  • A JSON metadata section describing tensor names, shapes, data types, and byte offsets
  • Raw tensor data stored contiguously in memory-aligned blocks

This simplicity enables memory-mapped loading: the operating system maps the file directly into process memory, allowing instant access to tensor data without copying gigabytes into RAM. When you open a 7B parameter model stored as safetensors, the load time is measured in milliseconds rather than seconds.

Why Safetensors Was Created

The Python pickle format, used by default in PyTorch’s torch.save() and torch.load(), can execute arbitrary Python code during deserialization. A malicious actor can craft a .bin or .pt file that runs malware when you call torch.load(). This is not a theoretical vulnerability—multiple incidents have demonstrated weaponized model files in the wild.

Beyond security, pickle-based formats suffer from performance issues:

IssuePickle-based (.bin, .pt)Safetensors
Arbitrary code executionYes, inherent to pickleNo, static format
Load time for 7B model5-15 seconds0.5-2 seconds
Memory overhead during load2× model size (copy required)~1× (memory mapping)
Framework portabilityPython/PyTorch specificAny language with bindings
Lazy loading supportNoYes

When loading a pickle file, Python must deserialize the entire structure into memory, reconstruct Python objects, then copy tensor data into the framework’s native format. Safetensors eliminates these steps by directly mapping the binary tensor data.

Installing and Using Safetensors

Install the Python library:

pip install safetensors

Loading Safetensors Files

Use safe_open() for memory-mapped lazy loading:

from safetensors import safe_open

with safe_open("model.safetensors", framework="pt", device="cpu") as f:
    # Get list of tensor names
    tensor_names = f.keys()
    
    # Load specific tensor (lazy - only loads this tensor)
    embedding_weights = f.get_tensor("model.embed_tokens.weight")
    
    # Get tensor metadata without loading
    metadata = f.metadata()

The framework parameter specifies the target framework: "pt" for PyTorch, "tf" for TensorFlow, "np" for NumPy, or "jax" for JAX. The device parameter controls where tensors are placed: "cpu", "cuda:0", or other device identifiers.

To load all tensors at once:

from safetensors.torch import load_file

tensors = load_file("model.safetensors")
# Returns dict: {"layer.weight": tensor, "layer.bias": tensor, ...}

Saving Safetensors Files

Save a dictionary of tensors:

from safetensors.torch import save_file
import torch

tensors = {
    "embedding.weight": torch.randn(50000, 768),
    "layer1.weight": torch.randn(768, 768),
    "layer1.bias": torch.randn(768)
}

save_file(tensors, "model.safetensors")

Include custom metadata:

save_file(
    tensors,
    "model.safetensors",
    metadata={"model_type": "bert", "vocab_size": "50000"}
)

Loading Models from Hugging Face

Hugging Face’s transformers library uses safetensors automatically when available:

from transformers import AutoModel

# Automatically downloads and loads .safetensors if available
model = AutoModel.from_pretrained("bert-base-uncased")

Force safetensors format:

model = AutoModel.from_pretrained(
    "bert-base-uncased",
    use_safetensors=True  # Fail if safetensors not available
)

Most models on Hugging Face Hub now include both model.safetensors and pytorch_model.bin files. The library prefers safetensors when both exist.

Converting Between Formats

PyTorch .bin to Safetensors

from safetensors.torch import save_file
import torch

# Load PyTorch checkpoint
state_dict = torch.load("pytorch_model.bin", map_location="cpu")

# Save as safetensors
save_file(state_dict, "model.safetensors")

Safetensors to PyTorch .bin

from safetensors.torch import load_file
import torch

tensors = load_file("model.safetensors")
torch.save(tensors, "pytorch_model.bin")

Hugging Face Conversion Script

The transformers library includes a conversion tool:

python -m transformers.convert_safetensors_to_pytorch 
    --model_name_or_path ./model_folder 
    --output_dir ./converted

File Format Technical Details

A safetensors file has this structure:

  1. Header (8 bytes): Little-endian unsigned 64-bit integer containing the JSON metadata length in bytes
  2. Metadata (variable): JSON object with this schema:
    {
      "layer_name": {
        "dtype": "F32",  // Data type: F32, F16, BF16, I64, I32, etc.
        "shape": [768, 768],  // Tensor dimensions
        "data_offsets": [0, 2359296]  // Start and end byte in data section
      },
      "__metadata__": {  // Optional custom metadata
        "key": "value"
      }
    }
  3. Data section: Raw tensor bytes, stored in C-contiguous order (row-major), aligned to 8-byte boundaries

The format supports these data types: F64, F32, F16, BF16, I64, U64, I32, U32, I16, U16, I8, U8, BOOL. Each tensor’s byte range is specified in the metadata, enabling selective loading without parsing the entire file.

Ecosystem Support

Safetensors is supported across the AI ecosystem:

Tool/FrameworkSupport LevelNotes
Hugging Face TransformersNativeDefault format since v4.30
Hugging Face DiffusersNativeUsed for Stable Diffusion models
PyTorchVia libraryRequires safetensors package
TensorFlowVia librarySupported through bindings
JAXVia librarySupported through bindings
OllamaNativeConverts to GGUF internally
LM StudioNativeLoads safetensors directly
ComfyUINativePrimary format for custom models
AUTOMATIC1111NativeStable Diffusion WebUI support
llama.cppVia conversionConvert to GGUF format
vLLMNativeInference server support
TGINativeText Generation Inference support

When evaluating whether a model will fit in your GPU memory, use the VRAM calculator to estimate requirements based on parameter count and quantization level. The file format itself does not affect VRAM usage—safetensors and pickle files of the same model consume identical GPU memory once loaded.

Performance Characteristics

Benchmarks on a system with NVMe SSD and 64GB RAM loading a 7B parameter model:

FormatLoad TimePeak RAM UsageFile Size
PyTorch .bin8.2s28GB13.5GB
Safetensors (load_file)1.1s14GB13.5GB
Safetensors (safe_open lazy)0.08s0.5GB13.5GB

The lazy loading approach with safe_open() is particularly valuable when you need to inspect model architecture, extract specific layers, or load models that exceed available RAM by loading tensors selectively.

For quantized models, safetensors supports all standard data types including FP16, BF16, INT8, and INT4. The AI models database includes safetensors file sizes and VRAM requirements for 37 popular models across different quantization levels.

Sharded Models

Models larger than a few gigabytes are often distributed as multiple safetensors files (sharding). A 70B parameter model might be split into 8 shards:

model-00001-of-00008.safetensors
model-00002-of-00008.safetensors
...
model-00008-of-00008.safetensors
model.safetensors.index.json

The index file maps tensor names to shard files:

{
  "metadata": {"total_size": 141123453952},
  "weight_map": {
    "model.embed_tokens.weight": "model-00001-of-00008.safetensors",
    "model.layers.0.self_attn.q_proj.weight": "model-00001-of-00008.safetensors",
    "model.layers.40.mlp.gate_proj.weight": "model-00005-of-00008.safetensors"
  }
}

Hugging Face libraries handle sharded loading automatically. Manual loading:

import json
from safetensors import safe_open

with open("model.safetensors.index.json") as f:
    index = json.load(f)

weight_map = index["weight_map"]

# Load specific tensor by looking up its shard
tensor_name = "model.layers.20.mlp.down_proj.weight"
shard_file = weight_map[tensor_name]

with safe_open(shard_file, framework="pt", device="cpu") as f:
    tensor = f.get_tensor(tensor_name)

Language Bindings

While the reference implementation is Python, safetensors has bindings for multiple languages:

  • Rust: Core implementation in Rust for performance and safety
  • Python: Official bindings via PyPI
  • JavaScript/Node.js: @huggingface/safetensors npm package
  • C/C++: Available through FFI to Rust library
  • Go: Community implementations available

The Rust implementation is the canonical reference. The Python bindings wrap this implementation, inheriting its performance characteristics.

Frequently Asked Questions

Can I use safetensors with existing PyTorch models without code changes?

Yes, if you’re using Hugging Face libraries. For custom models, you need to change torch.load() to load_file() from safetensors and torch.save() to save_file(). The tensor data and model architecture remain identical—only the serialization format changes. Converting existing checkpoints is a one-time operation that takes seconds.

Do safetensors files work across different PyTorch versions?

Yes. Unlike pickle files, which can break across Python or PyTorch version changes, safetensors stores raw binary data without version-specific serialization. A safetensors file created with PyTorch 1.12 loads correctly in PyTorch 2.x, and vice versa. This makes safetensors superior for long-term model archival and distribution.

Why are some models on Hugging Face Hub still distributed as .bin files?

Older models uploaded before 2023 may only have pickle-based files. Hugging Face is gradually converting the model hub, but some models remain pickle-only if the original uploader has not provided safetensors versions. When both formats exist, safetensors is preferred automatically. You can convert locally using the method shown in the conversion section above.

Does safetensors increase file size compared to PyTorch .bin?

No. File sizes are typically identical or within 1-2% because both formats store the same raw tensor data. Safetensors adds minimal overhead (a JSON header of a few kilobytes), while pickle adds Python object serialization overhead. For a 7B model, both formats produce ~13-14GB files. The difference is load speed and security, not storage efficiency.

Can I inspect safetensors files without loading the full model into memory?

Yes, this is one of safetensors’ key advantages. Use safe_open() to read the metadata and selectively load specific tensors. You can list all tensor names, check their shapes and data types, and extract individual layers without loading the entire multi-gigabyte file. This is particularly useful for model analysis, debugging, and extracting components.

Are GGUF and safetensors the same thing?

No. GGUF (GPT-Generated Unified Format) is a different format used primarily by llama.cpp for quantized inference. GGUF includes quantization schemes optimized for CPU inference that safetensors does not support. Safetensors is designed for training and general-purpose model distribution, while GGUF is optimized for efficient inference on consumer hardware. Many tools like Ollama accept safetensors as input and convert to GGUF internally for inference.

Written by Mustafa Ihsan

Mustafa Ihsan is the founder and editor of Convly.ai. He built and maintains the site's live AI models database, its price-performance index, and its free calculators for VRAM requirements, API costs and self-hosting economics. He writes about model pricing, benchmark results and the hardware needed to run AI models locally, and consistently prefers measured numbers to vendor claims.

Scroll to Top
Featured on There's An AI For That