diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp
index 6ab37a388f24beb17266d3828f77a1df4a906028..047b88dfb0502e284a78bfb21ce61059fafb1160 100644
--- a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp
+++ b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp
@@ -96,7 +96,10 @@ int main(int argc, char *argv[])
                     "Hello from rank: " + std::to_string(rank) +
                     " and timestep: " + std::to_string(timeStep));
 
-                bpWriter.PutSync(bpString, myString);
+                if (rank == 0)
+                {
+                    bpWriter.PutSync(bpString, myString);
+                }
 
                 bpWriter.EndStep();
             }
@@ -116,6 +119,9 @@ int main(int argc, char *argv[])
             adios2::Variable<float> *bpFloats000 =
                 ioReader.InquireVariable<float>("bpFloats000");
 
+            adios2::Variable<std::string> *bpString =
+                ioReader.InquireVariable<std::string>("bpString");
+
             if (bpFloats000 != nullptr)
             {
                 bpFloats000->SetSelection({{rank * Nx}, {Nx}});
@@ -125,7 +131,7 @@ int main(int argc, char *argv[])
                 bpReader.GetSync(*bpFloats000, data.data());
 
                 std::cout << "Data timestep " << bpFloats000->m_StepsStart
-                          << " from rank " << rank << "\n";
+                          << " from rank " << rank << ": ";
                 for (const auto datum : data)
                 {
                     std::cout << datum << " ";
@@ -136,8 +142,17 @@ int main(int argc, char *argv[])
             {
                 std::cout << "Variable bpFloats000 not found\n";
             }
+
+            if (bpString != nullptr)
+            {
+                bpString->SetStepSelection({3, 1});
+
+                std::string myString;
+                bpReader.GetSync(*bpString, myString);
+                std::cout << myString << "\n";
+            }
+
             bpReader.Close();
-            //}
         }
     }
     catch (std::invalid_argument &e)
diff --git a/source/adios2/engine/bp/BPFileReader.tcc b/source/adios2/engine/bp/BPFileReader.tcc
index 5fbecc0d91da68c15efa2691760f8e1b4dcb6487..743b4028909f2be8a42a2d6fbffde7e04253c9fc 100644
--- a/source/adios2/engine/bp/BPFileReader.tcc
+++ b/source/adios2/engine/bp/BPFileReader.tcc
@@ -16,10 +16,17 @@
 namespace adios2
 {
 
+template <>
+inline void BPFileReader::GetSyncCommon(Variable<std::string> &variable,
+                                        std::string *data)
+{
+    variable.SetData(data);
+    m_BP3Deserializer.GetStringFromMetadata(variable);
+}
+
 template <class T>
-void BPFileReader::GetSyncCommon(Variable<T> &variable, T *data)
+inline void BPFileReader::GetSyncCommon(Variable<T> &variable, T *data)
 {
-    // subfile info
     variable.SetData(data);
 
     const std::map<std::string, SubFileInfoMap> variableSubfileInfo =
diff --git a/source/adios2/toolkit/format/bp3/BP3Base.tcc b/source/adios2/toolkit/format/bp3/BP3Base.tcc
index ffd66cba53c7bb0652c894a07d075bd65077cf6f..3a807d2614805a3aa1743636fcc1a752a045ab6d 100644
--- a/source/adios2/toolkit/format/bp3/BP3Base.tcc
+++ b/source/adios2/toolkit/format/bp3/BP3Base.tcc
@@ -160,7 +160,7 @@ int8_t BP3Base::GetDataType<cldouble>() const noexcept
 }
 
 template <class T>
-inline BP3Base::Characteristics<T> BP3Base::ReadElementIndexCharacteristics(
+BP3Base::Characteristics<T> BP3Base::ReadElementIndexCharacteristics(
     const std::vector<char> &buffer, size_t &position, const DataTypes dataType,
     const bool untilTimeStep) const
 {
diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp
index 99b668ffdde584408dc5d0a5c23ceefaffd7ce17..edf25648c899194f12f0c2daeea31721e66b6cd5 100644
--- a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp
+++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp
@@ -65,6 +65,36 @@ void BP3Deserializer::ClipContiguousMemory(
 #undef declare_type
 }
 
+void BP3Deserializer::GetStringFromMetadata(
+    Variable<std::string> &variable) const
+{
+    std::string *data = variable.GetData();
+    const auto &buffer = m_Metadata.m_Buffer;
+
+    for (size_t i = 0; i < variable.m_StepsCount; ++i)
+    {
+        *(data + i) = "";
+        const size_t step = variable.m_StepsStart + i;
+        auto itStep = variable.m_IndexStepBlockStarts.find(step);
+
+        if (itStep == variable.m_IndexStepBlockStarts.end())
+        {
+            continue;
+        }
+
+        for (auto position : itStep->second)
+        {
+            const Characteristics<std::string> characteristics =
+                ReadElementIndexCharacteristics<std::string>(
+                    buffer, position, type_string, false);
+
+            *(data + i) = characteristics.Statistics.Value;
+        }
+
+        variable.m_Value = *(data + i);
+    }
+}
+
 // PRIVATE
 void BP3Deserializer::ParseMinifooter()
 {
@@ -139,6 +169,13 @@ void BP3Deserializer::ParseVariablesIndex(IO &io)
         switch (header.DataType)
         {
 
+        // TODO: string
+        case (type_string):
+        {
+            DefineVariableInIO<std::string>(header, io, buffer, position);
+            break;
+        }
+
         case (type_byte):
         {
             DefineVariableInIO<signed char>(header, io, buffer, position);
@@ -225,7 +262,7 @@ void BP3Deserializer::ParseVariablesIndex(IO &io)
                                                           position);
             break;
         }
-            // TODO: string
+
         } // end switch
     };
 
diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.h b/source/adios2/toolkit/format/bp3/BP3Deserializer.h
index eb24da84f86b34ecdc080272f5d7a8e35429d48e..1cb508b6272dbf6d04d8880510b518442e1f8df0 100644
--- a/source/adios2/toolkit/format/bp3/BP3Deserializer.h
+++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.h
@@ -59,6 +59,8 @@ public:
                               const Box<Dims> &blockBox,
                               const Box<Dims> &intersectionBox) const;
 
+    void GetStringFromMetadata(Variable<std::string> &variable) const;
+
 private:
     std::map<std::string, SubFileInfoMap> m_DeferredVariables;
 
diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc
index f36d3fb7fd4a279716490e62f9221d24370eb54d..3d49306b639e086e0ed07fe2d033680913d835e3 100644
--- a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc
+++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc
@@ -37,11 +37,74 @@ void BP3Deserializer::GetDeferredVariable(Variable<T> &variable, T *data)
 }
 
 // PRIVATE
