diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go
index b80d96da8e..e1a60855df 100644
--- a/runtime/interpreter/value.go
+++ b/runtime/interpreter/value.go
@@ -1043,6 +1043,8 @@ var _ ValueIndexableValue = &StringValue{}
 var _ MemberAccessibleValue = &StringValue{}
 var _ IterableValue = &StringValue{}
 
+var VarSizedArrayOfStringType = NewVariableSizedStaticType(nil, PrimitiveStaticTypeString)
+
 func (v *StringValue) prepareGraphemes() {
 	if v.graphemes == nil {
 		v.graphemes = uniseg.NewGraphemes(v.Str)
@@ -1342,6 +1344,20 @@ func (v *StringValue) GetMember(interpreter *Interpreter, locationRange Location
 				return v.ToLower(invocation.Interpreter)
 			},
 		)
+
+	case sema.StringTypeSplitFunctionName:
+		return NewHostFunctionValue(
+			interpreter,
+			sema.StringTypeSplitFunctionType,
+			func(invocation Invocation) Value {
+				separator, ok := invocation.Arguments[0].(*StringValue)
+				if !ok {
+					panic(errors.NewUnreachableError())
+				}
+
+				return v.Split(invocation.Interpreter, invocation.LocationRange, separator.Str)
+			},
+		)
 	}
 
 	return nil
@@ -1396,6 +1412,35 @@ func (v *StringValue) ToLower(interpreter *Interpreter) *StringValue {
 	)
 }
 
+func (v *StringValue) Split(inter *Interpreter, locationRange LocationRange, separator string) Value {
+	split := strings.Split(v.Str, separator)
+
+	var index int
+	count := len(split)
+
+	return NewArrayValueWithIterator(
+		inter,
+		VarSizedArrayOfStringType,
+		common.ZeroAddress,
+		uint64(count),
+		func() Value {
+			if index >= count {
+				return nil
+			}
+
+			str := split[index]
+			index++
+			return NewStringValue(
+				inter,
+				common.NewStringMemoryUsage(len(str)),
+				func() string {
+					return str
+				},
+			)
+		},
+	)
+}
+
 func (v *StringValue) Storable(storage atree.SlabStorage, address atree.Address, maxInlineSize uint64) (atree.Storable, error) {
 	return maybeLargeImmutableStorable(v, storage, address, maxInlineSize)
 }
diff --git a/runtime/sema/string_type.go b/runtime/sema/string_type.go
index 6568c5b0a8..74b9baaccf 100644
--- a/runtime/sema/string_type.go
+++ b/runtime/sema/string_type.go
@@ -42,6 +42,11 @@ const StringTypeJoinFunctionDocString = `
 Returns a string after joining the array of strings with the provided separator.
 `
 
+const StringTypeSplitFunctionName = "split"
+const StringTypeSplitFunctionDocString = `
+Returns a variable-sized array of strings after splitting the string on the delimiter.
+`
+
 // StringType represents the string type
 var StringType = &SimpleType{
 	Name:          "String",
@@ -105,6 +110,12 @@ func init() {
 				StringTypeToLowerFunctionType,
 				stringTypeToLowerFunctionDocString,
 			),
+			NewUnmeteredPublicFunctionMember(
+				t,
+				StringTypeSplitFunctionName,
+				StringTypeSplitFunctionType,
+				StringTypeSplitFunctionDocString,
+			),
 		})
 	}
 }
@@ -335,3 +346,18 @@ var StringTypeJoinFunctionType = NewSimpleFunctionType(
 	},
 	StringTypeAnnotation,
 )
+
+var StringTypeSplitFunctionType = NewSimpleFunctionType(
+	FunctionPurityView,
+	[]Parameter{
+		{
+			Identifier:     "separator",
+			TypeAnnotation: StringTypeAnnotation,
+		},
+	},
+	NewTypeAnnotation(
+		&VariableSizedType{
+			Type: StringType,
+		},
+	),
+)
diff --git a/runtime/tests/checker/string_test.go b/runtime/tests/checker/string_test.go
index 2ce9fc681b..5d94c0c077 100644
--- a/runtime/tests/checker/string_test.go
+++ b/runtime/tests/checker/string_test.go
@@ -408,3 +408,46 @@ func TestCheckStringJoinTypeMissingArgumentLabelSeparator(t *testing.T) {
 
 	assert.IsType(t, &sema.MissingArgumentLabelError{}, errs[0])
 }
