diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
index 3939e847707d..291c32511bfd 100755
--- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
+++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
@@ -763,7 +763,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
                 <MenuItemWithTopDescription
                     key={name}
                     shouldShowRightIcon={!isReadOnly}
-                    title={TransactionUtils.getTag(transaction, index)}
+                    title={TransactionUtils.getTagForDisplay(transaction, index)}
                     description={name}
                     numberOfLinesTitle={2}
                     onPress={() =>
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index d3c86698f910..84a734846ce7 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -379,7 +379,7 @@ function MoneyRequestView({
                         >
                             <MenuItemWithTopDescription
                                 description={name ?? translate('common.tag')}
-                                title={TransactionUtils.getTag(transaction, index)}
+                                title={TransactionUtils.getTagForDisplay(transaction, index)}
                                 interactive={canEdit}
                                 shouldShowRightIcon={canEdit}
                                 titleStyle={styles.flex1}
diff --git a/src/libs/IOUUtils.ts b/src/libs/IOUUtils.ts
index 0bd5d3162236..56ac47676a37 100644
--- a/src/libs/IOUUtils.ts
+++ b/src/libs/IOUUtils.ts
@@ -109,18 +109,18 @@ function isValidMoneyRequestType(iouType: string): boolean {
 }
 
 /**
- * Inserts a newly selected tag into the already existed report tags like a string
+ * Inserts a newly selected tag into the already existing tags like a string
  *
- * @param reportTags - currently selected tags for a report
- * @param tag - a newly selected tag, that should be added to the reportTags
+ * @param transactionTags - currently selected tags for a report
+ * @param tag - a newly selected tag, that should be added to the transactionTags
  * @param tagIndex - the index of a tag list
  * @returns
  */
-function insertTagIntoReportTagsString(reportTags: string, tag: string, tagIndex: number): string {
-    const splittedReportTags = reportTags.split(CONST.COLON);
-    splittedReportTags[tagIndex] = tag;
+function insertTagIntoTransactionTagsString(transactionTags: string, tag: string, tagIndex: number): string {
+    const tagArray = TransactionUtils.getTagArrayFromName(transactionTags);
+    tagArray[tagIndex] = tag;
 
-    return splittedReportTags.join(CONST.COLON).replace(/:*$/, '');
+    return tagArray.join(CONST.COLON).replace(/:*$/, '');
 }
 
-export {calculateAmount, updateIOUOwnerAndTotal, isIOUReportPendingCurrencyConversion, isValidMoneyRequestType, navigateToStartMoneyRequestStep, insertTagIntoReportTagsString};
+export {calculateAmount, updateIOUOwnerAndTotal, isIOUReportPendingCurrencyConversion, isValidMoneyRequestType, navigateToStartMoneyRequestStep, insertTagIntoTransactionTagsString};
diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts
index 13a58834860b..f501244a725d 100644
--- a/src/libs/ModifiedExpenseMessage.ts
+++ b/src/libs/ModifiedExpenseMessage.ts
@@ -9,6 +9,7 @@ import * as Localize from './Localize';
 import * as PolicyUtils from './PolicyUtils';
 import * as ReportUtils from './ReportUtils';
 import type {ExpenseOriginalMessage} from './ReportUtils';
+import * as TransactionUtils from './TransactionUtils';
 
 let allPolicyTags: OnyxCollection<PolicyTagList> = {};
 Onyx.connect({
@@ -189,8 +190,8 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr
         const policyTags = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {};
         const transactionTag = reportActionOriginalMessage?.tag ?? '';
         const oldTransactionTag = reportActionOriginalMessage?.oldTag ?? '';
-        const splittedTag = transactionTag.split(CONST.COLON);
-        const splittedOldTag = oldTransactionTag.split(CONST.COLON);
+        const splittedTag = TransactionUtils.getTagArrayFromName(transactionTag);
+        const splittedOldTag = TransactionUtils.getTagArrayFromName(oldTransactionTag);
         const localizedTagListName = Localize.translateLocal('common.tag');
 
         Object.keys(policyTags).forEach((policyTagKey, index) => {
diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts
index d3eafc6554db..3ff2c39859c2 100644
--- a/src/libs/TransactionUtils.ts
+++ b/src/libs/TransactionUtils.ts
@@ -364,18 +364,50 @@ function getBillable(transaction: OnyxEntry<Transaction>): boolean {
     return transaction?.billable ?? false;
 }
 
+/**
+ * Return a colon-delimited tag string as an array, considering escaped colons and double backslashes.
+ */
+function getTagArrayFromName(tagName: string): string[] {
+    // WAIT!!!!!!!!!!!!!!!!!!
+    // You need to keep this in sync with TransactionUtils.php
+
+    // We need to be able to preserve double backslashes in the original string
+    // and not have it interfere with splitting on a colon (:).
+    // So, let's replace it with something absurd to begin with, do our split, and
+    // then replace the double backslashes in the end.
+    const tagWithoutDoubleSlashes = tagName.replace(/\\\\/g, '☠');
+    const tagWithoutEscapedColons = tagWithoutDoubleSlashes.replace(/\\:/g, '☢');
+
+    // Do our split
+    const matches = tagWithoutEscapedColons.split(':');
+    const newMatches: string[] = [];
+
+    for (const item of matches) {
+        const tagWithEscapedColons = item.replace(/☢/g, '\\:');
+        const tagWithDoubleSlashes = tagWithEscapedColons.replace(/☠/g, '\\\\');
+        newMatches.push(tagWithDoubleSlashes);
+    }
+
+    return newMatches;
+}
+
 /**
  * Return the tag from the transaction. When the tagIndex is passed, return the tag based on the index.
  * This "tag" field has no "modified" complement.
  */
 function getTag(transaction: OnyxEntry<Transaction>, tagIndex?: number): string {
     if (tagIndex !== undefined) {
-        return transaction?.tag?.split(CONST.COLON)[tagIndex] ?? '';
+        const tagsArray = getTagArrayFromName(transaction?.tag ?? '');
+        return tagsArray[tagIndex] ?? '';
     }
 
     return transaction?.tag ?? '';
 }
 
+function getTagForDisplay(transaction: OnyxEntry<Transaction>, tagIndex?: number): string {
+    return getTag(transaction, tagIndex).replace(/[\\\\]:/g, ':');
+}
+
 /**
  * Return the created field from the transaction, return the modifiedCreated if present.
  */
@@ -605,6 +637,8 @@ export {
     getCategory,
     getBillable,
     getTag,
+    getTagArrayFromName,
+    getTagForDisplay,
     getTransactionViolations,
     getLinkedTransaction,
     getAllReportTransactions,
diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts
index a1cd001badee..16b428549156 100644
--- a/src/libs/Violations/ViolationsUtils.ts
+++ b/src/libs/Violations/ViolationsUtils.ts
@@ -2,6 +2,7 @@ import reject from 'lodash/reject';
 import Onyx from 'react-native-onyx';
 import type {OnyxUpdate} from 'react-native-onyx';
 import type {Phrase, PhraseParameters} from '@libs/Localize';
+import * as TransactionUtils from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -50,7 +51,7 @@ const ViolationsUtils = {
         }
 
         if (policyRequiresTags) {
-            const selectedTags = updatedTransaction.tag?.split(CONST.COLON) ?? [];
+            const selectedTags = TransactionUtils.getTagArrayFromName(updatedTransaction.tag ?? '') ?? [];
             const policyTagKeys = Object.keys(policyTagList);
 
             if (policyTagKeys.length === 0) {
diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts
index 9e6745bbc291..6f8421ace41a 100644
--- a/src/libs/actions/Policy.ts
+++ b/src/libs/actions/Policy.ts
@@ -1633,8 +1633,8 @@ function buildOptimisticPolicyRecentlyUsedCategories(policyID?: string, category
     return lodashUnion([category], policyRecentlyUsedCategories);
 }
 
-function buildOptimisticPolicyRecentlyUsedTags(policyID?: string, reportTags?: string): RecentlyUsedTags {
-    if (!policyID || !reportTags) {
+function buildOptimisticPolicyRecentlyUsedTags(policyID?: string, transactionTags?: string): RecentlyUsedTags {
+    if (!policyID || !transactionTags) {
         return {};
     }
 
@@ -1643,7 +1643,7 @@ function buildOptimisticPolicyRecentlyUsedTags(policyID?: string, reportTags?: s
     const policyRecentlyUsedTags = allRecentlyUsedTags?.[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`] ?? {};
     const newOptimisticPolicyRecentlyUsedTags: RecentlyUsedTags = {};
 
-    reportTags.split(CONST.COLON).forEach((tag, index) => {
+    TransactionUtils.getTagArrayFromName(transactionTags).forEach((tag, index) => {
         if (!tag) {
             return;
         }
diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js
index 29917154a527..d52436fbbf4f 100644
--- a/src/pages/EditRequestPage.js
+++ b/src/pages/EditRequestPage.js
@@ -135,7 +135,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p
             IOU.updateMoneyRequestTag(
                 transaction.transactionID,
                 report.reportID,
-                IOUUtils.insertTagIntoReportTagsString(transactionTag, updatedTag, tagIndex),
+                IOUUtils.insertTagIntoTransactionTagsString(transactionTag, updatedTag, tagIndex),
                 policy,
                 policyTags,
                 policyCategories,
diff --git a/src/pages/iou/request/step/IOURequestStepTag.js b/src/pages/iou/request/step/IOURequestStepTag.js
index 20ab92d3d446..572663160090 100644
--- a/src/pages/iou/request/step/IOURequestStepTag.js
+++ b/src/pages/iou/request/step/IOURequestStepTag.js
@@ -82,7 +82,7 @@ function IOURequestStepTag({
      */
     const updateTag = (selectedTag) => {
         const isSelectedTag = selectedTag.searchText === tag;
-        const updatedTag = IOUUtils.insertTagIntoReportTagsString(transactionTag, isSelectedTag ? '' : selectedTag.searchText, tagIndex);
+        const updatedTag = IOUUtils.insertTagIntoTransactionTagsString(transactionTag, isSelectedTag ? '' : selectedTag.searchText, tagIndex);
         if (isSplitBill && isEditing) {
             IOU.setDraftSplitTransaction(transactionID, {tag: updatedTag});
             navigateBack();
