diff --git a/Applications/DataExplorer/Base/ImportFileTypes.h b/Applications/DataExplorer/Base/ImportFileTypes.h
index 95aec4e84f026527d3e622f7c3417f96a3a4dea4..8e45d6018e100ad3e72d7855293fb151741f3297 100644
--- a/Applications/DataExplorer/Base/ImportFileTypes.h
+++ b/Applications/DataExplorer/Base/ImportFileTypes.h
@@ -101,7 +101,7 @@ public:
         if (t == ImportFileType::OGS_STN)
             return "OpenGeosys files (*.stn)";
         if (t == ImportFileType::OGS_MSH)
-            return "OpenGeosys files (*.vtu *.msh)";
+            return "OpenGeosys files (*.vtu *.vtk *.msh)";
         if (t == ImportFileType::PETREL)
             return "Petrel files (*)";
         if (t == ImportFileType::RASTER)
diff --git a/Applications/DataExplorer/mainwindow.cpp b/Applications/DataExplorer/mainwindow.cpp
index ec1fb1eb6bb9f5ba3e318d2c9c7fe569ed5ac2b0..93d721ef552374785f23a858cb863e51d47528f3 100644
--- a/Applications/DataExplorer/mainwindow.cpp
+++ b/Applications/DataExplorer/mainwindow.cpp
@@ -585,7 +585,9 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName)
             }
         }
         // OpenGeoSys mesh files
-        else if (fi.suffix().toLower() == "msh" || fi.suffix().toLower() == "vtu")
+        else if (fi.suffix().toLower() == "msh" ||
+                 fi.suffix().toLower() == "vtu" ||
+                 fi.suffix().toLower() == "vtk")
         {
 #ifndef NDEBUG
             QTime myTimer0;
@@ -987,7 +989,9 @@ void MainWindow::mapGeometry(const std::string &geo_name)
     MeshLib::Mesh* mesh (nullptr);
     if (choice == 0) // load mesh from file
     {
-        if (fi.suffix().toLower() == "vtu" || fi.suffix().toLower() == "msh")
+        if (fi.suffix().toLower() == "vtu" ||
+            fi.suffix().toLower() == "vtk" ||
+            fi.suffix().toLower() == "msh")
         {
             mesh = MeshLib::IO::readMeshFromFile(file_name.toStdString());
         }
diff --git a/MeshLib/IO/VtkIO/VtuInterface.cpp b/MeshLib/IO/VtkIO/VtuInterface.cpp
index 6b958a75f4472df6d6984fb744bfa60533b04804..8c98358c2f30013d38a60e3f635eff74545f4d68 100644
--- a/MeshLib/IO/VtkIO/VtuInterface.cpp
+++ b/MeshLib/IO/VtkIO/VtuInterface.cpp
@@ -14,6 +14,7 @@
 #include "VtuInterface.h"
 
 #include <vtkNew.h>
+#include <vtkGenericDataObjectReader.h>
 #include <vtkXMLUnstructuredGridReader.h>
 #include <vtkXMLUnstructuredGridWriter.h>
 #if defined(USE_PETSC) || defined(USE_MPI)
@@ -72,6 +73,42 @@ MeshLib::Mesh* VtuInterface::readVTUFile(std::string const &file_name)
     return MeshLib::VtkMeshConverter::convertUnstructuredGrid(vtkGrid, mesh_name);
 }
 
+MeshLib::Mesh* VtuInterface::readVTKFile(std::string const& file_name)
+{
+    if (!BaseLib::IsFileExisting(file_name))
+    {
+        ERR("File '{:s}' does not exist.", file_name);
+        return nullptr;
+    }
+
+    vtkSmartPointer<vtkGenericDataObjectReader> reader =
+        vtkSmartPointer<vtkGenericDataObjectReader>::New();
+    reader->SetFileName(file_name.c_str());
+    reader->Update();
+
+    // check for unstructured grid
+    if (reader->ReadOutputType() != 4)
+    {
+        ERR("Only VTK-files with dataset type \"Unstructured Grid\" are "
+            "currently supported.");
+        return nullptr;
+    }
+
+    reader->ReadAllFieldsOn();
+    reader->ReadAllScalarsOn();
+    vtkUnstructuredGrid* vtkGrid = reader->GetUnstructuredGridOutput();
+    if (vtkGrid->GetNumberOfPoints() == 0)
+    {
+        ERR("Mesh '{:s}' contains zero points.", file_name);
+        return nullptr;
+    }
+
+    std::string const mesh_name(
+        BaseLib::extractBaseNameWithoutExtension(file_name));
+    return MeshLib::VtkMeshConverter::convertUnstructuredGrid(vtkGrid,
+                                                              mesh_name);
+}
+
 #ifdef USE_PETSC
 std::string getVtuFileNameForPetscOutputWithoutExtension(
     std::string const& file_name)
diff --git a/MeshLib/IO/VtkIO/VtuInterface.h b/MeshLib/IO/VtkIO/VtuInterface.h
index 81e3b4bf44966d194bfee0ad8128beb931292ddd..c8f9cae2d2044f46282d62baf09099c8d85ee2db 100644
--- a/MeshLib/IO/VtkIO/VtuInterface.h
+++ b/MeshLib/IO/VtkIO/VtuInterface.h
@@ -41,10 +41,15 @@ public:
                           int dataMode = vtkXMLWriter::Appended,
                           bool compressed = false);
 
-    /// Read an unstructured grid from a VTU file
+    /// Read an unstructured grid from a VTU file.
     /// \return The converted mesh or a nullptr if reading failed
     static MeshLib::Mesh* readVTUFile(std::string const &file_name);
 
+    /// Read an unstructured grid from a legacy VTK file.
+    /// Other data structures such as PolyData are ignored.
+    /// \return The converted mesh or a nullptr if reading failed
+    static MeshLib::Mesh* readVTKFile(std::string const& file_name);
+
     /// Writes the given mesh to file.
     /// \return True on success, false on error
     bool writeToFile(std::string const &file_name);
diff --git a/MeshLib/IO/readMeshFromFile.cpp b/MeshLib/IO/readMeshFromFile.cpp
index 5b2f94aa849df32eb29d1e83078b1398ec99ddfb..6a6845fb96b5d2a0011177057b687b5628d11145 100644
--- a/MeshLib/IO/readMeshFromFile.cpp
+++ b/MeshLib/IO/readMeshFromFile.cpp
@@ -80,6 +80,11 @@ MeshLib::Mesh* readMeshFromFileSerial(const std::string &file_name)
         return MeshLib::IO::VtuInterface::readVTUFile(file_name);
     }
 
+    if (BaseLib::hasFileExtension(".vtk", file_name))
+    {
+        return MeshLib::IO::VtuInterface::readVTKFile(file_name);
+    }
+
     ERR("readMeshFromFile(): Unknown mesh file format in file {:s}.",
         file_name);
     return nullptr;