+
+func TestCheckStringSplit(t *testing.T) {
+
+	t.Parallel()
+
+	checker, err := ParseAndCheck(t, `
+		let s = "👪.❤️.Abc".split(separator: ".")
+	`)
+	require.NoError(t, err)
+
+	assert.Equal(t,
+		&sema.VariableSizedType{
+			Type: sema.StringType,
+		},
+		RequireGlobalValue(t, checker.Elaboration, "s"),
+	)
+}
+
+func TestCheckStringSplitTypeMismatchSeparator(t *testing.T) {
+
+	t.Parallel()
+
+	_, err := ParseAndCheck(t, `
+		let s = "Abc:1".split(separator: 1234)
+	`)
+
+	errs := RequireCheckerErrors(t, err, 1)
+
+	assert.IsType(t, &sema.TypeMismatchError{}, errs[0])
+}
+
+func TestCheckStringSplitTypeMissingArgumentLabelSeparator(t *testing.T) {
+
+	t.Parallel()
+
+	_, err := ParseAndCheck(t, `
+	let s = "👪Abc".split("/")
+	`)
+
+	errs := RequireCheckerErrors(t, err, 1)
+
+	assert.IsType(t, &sema.MissingArgumentLabelError{}, errs[0])
+}
diff --git a/runtime/tests/interpreter/string_test.go b/runtime/tests/interpreter/string_test.go
index 51873a5a79..37bba83186 100644
--- a/runtime/tests/interpreter/string_test.go
+++ b/runtime/tests/interpreter/string_test.go
@@ -499,3 +499,100 @@ func TestInterpretStringJoin(t *testing.T) {
 	testCase(t, "testEmptyArray", interpreter.NewUnmeteredStringValue(""))
 	testCase(t, "testSingletonArray", interpreter.NewUnmeteredStringValue("pqrS"))
 }
+
+func TestInterpretStringSplit(t *testing.T) {
+
+	t.Parallel()
+
+	inter := parseCheckAndInterpret(t, `
+		fun split(): [String] {
+			return "👪////❤️".split(separator: "////")
+		}
+		fun splitBySpace(): [String] {
+			return "👪 ❤️ Abc6 ;123".split(separator: " ")
+		}
+		fun splitWithUnicodeEquivalence(): [String] {
+			return "Caf\u{65}\u{301}ABc".split(separator: "\u{e9}")
+		}
+		fun testEmptyString(): [String] {
+			return "".split(separator: "//")
+		}
+		fun testNoMatch(): [String] {
+			return "pqrS;asdf".split(separator: ";;")
+		}
+	`)
+
+	testCase := func(t *testing.T, funcName string, expected *interpreter.ArrayValue) {
+		t.Run(funcName, func(t *testing.T) {
+			result, err := inter.Invoke(funcName)
+			require.NoError(t, err)
+
+			RequireValuesEqual(
+				t,
+				inter,
+				expected,
+				result,
+			)
+		})
+	}
+
+	varSizedStringType := &interpreter.VariableSizedStaticType{
+		Type: interpreter.PrimitiveStaticTypeString,
+	}
+
+	testCase(t,
+		"split",
+		interpreter.NewArrayValue(
+			inter,
+			interpreter.EmptyLocationRange,
+			varSizedStringType,
+			common.ZeroAddress,
+			interpreter.NewUnmeteredStringValue("👪"),
+			interpreter.NewUnmeteredStringValue("❤️"),
+		),
+	)
+	testCase(t,
+		"splitBySpace",
+		interpreter.NewArrayValue(
+			inter,
+			interpreter.EmptyLocationRange,
+			varSizedStringType,
+			common.ZeroAddress,
+			interpreter.NewUnmeteredStringValue("👪"),
+			interpreter.NewUnmeteredStringValue("❤️"),
+			interpreter.NewUnmeteredStringValue("Abc6"),
+			interpreter.NewUnmeteredStringValue(";123"),
+		),
+	)
+	testCase(t,
+		"splitWithUnicodeEquivalence",
+		interpreter.NewArrayValue(
+			inter,
+			interpreter.EmptyLocationRange,
+			varSizedStringType,
+			common.ZeroAddress,
+			interpreter.NewUnmeteredStringValue("Caf"),
+			interpreter.NewUnmeteredStringValue("ABc"),
+		),
+	)
+	testCase(t,
+		"testEmptyString",
+		interpreter.NewArrayValue(
+			inter,
+			interpreter.EmptyLocationRange,
+			varSizedStringType,
+			common.ZeroAddress,
+			interpreter.NewUnmeteredStringValue(""),
+		),
+	)
+	testCase(t,
+		"testNoMatch",
+		interpreter.NewArrayValue(
+			inter,
+			interpreter.EmptyLocationRange,
+			varSizedStringType,
+			common.ZeroAddress,
+			interpreter.NewUnmeteredStringValue("pqrS;asdf"),
+		),
+	)
+}