What Is a .NPY File?

Numpy Array

📂Data
🏷️.npy
🎯application/octet-stream

NumPy Array File (.npy)

Overview

The .npy format is NumPy's native binary format for storing a single array on disk. It preserves everything the in-memory array knows about itself - the exact dtype, the shape, and the memory ordering - so a saved array reloads as an exact bitwise copy, with no parsing, no type inference, and no precision loss.

That is the key difference from CSV: writing a float64 array to CSV converts every value to text and back, which is slow and can lose the last bits of precision. An .npy file is essentially the raw memory buffer with a small self-describing header in front of it.

Technical Specifications

Format Details

  • MIME Type: application/octet-stream
  • File Extension: .npy
  • Category: Data
  • Specification: NEP 1 (NumPy Enhancement Proposal 1)
  • Magic bytes: 93 4E 55 4D 50 59 (\x93NUMPY)
  • Format versions: 1.0, 2.0 (longer headers), 3.0 (UTF-8 field names)
  • Contains: exactly one array

Magic Number

00000000  93 4e 55 4d 50 59 01 00  76 00 7b 27 64 65 73 63  |.NUMPY..v.{'desc|
00000010  72 27 3a 20 27 3c 66 38  27 2c 20 27 66 6f 72 74  |r': '<f8', 'fort|
00000020  72 61 6e 5f 6f 72 64 65  72 27 3a 20 46 61 6c 73  |ran_order': Fals|

The leading \x93 is deliberately a non-ASCII byte, so the file cannot be mistaken for text. It is followed by the ASCII string NUMPY.

File Structure

An .npy file has three parts:

1. Magic string and version
   \x93NUMPY  +  major (1 byte)  +  minor (1 byte)

2. Header
   header length  (2 bytes in v1.0, 4 bytes in v2.0+, little-endian)
   header data    (an ASCII/UTF-8 Python dict literal)

3. Raw array data
   the array bytes, contiguous, in the declared order

The header dictionary always contains three keys:

{'descr': '<f8', 'fortran_order': False, 'shape': (1000, 3)}
  • descr: a dtype string. < means little-endian, f8 means 8-byte float. So <f8 is float64.
  • fortran_order: False for C-contiguous (row-major), True for Fortran-contiguous (column-major).
  • shape: the array dimensions as a tuple.

The header is padded with spaces so that the data section begins on a 64-byte boundary, which lets NumPy memory-map the file directly.

History and Development

Before .npy, NumPy users saved arrays either as text (losing speed and precision) or with Python's pickle (tying the file to Python and creating a security hazard). NEP 1, accepted in 2007, defined a minimal binary format that was language-neutral, self-describing, and simple enough to reimplement in a few dozen lines.

Version 2.0 raised the header size limit for arrays with very many structured fields, and version 3.0 allowed UTF-8 in structured dtype field names. The format has otherwise been stable for well over a decade, which is a large part of its value.

Common Use Cases

  • Intermediate results: caching an expensive computation so a pipeline can resume without recomputing.
  • Machine learning datasets: storing feature matrices, embeddings, and label vectors.
  • Scientific data exchange: passing arrays between Python, Julia, R, and C++ tools.
  • Memory-mapped access: reading slices of an array larger than RAM without loading the whole file.
  • Test fixtures: pinning exact numeric inputs and expected outputs for regression tests.

How to Open an NPY File

In Python

import numpy as np

# Load the whole array
arr = np.load("data.npy")
print(arr.shape, arr.dtype)

# Memory-map instead of reading it all into RAM
big = np.load("huge.npy", mmap_mode="r")
chunk = big[1000:2000]        # only this slice is read from disk

Saving

import numpy as np

arr = np.random.rand(1000, 3)
np.save("data.npy", arr)      # .npy is appended automatically

Inspecting without loading the data

import numpy as np

with open("data.npy", "rb") as f:
    version = np.lib.format.read_magic(f)
    shape, fortran_order, dtype = np.lib.format.read_array_header_1_0(f)
    print(shape, dtype, "fortran" if fortran_order else "c-order")

From the shell

# The header is human-readable ASCII in the first ~100 bytes
head -c 128 data.npy | xxd

file data.npy

In other languages

  • Julia: NPZ.jl
  • R: the RcppCNPy package
  • C++: cnpy, or xtensor-io
  • Rust: the ndarray-npy crate
  • Go: github.com/sbinet/npyio

Security Considerations

np.load accepts an allow_pickle argument. When it is True, loading a file containing an object-dtype array executes pickle deserialisation, which can run arbitrary code. NumPy changed the default to False in version 1.16.3 precisely because of this risk.

Never set allow_pickle=True for a file you did not create yourself. A plain numeric .npy file never needs it.

Advantages

  • Exact round-trip: dtype, shape, and byte order are preserved perfectly.
  • Fast: essentially a memory copy; no parsing.
  • Self-describing: the file states its own type and shape.
  • Memory-mappable: the aligned header allows lazy, partial reads of huge arrays.
  • Simple: the specification is short enough to implement from scratch.

Limitations

  • One array per file: use NPZ for multiple arrays.
  • No compression: the data section is stored raw.
  • Not human-readable: only the header is text.
  • Weak ecosystem outside Python: support exists elsewhere but is rarely built in.
  • No schema evolution: the file records a fixed dtype with no versioning of your own data model.
  • NPZ: a ZIP archive holding several .npy files.
  • PICKLE: Python's general object serialisation, more flexible but unsafe to load from untrusted sources.
  • PARQUET: columnar storage for tabular data, with compression and a real schema.
  • H5: HDF5, for large hierarchical scientific datasets.
  • CSV: the text alternative: portable and readable, but slow and lossy for floats.

File Information

File Description

Numpy Array

Category

Data

Extensions

.npy

MIME Type

application/octet-stream

Related File Types

Other file types in the Data category you might also need:

Start Analyzing NPY Files Now

Use our free AI-powered tool to detect and analyze Numpy Array files instantly with Google's Magika technology.

Try File Detection Tool