diff --git a/client/js/controls/auto_complete_control.js b/client/js/controls/auto_complete_control.js
index 2bb1c9f..3f46ab5 100644
--- a/client/js/controls/auto_complete_control.js
+++ b/client/js/controls/auto_complete_control.js
@@ -28,6 +28,7 @@ class AutoCompleteControl {
         this._sourceInputNode = sourceInputNode;
         this._options = {};
         Object.assign(this._options, {
+            transform: null,
             verticalShift: 2,
             source: null,
             addSpace: false,
@@ -37,27 +38,8 @@ class AutoCompleteControl {
                 const start = _getSelectionStart(sourceInputNode);
                 return value.substring(0, start).replace(/.*\s+/, '');
             },
-            confirm: text => {
-                const start = _getSelectionStart(sourceInputNode);
-                let prefix = '';
-                let suffix = sourceInputNode.value.substring(start);
-                let middle = sourceInputNode.value.substring(0, start);
-                const index = middle.lastIndexOf(' ');
-                if (index !== -1) {
-                    prefix = sourceInputNode.value.substring(0, index + 1);
-                    middle = sourceInputNode.value.substring(index + 1);
-                }
-                sourceInputNode.value = prefix +
-                    this._results[this._activeResult].value +
-                    ' ' +
-                    suffix.trimLeft();
-                if (!this._options.addSpace) {
-                    sourceInputNode.value = sourceInputNode.value.trim();
-                }
-                sourceInputNode.focus();
-            },
-            delete: text => {
-            },
+            confirm: null,
+            delete: null,
             getMatches: null,
         }, options);
 
@@ -74,6 +56,43 @@ class AutoCompleteControl {
         this._isVisible = false;
     }
 
+    defaultConfirmStrategy(text) {
+        const start = _getSelectionStart(this._sourceInputNode);
+        let prefix = '';
+        let suffix = this._sourceInputNode.value.substring(start);
+        let middle = this._sourceInputNode.value.substring(0, start);
+        const index = middle.lastIndexOf(' ');
+        if (index !== -1) {
+            prefix = this._sourceInputNode.value.substring(0, index + 1);
+            middle = this._sourceInputNode.value.substring(index + 1);
+        }
+        this._sourceInputNode.value = prefix + text + ' ' + suffix.trimLeft();
+        if (!this._options.addSpace) {
+            this._sourceInputNode.value = this._sourceInputNode.value.trim();
+        }
+        this._sourceInputNode.focus();
+    }
+
+    _delete(text) {
+        if (this._options.transform) {
+            text = this._options.transform(text);
+        }
+        if (this._options.delete) {
+            this._options.delete(text);
+        }
+    }
+
+    _confirm(text) {
+        if (this._options.transform) {
+            text = this._options.transform(text);
+        }
+        if (this._options.confirm) {
+            this._options.confirm(text);
+        } else {
+            this.defaultConfirmStrategy(text);
+        }
+    }
+
     _show() {
         this._suggestionDiv.style.display = 'block';
         this._isVisible = true;
@@ -136,12 +155,12 @@ class AutoCompleteControl {
                 func = () => { this._selectNext(); };
             } else if (key === KEY_RETURN && this._activeResult >= 0) {
                 func = () => {
-                    this._options.confirm(this._getActiveSuggestion());
+                    this._confirm(this._getActiveSuggestion());
                     this.hide();
                 };
             } else if (key === KEY_DELETE && this._activeResult >= 0) {
                 func = () => {
-                    this._options.delete(this._getActiveSuggestion());
+                    this._delete(this._getActiveSuggestion());
                     this.hide();
                 };
             }
@@ -229,7 +248,7 @@ class AutoCompleteControl {
                 e => {
                     e.preventDefault();
                     this._activeResult = resultIndexWorkaround;
-                    this._options.confirm(this._getActiveSuggestion());
+                    this._confirm(this._getActiveSuggestion());
                     this.hide();
                 });
             listItem.appendChild(link);
diff --git a/client/js/util/misc.js b/client/js/util/misc.js
index 3258030..56eb66e 100644
--- a/client/js/util/misc.js
+++ b/client/js/util/misc.js
@@ -213,6 +213,10 @@ function arraysDiffer(source1, source2, orderImportant) {
         source2.filter(value => !source1.includes(value)).length > 0);
 }
 
+function escapeSearchTerm(text) {
+    return text.replace(/([a-z_-]):/g, '$1\\:');
+}
+
 module.exports = {
     range:                   range,
     formatUrlParameters:     formatUrlParameters,
@@ -231,4 +235,5 @@ module.exports = {
     splitByWhitespace:       splitByWhitespace,
     arraysDiffer:            arraysDiffer,
     decamelize:              decamelize,
+    escapeSearchTerm:        escapeSearchTerm,
 };
diff --git a/client/js/views/posts_header_view.js b/client/js/views/posts_header_view.js
index 2425f51..04764c1 100644
--- a/client/js/views/posts_header_view.js
+++ b/client/js/views/posts_header_view.js
@@ -21,7 +21,8 @@ class PostsHeaderView extends events.EventTarget {
         views.replaceContent(this._hostNode, template(ctx));
 
         this._queryAutoCompleteControl = new TagAutoCompleteControl(
-            this._queryInputNode, {addSpace: true});
+            this._queryInputNode,
+            {addSpace: true, transform: misc.escapeSearchTerm});
         if (this._massTagInputNode) {
             this._masstagAutoCompleteControl = new TagAutoCompleteControl(
                 this._massTagInputNode, {addSpace: false});
diff --git a/client/js/views/tags_header_view.js b/client/js/views/tags_header_view.js
index cb0489e..8b1b476 100644
--- a/client/js/views/tags_header_view.js
+++ b/client/js/views/tags_header_view.js
@@ -17,7 +17,8 @@ class TagsHeaderView extends events.EventTarget {
         views.replaceContent(this._hostNode, template(ctx));
 
         if (this._queryInputNode) {
-            new TagAutoCompleteControl(this._queryInputNode);
+            new TagAutoCompleteControl(
+                this._queryInputNode, {transform: misc.escapeSearchTerm});
         }
 
         search.searchInputNodeFocusHelper(this._queryInputNode);