+template <>
+inline void BP3Deserializer::DefineVariableInIO<std::string>(
+    const ElementIndexHeader &header, IO &io, const std::vector<char> &buffer,
+    size_t position) const
+{
+    const size_t initialPosition = position;
+
+    const Characteristics<std::string> characteristics =
+        ReadElementIndexCharacteristics<std::string>(
+            buffer, position, static_cast<DataTypes>(header.DataType));
+
+    std::string variableName(header.Name);
+    if (!header.Path.empty())
+    {
+        variableName = header.Path + PathSeparator + header.Name;
+    }
+
+    Variable<std::string> *variable = nullptr;
+    if (characteristics.Statistics.IsValue)
+    {
+        std::lock_guard<std::mutex> lock(m_Mutex);
+        variable = &io.DefineVariable<std::string>(variableName);
+        variable->m_Value =
+            characteristics.Statistics.Value; // assigning first step
+    }
+    else
+    {
+        // TODO: throw exception?
+    }
+
+    // going back to get variable index position
+    variable->m_IndexStart =
+        initialPosition - (header.Name.size() + header.GroupName.size() +
+                           header.Path.size() + 23);
+
+    const size_t endPosition =
+        variable->m_IndexStart + static_cast<size_t>(header.Length) + 4;
+
+    position = initialPosition;
+
+    size_t currentStep = 0; // Starts at 1 in bp file
+
+    while (position < endPosition)
+    {
+        const size_t subsetPosition = position;
+
+        // read until step is found
+        const Characteristics<std::string> subsetCharacteristics =
+            ReadElementIndexCharacteristics<std::string>(
+                buffer, position, static_cast<DataTypes>(header.DataType),
+                false);
+
+        if (subsetCharacteristics.Statistics.Step > currentStep)
+        {
+            currentStep = subsetCharacteristics.Statistics.Step;
+            variable->m_AvailableStepsCount =
+                subsetCharacteristics.Statistics.Step;
+        }
+        variable->m_IndexStepBlockStarts[currentStep].push_back(subsetPosition);
+        position = subsetPosition + subsetCharacteristics.EntryLength + 5;
+    }
+}
+
 template <class T>
-void BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header,
-                                         IO &io,
-                                         const std::vector<char> &buffer,
-                                         size_t position) const
+inline void
+BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, IO &io,
+                                    const std::vector<char> &buffer,
+                                    size_t position) const
 {
     const size_t initialPosition = position;
 
diff --git a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp
index e0d72e8078667aa3b5262cba35a22fbf8d0f6f14..4aa708d8266a5af2b9c3e4c1c7229e1051a2484b 100644
--- a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp
+++ b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp
@@ -160,10 +160,10 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
 
         adios2::Engine &bpReader = io.Open(fname, adios2::Mode::Read);
 
-        //        auto var_iString = io.InquireVariable<std::string>("iString");
-        //        ASSERT_NE(var_iString, nullptr);
-        // ASSERT_EQ(var_iString->m_Shape.size(), 0);
-        // ASSERT_EQ(var_iString->m_AvailableStepsCount, NSteps);
+        auto var_iString = io.InquireVariable<std::string>("iString");
+        ASSERT_NE(var_iString, nullptr);
+        ASSERT_EQ(var_iString->m_Shape.size(), 0);
+        ASSERT_EQ(var_iString->m_AvailableStepsCount, NSteps);
 
         auto var_i8 = io.InquireVariable<int8_t>("i8");
         ASSERT_NE(var_i8, nullptr);
@@ -228,7 +228,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
         // TODO: other types
 
         SmallTestData testData;
-        std::vector<char> IString(testData.S1.size());
+
+        std::string IString;
         std::array<int8_t, Nx> I8;
         std::array<int16_t, Nx> I16;
         std::array<int32_t, Nx> I32;
@@ -260,6 +261,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
 
         for (size_t t = 0; t < NSteps; ++t)
         {
+            var_iString->SetStepSelection({t + 1, 1});
+
             var_i8->SetStepSelection({t + 1, 1});
             var_i16->SetStepSelection({t + 1, 1});
             var_i32->SetStepSelection({t + 1, 1});
@@ -277,6 +280,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
             SmallTestData currentTestData = generateNewSmallTestData(
                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
 
+            bpReader.GetSync(*var_iString, IString);
+
             bpReader.GetDeferred(*var_i8, I8.data());
             bpReader.GetDeferred(*var_i16, I16.data());
             bpReader.GetDeferred(*var_i32, I32.data());
@@ -292,6 +297,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
 
             bpReader.PerformGets();
 
+            EXPECT_EQ(IString, currentTestData.S1);
+
             for (size_t i = 0; i < Nx; ++i)
             {
                 std::stringstream ss;