diff --git a/qim3d/io/load.py b/qim3d/io/load.py
index 49736eb3065b8614fe3aa5d7f2bc92ba6896c933..33a7c6b13512a1c8b08418d6f9514c874d9e9350 100644
--- a/qim3d/io/load.py
+++ b/qim3d/io/load.py
@@ -1,17 +1,19 @@
 """Provides functionality for loading data from various file formats."""
 
-import os
 import difflib
-import tifffile
+import os
+from pathlib import Path
+
 import h5py
 import nibabel as nib
 import numpy as np
-from pathlib import Path
+import tifffile
+from PIL import Image, UnidentifiedImageError
+
 import qim3d
 from qim3d.io.logger import log
 from qim3d.utils.internal_tools import sizeof, stringify_path
 from qim3d.utils.system import Memory
-from PIL import Image, UnidentifiedImageError
 
 
 class DataLoader:
@@ -31,6 +33,7 @@ class DataLoader:
         load_h5(path): Load an HDF5 file from the specified path.
         load_tiff_stack(path): Load a stack of TIFF files from the specified path.
         load_txrm(path): Load a TXRM/TXM/XRM file from the specified path
+        load_vol(path): Load a VOL file from the specified path. Path should point to the .vgi metadata file
         load(path): Load a file or directory based on the given path
 
     Example:
@@ -293,6 +296,106 @@ class DataLoader:
         """
         return np.array(Image.open(path))
 
+    def _load_vgi_metadata(self, path):
+        """ Helper functions that loads metadata from a VGI file
+
+        Args:
+            path (str): The path to the VGI file.
+        
+        returns:
+            dict: The loaded metadata.
+        """
+        meta_data = {}
+        current_section = meta_data
+        section_stack = [meta_data]
+
+        should_indent = True
+
+        with open(path, 'r') as f:
+            for line in f:
+                line = line.strip()
+                # {NAME} is start of a new object, so should indent
+                if line.startswith('{') and line.endswith('}'):
+                    section_name = line[1:-1]
+                    current_section[section_name] = {}
+                    section_stack.append(current_section)
+                    current_section = current_section[section_name]
+
+                    should_indent = True
+                # [NAME] is start of a section, so should not indent
+                elif line.startswith('[') and line.endswith(']'):
+                    section_name = line[1:-1]
+
+                    if not should_indent:
+                        if len(section_stack) > 1:
+                            current_section = section_stack.pop()
+
+                    current_section[section_name] = {}
+                    section_stack.append(current_section)
+                    current_section = current_section[section_name]
+
+                    should_indent = False
+                # = is a key value pair
+                elif '=' in line:
+                    key, value = line.split('=', 1)
+                    current_section[key.strip()] = value.strip()
+                elif line == '':
+                    if len(section_stack) > 1:
+                        current_section = section_stack.pop()
+
+        return meta_data
+
+    def load_vol(self, path):
+        """ Load a VOL filed based on the VGI metadata file
+
+        Args:
+            path (str): The path to the VGI file.
+        
+        Raises:
+            ValueError: If path points to a .vol file and not a .vgi file
+        
+        returns:
+            numpy.ndarray, numpy.memmap or tuple: The loaded volume.
+                If 'self.return_metadata' is True, returns a tuple (volume, metadata).
+        """
+        # makes sure path point to .VGI metadata file and not the .VOL file
+        if path.endswith(".vol") and os.path.isfile(path.replace(".vol",".vgi")):
+            path = path.replace(".vol",".vgi")
+            log.warning("Corrected path to .vgi metadata file from .vol file")
+        elif path.endswith(".vol") and not os.path.isfile(path.replace(".vol",".vgi")):
+            raise ValueError(f"Unsupported file format, should point to .vgi metadata file assumed to be in same folder as .vol file: {path}")
+
+        meta_data = self._load_vgi_metadata(path)
+
+        # Extracts relevant information from the metadata
+        file_name =  meta_data['volume1']["file1"]["Name"]
+        path = path.rsplit('/', 1)[0]  # Remove characters after the last "/" to be replaced with .vol filename
+        vol_path = os.path.join(path, file_name) # .vol and .vgi files are assumed to be in the same directory
+        dims = meta_data['volume1']['file1']['Size']
+        dims = [int(n) for n in dims.split() if n.isdigit()]
+        
+        dt = meta_data['volume1']['file1']['Datatype']
+        match dt:
+            case 'float':
+                dt = np.float32
+            case 'uint8':
+                dt = np.uint8
+            case 'unsigned integer':
+                dt = np.uint16
+            case _:
+                raise ValueError(f"Unsupported data type: {dt}")
+        
+        if self.virtual_stack:
+            vol = np.memmap(vol_path, dtype=dt, mode='r', shape=(dims[2], dims[0], dims[1]))
+        else:
+            vol = np.fromfile(vol_path, dtype=dt, count=np.prod(dims))
+            vol = np.reshape(vol, (dims[2], dims[0], dims[1]))
+
+        if self.return_metadata:
+            return vol, meta_data
+        else:
+            return vol
+
     def load(self, path):
         """
         Load a file or directory based on the given path.
@@ -327,6 +430,8 @@ class DataLoader:
                 return self.load_txrm(path)
             elif path.endswith((".nii",".nii.gz")):
                 return self.load_nifti(path)
+            elif path.endswith((".vol",".vgi")):
+                return self.load_vol(path)
             else:
                 try:
                     return self.load_pil(path)