diff --git a/assets/img/icons/regexp.svg b/assets/img/icons/regexp.svg
new file mode 100755
index 0000000..514c7b6
--- /dev/null
+++ b/assets/img/icons/regexp.svg
@@ -0,0 +1,7 @@
+<!-- Generated by IcoMoon.io -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="21" height="16" viewBox="0 0 21 16">
+<path d="M14.964 7.134c-0.809-0.467-1.915-0.854-2.865-1.134 0.95-0.28 2.056-0.667 2.865-1.134 0.478-0.276 0.642-0.888 0.366-1.366s-0.888-0.642-1.366-0.366c-0.809 0.467-1.697 1.232-2.415 1.914 0.232-0.963 0.45-2.114 0.45-3.048 0-0.552-0.448-1-1-1s-1 0.448-1 1c0 0.934 0.218 2.086 0.45 3.048-0.717-0.683-1.606-1.447-2.415-1.914-0.478-0.276-1.090-0.112-1.366 0.366s-0.112 1.090 0.366 1.366c0.809 0.467 1.915 0.854 2.865 1.134-0.95 0.28-2.056 0.667-2.865 1.134-0.478 0.276-0.642 0.888-0.366 1.366s0.888 0.642 1.366 0.366c0.809-0.467 1.697-1.232 2.415-1.914-0.232 0.963-0.45 2.114-0.45 3.048 0 0.552 0.448 1 1 1s1-0.448 1-1c0-0.934-0.218-2.086-0.45-3.048 0.717 0.683 1.606 1.447 2.415 1.914 0.478 0.276 1.090 0.112 1.366-0.366s0.112-1.090-0.366-1.366z"></path>
+<path d="M7 13.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path>
+<path d="M0 16l4-16h2l-4 16z"></path>
+<path d="M15 16l4-16h2l-4 16z"></path>
+</svg>
diff --git a/assets/img/icons/regexp2.svg b/assets/img/icons/regexp2.svg
new file mode 100755
index 0000000..341a484
--- /dev/null
+++ b/assets/img/icons/regexp2.svg
@@ -0,0 +1,4 @@
+<!-- Generated by IcoMoon.io -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+<path d="M15.15 0h-11.235c-0.562 0-1.106 0.442-1.21 0.983l-2.688 14.034c-0.104 0.541 0.271 0.983 0.833 0.983h11.235c0.562 0 1.106-0.442 1.21-0.983l2.688-14.034c0.104-0.541-0.271-0.983-0.833-0.983zM11.964 9.134c0.478 0.276 0.642 0.888 0.366 1.366s-0.888 0.642-1.366 0.366c-0.809-0.467-1.697-1.232-2.415-1.914 0.232 0.963 0.45 2.114 0.45 3.048 0 0.552-0.448 1-1 1s-1-0.448-1-1c0-0.934 0.218-2.085 0.45-3.048-0.717 0.683-1.606 1.447-2.415 1.914-0.478 0.276-1.090 0.112-1.366-0.366s-0.112-1.090 0.366-1.366c0.809-0.467 1.915-0.854 2.865-1.134-0.95-0.28-2.056-0.667-2.865-1.134-0.478-0.276-0.642-0.888-0.366-1.366s0.888-0.642 1.366-0.366c0.809 0.467 1.697 1.232 2.415 1.914-0.232-0.963-0.45-2.114-0.45-3.048 0-0.552 0.448-1 1-1s1 0.448 1 1c0 0.934-0.218 2.086-0.45 3.048 0.717-0.683 1.606-1.447 2.415-1.914 0.478-0.276 1.090-0.112 1.366 0.366s0.112 1.090-0.366 1.366c-0.809 0.467-1.915 0.854-2.865 1.134 0.95 0.28 2.056 0.667 2.865 1.134z"></path>
+</svg>
diff --git a/components/alerts/alerts.vue b/components/alerts/alerts.vue
index 3997363..306d145 100644
--- a/components/alerts/alerts.vue
+++ b/components/alerts/alerts.vue
@@ -12,9 +12,60 @@
 			</button>
 		</div>
 
