diff --git a/src/wp-includes/icons.php b/src/wp-includes/icons.php
new file mode 100644
index 0000000000000..33f6498d50f23
--- /dev/null
+++ b/src/wp-includes/icons.php
@@ -0,0 +1,68 @@
+get_registered_icon( $name );
+ if ( is_null( $icon ) ) {
+ return '';
+ }
+
+ $svg = $icon['content'];
+ if ( empty( $svg ) ) {
+ return '';
+ }
+
+ $args = wp_parse_args(
+ $args,
+ array(
+ 'size' => 24,
+ 'class' => '',
+ 'label' => '',
+ )
+ );
+
+ $processor = new WP_HTML_Tag_Processor( $svg );
+ if ( ! $processor->next_tag( 'svg' ) ) {
+ return '';
+ }
+
+ $processor->set_attribute( 'width', (string) $args['size'] );
+ $processor->set_attribute( 'height', (string) $args['size'] );
+ $processor->add_class( 'wp-icon' );
+
+ if ( ! empty( $args['class'] ) ) {
+ $processor->add_class( $args['class'] );
+ }
+
+ if ( ! empty( $args['label'] ) ) {
+ $processor->set_attribute( 'role', 'img' );
+ $processor->set_attribute( 'aria-label', $args['label'] );
+ } else {
+ $processor->set_attribute( 'aria-hidden', 'true' );
+ }
+
+ return $processor->get_updated_html();
+}
diff --git a/src/wp-settings.php b/src/wp-settings.php
index b2736bddadc3c..ac831c864c285 100644
--- a/src/wp-settings.php
+++ b/src/wp-settings.php
@@ -297,6 +297,7 @@
require ABSPATH . WPINC . '/class-wp-connector-registry.php';
require ABSPATH . WPINC . '/connectors.php';
require ABSPATH . WPINC . '/class-wp-icons-registry.php';
+require ABSPATH . WPINC . '/icons.php';
require ABSPATH . WPINC . '/widgets.php';
require ABSPATH . WPINC . '/class-wp-widget.php';
require ABSPATH . WPINC . '/class-wp-widget-factory.php';
diff --git a/tests/phpunit/tests/icons/wpGetIcon.php b/tests/phpunit/tests/icons/wpGetIcon.php
new file mode 100644
index 0000000000000..33911b1b38faf
--- /dev/null
+++ b/tests/phpunit/tests/icons/wpGetIcon.php
@@ -0,0 +1,97 @@
+assertStringStartsWith( '', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_returns_empty_string_for_unknown_icon() {
+ $output = wp_get_icon( 'this-icon-does-not-exist' );
+ $this->assertSame( '', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_default_attributes() {
+ $output = wp_get_icon( 'core/plus' );
+ // WP_HTML_Tag_Processor lowercases attribute names.
+ $this->assertStringContainsString( 'viewbox="0 0 24 24"', $output );
+ $this->assertStringContainsString( 'width="24"', $output );
+ $this->assertStringContainsString( 'height="24"', $output );
+ $this->assertStringContainsString( 'class="wp-icon"', $output );
+ $this->assertStringContainsString( 'aria-hidden="true"', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_custom_size() {
+ $output = wp_get_icon( 'core/plus', array( 'size' => 32 ) );
+ $this->assertStringContainsString( 'width="32"', $output );
+ $this->assertStringContainsString( 'height="32"', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_custom_class() {
+ $output = wp_get_icon( 'core/plus', array( 'class' => 'my-button-icon' ) );
+ $this->assertStringContainsString( 'class="wp-icon my-button-icon"', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_with_label() {
+ $output = wp_get_icon( 'core/plus', array( 'label' => 'Add item' ) );
+ $this->assertStringContainsString( 'role="img"', $output );
+ $this->assertStringContainsString( 'aria-label="Add item"', $output );
+ $this->assertStringNotContainsString( 'aria-hidden', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_without_label_is_hidden() {
+ $output = wp_get_icon( 'core/plus' );
+ $this->assertStringContainsString( 'aria-hidden="true"', $output );
+ $this->assertStringNotContainsString( 'role="img"', $output );
+ $this->assertStringNotContainsString( 'aria-label', $output );
+ }
+
+ /**
+ * @ticket 64847
+ */
+ public function test_wp_get_icon_contains_svg_content() {
+ $output = wp_get_icon( 'core/plus' );
+ $this->assertStringContainsString( ' '">' ) );
+ $this->assertStringNotContainsString( '