diff --git a/src/components/router/appRouter.js b/src/components/router/appRouter.js
index 5688ecd6032..e871448160c 100644
--- a/src/components/router/appRouter.js
+++ b/src/components/router/appRouter.js
@@ -673,6 +673,16 @@ class AppRouter {
             return url;
         }
 
+        if (item === 'tag') {
+            url = `#/list.html?type=tag&tag=${encodeURIComponent(options.tag)}&serverId=${serverId}`;
+
+            if (options.parentId) {
+                url += '&parentId=' + options.parentId;
+            }
+
+            return url;
+        }
+
         if (context !== 'folders' && !itemHelper.isLocalItem(item)) {
             if (item.CollectionType == CollectionType.Movies) {
                 url = `#/movies.html?topParentId=${item.Id}&collectionType=${item.CollectionType}`;
diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js
index 56ef667d537..ae4cc953b6b 100644
--- a/src/controllers/itemDetails/index.js
+++ b/src/controllers/itemDetails/index.js
@@ -1309,8 +1309,12 @@ function renderTags(page, item) {
     }
 
     tags.forEach(tag => {
+        const href = appRouter.getRouteUrl('tag', {
+            tag,
+            serverId: item.ServerId
+        });
         tagElements.push(
-            `<a href="#/search.html?query=${encodeURIComponent(tag)}" class="button-link emby-button" is="emby-linkbutton">`
+            `<a href="${href}" class="button-link emby-button" is="emby-linkbutton">`
             + escapeHtml(tag)
             + '</a>'
         );
diff --git a/src/controllers/list.js b/src/controllers/list.js
index 02da709c034..9df69c4ed11 100644
--- a/src/controllers/list.js
+++ b/src/controllers/list.js
@@ -284,7 +284,8 @@ function getItems(instance, params, item, sortBy, startIndex, limit) {
             Recursive: true,
             IsFavorite: params.IsFavorite === 'true' || null,
             ArtistIds: params.artistId || null,
-            SortBy: sortBy
+            SortBy: sortBy,
+            Tags: params.tag || null
         }));
     }
 
@@ -333,7 +334,7 @@ function getItems(instance, params, item, sortBy, startIndex, limit) {
 }
 
 function getItem(params) {
-    if (params.type === 'Recordings' || params.type === 'Programs' || params.type === 'nextup') {
+    if ([ 'Recordings', 'Programs', 'nextup', 'tag' ].includes(params.type)) {
         return Promise.resolve(null);
     }
 
@@ -726,6 +727,10 @@ class ItemsView {
             if (params.type === 'Video') {
                 return globalize.translate('Videos');
             }
+
+            if (params.tag) {
+                return params.tag;
+            }
         }
 
         function play() {
@@ -1203,7 +1208,7 @@ class ItemsView {
             showTitle = true;
         } else if (showTitle === 'false') {
             showTitle = false;
-        } else if (params.type === 'Programs' || params.type === 'Recordings' || params.type === 'Person' || params.type === 'nextup' || params.type === 'Audio' || params.type === 'MusicAlbum' || params.type === 'MusicArtist') {
+        } else if ([ 'Audio', 'MusicAlbum', 'MusicArtist', 'Person', 'Programs', 'Recordings', 'nextup', 'tag' ].includes(params.type)) {
             showTitle = true;
         } else if (item && item.Type !== 'PhotoAlbum') {
             showTitle = true;
@@ -1220,7 +1225,7 @@ class ItemsView {
         }
 
         return {
-            showTitle: showTitle,
+            showTitle,
             showYear: userSettings.get(basekey + '-showYear') !== 'false',
             imageType: imageType || 'primary',
             viewType: userSettings.get(basekey + '-viewType') || 'images'