diff --git a/frontend/src/components/filter/Form.vue b/frontend/src/components/filter/Form.vue
index bd55fe9..fcff5a0 100644
--- a/frontend/src/components/filter/Form.vue
+++ b/frontend/src/components/filter/Form.vue
@@ -241,6 +241,26 @@
                v-model="newFilter.description"
                :disabled="disabled" />
       </div>
+
+      <div class="container ids-container">
+        <label for="ids">
+          <p class="title">
+          <font-awesome-icon icon="fas fa-tag" />
+            Point IDs
+          </p>
+
+          <p class="help">
+            Comma-separated list of point IDs to filter by
+          </p>
+        </label>
+
+        <input type="text"
+               id="ids"
+               name="ids"
+               placeholder="Filter by point IDs"
+               v-model="newFilter.ids"
+               :disabled="disabled" />
+      </div>
     </main>
 
     <footer>
@@ -516,6 +536,10 @@ $footer-height: 3.5em;
         width: 50%;
       }
 
+      .title {
+        text-align: center;
+      }
+
       label {
         margin-bottom: 0.25em;
         @include until(tablet) {
diff --git a/frontend/src/models/LocationQuery.ts b/frontend/src/models/LocationQuery.ts
index 6026947..0e0f1e8 100644
--- a/frontend/src/models/LocationQuery.ts
+++ b/frontend/src/models/LocationQuery.ts
@@ -6,6 +6,7 @@ class LocationQuery {
   public deviceId: Optional<string> = null;
   public startDate: Optional<Date> = null;
   public endDate: Optional<Date> = null;
+  public ids: Optional<number[]> = null;
   public minId: Optional<number> = null;
   public maxId: Optional<number> = null;
   public minLatitude: Optional<number> = null;
@@ -25,6 +26,7 @@ class LocationQuery {
     deviceId?: Optional<string>;
     startDate?: Optional<Date>;
     endDate?: Optional<Date>;
+    ids?: Optional<number[] | string>;
     minId?: Optional<number>;
     maxId?: Optional<number>;
     minLatitude?: Optional<number>;
@@ -43,6 +45,7 @@ class LocationQuery {
     this.deviceId = data.deviceId || this.deviceId;
     this.startDate = data.startDate || this.startDate;
     this.endDate = data.endDate || this.endDate;
+    this.ids = data.ids ? (Array.isArray(data.ids) ? data.ids : data.ids.split(/\s*,\s*/).map(Number)) : this.ids;
     this.minId = data.minId || this.minId;
     this.maxId = data.maxId || this.maxId;
     this.minLatitude = data.minLatitude || this.minLatitude;
diff --git a/src/requests/LocationRequest.ts b/src/requests/LocationRequest.ts
index a1bb7c8..45f1081 100644
--- a/src/requests/LocationRequest.ts
+++ b/src/requests/LocationRequest.ts
@@ -13,6 +13,7 @@ class LocationRequest {
   offset: Optional<number> = null;
   startDate: Optional<Date> = null;
   endDate: Optional<Date> = null;
+  ids: Optional<number[]> = null;
   minId: Optional<number> = null;
   maxId: Optional<number> = null;
   minLatitude: Optional<number> = null;
@@ -33,6 +34,7 @@ class LocationRequest {
     offset?: number;
     startDate?: Date;
     endDate?: Date;
+    ids?: number[] | string;
     minId?: number;
     maxId?: number;
     minLatitude?: number;
@@ -64,6 +66,15 @@ class LocationRequest {
     this.description = req.description;
     this.orderBy = req.orderBy || this.orderBy;
     this.order = (req.order || this.order).toUpperCase() as Order;
+
+    const ids = typeof req.ids === 'string' ? req.ids.split(/\s*,\s*/) : req.ids;
+    this.ids = (ids || []).map((id: any) => {
+      const numId = parseInt(id);
+      if (isNaN(numId)) {
+        throw new ValidationError(`Invalid value for ids: ${id}`);
+      }
+      return numId;
+    });
   }
 
   private initNumber(key: string, req: any, parser: (s: string) => number = parseInt): void {
@@ -89,6 +100,16 @@ class LocationRequest {
     let queryMap: any = {};
     const where: any = {};
 
+    if (this.ids?.length) {
+      queryMap.where = {
+        [db.locationTableColumns.id || 'id']: {[Op.in]: this.ids},
+      };
+
+      queryMap.order = [[db.locationTableColumns.timestamp || 'timestamp', this.order.toUpperCase()]];
+      // If we have ids, we don't need any other filters
+      return queryMap;
+    }
+
     if (this.limit != null) {
       queryMap.limit = this.limit;
     }