diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php
index 3342cad..084dc55 100644
--- a/src/wp-admin/includes/ajax-actions.php
+++ b/src/wp-admin/includes/ajax-actions.php
@@ -99,62 +99,6 @@ function wp_ajax_fetch_list() {
 }
 
 /**
- * Ajax handler for tag search.
- *
- * @since 3.1.0
- */
-function wp_ajax_ajax_tag_search() {
-	if ( ! isset( $_GET['tax'] ) ) {
-		wp_die( 0 );
-	}
-
-	$taxonomy = sanitize_key( $_GET['tax'] );
-	$tax = get_taxonomy( $taxonomy );
-	if ( ! $tax ) {
-		wp_die( 0 );
-	}
-
-	if ( ! current_user_can( $tax->cap->assign_terms ) ) {
-		wp_die( -1 );
-	}
-
-	$s = wp_unslash( $_GET['q'] );
-
-	$comma = _x( ',', 'tag delimiter' );
-	if ( ',' !== $comma )
-		$s = str_replace( $comma, ',', $s );
-	if ( false !== strpos( $s, ',' ) ) {
-		$s = explode( ',', $s );
-		$s = $s[count( $s ) - 1];
-	}
-	$s = trim( $s );
-
-	/**
-	 * Filters the minimum number of characters required to fire a tag search via Ajax.
-	 *
-	 * @since 4.0.0
-	 *
-	 * @param int         $characters The minimum number of characters required. Default 2.
-	 * @param WP_Taxonomy $tax        The taxonomy object.
-	 * @param string      $s          The search term.
-	 */
-	$term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $tax, $s );
-
-	/*
-	 * Require $term_search_min_chars chars for matching (default: 2)
-	 * ensure it's a non-negative, non-zero integer.
-	 */
-	if ( ( $term_search_min_chars == 0 ) || ( strlen( $s ) < $term_search_min_chars ) ){
-		wp_die();
-	}
-
-	$results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) );
-
-	echo join( $results, "\n" );
-	wp_die();
-}
-
-/**
  * Ajax handler for compression testing.
  *
  * @since 3.1.0
diff --git a/src/wp-admin/includes/deprecated.php b/src/wp-admin/includes/deprecated.php
index 2bf25d3..9cd4653 100644
--- a/src/wp-admin/includes/deprecated.php
+++ b/src/wp-admin/includes/deprecated.php
@@ -1396,3 +1396,55 @@ function post_form_autocomplete_off() {
 		echo ' autocomplete="off"';
 	}
 }
+
+/**
+ * Ajax handler for tag search.
+ *
+ * @deprecated 4.8.0 Use the REST API tags endpoint instead.
+ *
+ * @since 3.1.0
+ */
+function wp_ajax_ajax_tag_search() {
+	_deprecated_function( __FUNCTION__, '4.8', '/wp-json/wp/v2/tags' );
+
+	if ( ! isset( $_GET['tax'] ) ) {
+		wp_die( 0 );
+	}
+
+	$taxonomy = sanitize_key( $_GET['tax'] );
+	$tax = get_taxonomy( $taxonomy );
+	if ( ! $tax ) {
+		wp_die( 0 );
+	}
+
+	if ( ! current_user_can( $tax->cap->assign_terms ) ) {
+		wp_die( -1 );
+	}
+
+	$s = wp_unslash( $_GET['q'] );
+
+	$comma = _x( ',', 'tag delimiter' );
+	if ( ',' !== $comma )
+		$s = str_replace( $comma, ',', $s );
+	if ( false !== strpos( $s, ',' ) ) {
+		$s = explode( ',', $s );
+		$s = $s[count( $s ) - 1];
+	}
+	$s = trim( $s );
+
+	/** This filter is documented in wp-includes/script-loader.php */
+	$term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $tax, $s );
+
+	/*
+	 * Require $term_search_min_chars chars for matching (default: 2)
+	 * ensure it's a non-negative, non-zero integer.
+	 */
+	if ( ( $term_search_min_chars == 0 ) || ( strlen( $s ) < $term_search_min_chars ) ){
+		wp_die();
+	}
+
+	$results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) );
+
+	echo join( $results, "\n" );
+	wp_die();
+}
diff --git a/src/wp-admin/js/tags-suggest.js b/src/wp-admin/js/tags-suggest.js
index 6465cc9..d0399a0 100644
--- a/src/wp-admin/js/tags-suggest.js
+++ b/src/wp-admin/js/tags-suggest.js
@@ -6,7 +6,6 @@
 		return;
 	}
 
-	var tempID = 0;
 	var separator = window.tagsSuggestL10n.tagDelimiter || ',';
 
 	function split( val ) {
@@ -53,33 +52,14 @@
 
 				term = getLast( request.term );
 
-				$.get( window.ajaxurl, {
-					action: 'ajax-tag-search',
-					tax: taxonomy,
-					q: term
+				$.get( window.tagsSuggestL10n.restURL, {
+					taxonomy: taxonomy,
+					search: term
 				} ).always( function() {
 					$element.removeClass( 'ui-autocomplete-loading' ); // UI fails to remove this sometimes?
 				} ).done( function( data ) {
-					var tagName;
-					var tags = [];
-
-					if ( data ) {
-						data = data.split( '\n' );
-
-						for ( tagName in data ) {
-							var id = ++tempID;
-
-							tags.push({
-								id: id,
-								name: data[tagName]
-							});
-						}
-
-						cache = tags;
-						response( tags );
-					} else {
-						response( tags );
-					}
+					cache = data;
+					response( data );
 				} );
 
 				last = request.term;
@@ -118,7 +98,7 @@
 			close: function() {
 				$element.attr( 'aria-expanded', 'false' );
 			},
-			minLength: 2,
+			minLength: window.tagsSuggestL10n.minChars,
 			position: {
 				my: 'left top+2',
 				at: 'left bottom',
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php
index def438c..51f51a0 100644
--- a/src/wp-includes/script-loader.php
+++ b/src/wp-includes/script-loader.php
@@ -547,6 +547,16 @@ function wp_default_scripts( &$scripts ) {
 			'termSelected' => __( 'Term selected.' ),
 			'termAdded'    => __( 'Term added.' ),
 			'termRemoved'  => __( 'Term removed.' ),
+			'restURL'      => rest_url( '/wp/v2/tags' ),
+
+			/**
+			 * Filters the minimum number of characters required to fire a tag search via Ajax.
+			 *
+			 * @since 4.0.0
+			 *
+			 * @param int         $characters The minimum number of characters required. Default 2.
+			 */
+			'minChars'     => (int) apply_filters( 'term_search_min_chars', 2 ),
 		) );
 
 		$scripts->add( 'post', "/wp-admin/js/post$suffix.js", array( 'suggest', 'wp-lists', 'postbox', 'tags-box', 'underscore', 'word-count', 'wp-a11y' ), false, 1 );