+		<div class="filters">
+			<input
+				v-model="query"
+				type="search"
+				class="input filters-search"
+				placeholder="Search alerts"
+			>
+
+			<div class="filters-filters">
+				<Icon
+					icon="star"
+					title="Only show actor alerts"
+					class="noselect"
+					:class="{ active: filterActors }"
+					@click="filterActors = !filterActors"
+				/>
+
+				<Icon
+					icon="price-tags"
+					title="Only show tag alerts"
+					class="noselect"
+					:class="{ active: filterTags }"
+					@click="filterTags = !filterTags"
+				/>
+
+				<Icon
+					icon="device_hub"
+					title="Only show channel alerts"
+					class="noselect"
+					:class="{ active: filterEntities }"
+					@click="filterEntities = !filterEntities"
+				/>
+
+				<Icon
+					icon="regexp"
+					title="Only show expression alerts"
+					class="noselect"
+					:class="{ active: filterExpressions }"
+					@click="filterExpressions = !filterExpressions"
+				/>
+
+				<Icon
+					icon="target3"
+					title="Only show uncombined alerts"
+					class="noselect uncombined"
+					:class="{ active: filterCombined }"
+					@click="filterCombined = !filterCombined"
+				/>
+			</div>
+		</div>
+
 		<ul class="alerts nolist">
 			<li
-				v-for="alert in alerts"
+				v-for="alert in filteredAlerts"
 				:key="`alert-${alert.id}`"
 				class="alert"
 			>
@@ -168,7 +219,7 @@
 </template>
 
 <script setup>
-import { ref, inject } from 'vue';
+import { ref, computed, inject } from 'vue';
 import { format } from 'date-fns';
 
 import AlertDialog from '#/components/alerts/create.vue';
@@ -181,6 +232,57 @@ const alerts = ref(pageContext.pageProps.alerts);
 const showAlertDialog = ref(false);
 const done = ref(true);
 
+const query = ref('');
+const filterActors = ref(false);
+const filterEntities = ref(false);
+const filterTags = ref(false);
+const filterExpressions = ref(false);
+const filterCombined = ref(false);
+
+const filteredAlerts = computed(() => {
+	const queryRegex = new RegExp(query.value, 'i');
+
+	return alerts.value.filter((alert) => {
+		if (filterActors.value && alert.actors.length === 0) {
+			return false;
+		}
+
+		if (filterEntities.value && alert.entities.length === 0) {
+			return false;
+		}
+
+		if (filterTags.value && alert.tags.length === 0) {
+			return false;
+		}
+
+		if (filterExpressions.value && alert.matches.length === 0) {
+			return false;
+		}
+
+		if (filterCombined.value && [...alert.actors, ...alert.entities, ...alert.tags, ...alert.matches].length > 1) {
+			return false;
+		}
+
+		if (alert.actors.some((actor) => queryRegex.test(actor.name))) {
+			return true;
+		}
+
+		if (alert.tags.some((tag) => queryRegex.test(tag.name))) {
+			return true;
+		}
+
+		if (alert.entities.some((entity) => queryRegex.test(entity.name))) {
+			return true;
+		}
+
+		if (alert.matches.some((match) => queryRegex.test(match.expression))) {
+			return true;
+		}
+
+		return false;
+	});
+});
+
 async function reloadAlerts() {
 	alerts.value = await get('/alerts');
 }
@@ -223,6 +325,37 @@ async function removeAlert(alert) {
 	margin-bottom: 1rem;
 }
 
+.filters {
+	display: flex;
+	align-items: center;
+	padding-left: .5rem;
+	margin-bottom: .5rem;
+
+	.input {
+		margin-right: 1rem;
+	}
+
+	.icon {
+		width: 1.25rem;
+		height: 1.25rem;
+		padding: .25rem .5rem;
+		fill: var(--glass);
+
+		&:hover {
+			fill: var(--primary);
+			cursor: pointer;
+		}
+
+		&.active {
+			fill: var(--primary);
+		}
+	}
+
+	.uncombined {
+		margin-left: .5rem;
+	}
+}
+
 .alert {
 	padding: 0 0 0 .5rem;
 	display: flex;