diff --git a/README.md b/README.md
index c67631be..f4c9a701 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,8 @@ this list is not final and keeps expanding over time. if support for a service y
 | bilibili.com & bilibili.tv     | ✅            | ✅         | ✅         | ➖         | ➖              |
 | dailymotion                    | ✅            | ✅         | ✅         | ✅         | ✅              |
 | instagram posts & reels        | ✅            | ✅         | ✅         | ➖         | ➖              |
-| ok video                       | ✅            | ❌         | ❌         | ✅         | ✅              |
+| loom                           | ✅            | ❌         | ✅         | ✅         | ➖              |
+| ok video                       | ✅            | ❌         | ✅         | ✅         | ✅              |
 | pinterest                      | ✅            | ✅         | ✅         | ➖         | ➖              |
 | reddit                         | ✅            | ✅         | ✅         | ❌         | ❌              |
 | rutube                         | ✅            | ✅         | ✅         | ✅         | ✅              |
@@ -31,7 +32,7 @@ this list is not final and keeps expanding over time. if support for a service y
 | twitter/x                      | ✅            | ✅         | ✅         | ➖         | ➖              |
 | vimeo                          | ✅            | ✅         | ✅         | ✅         | ✅              |
 | vine archive                   | ✅            | ✅         | ✅         | ➖         | ➖              |
-| vk videos & clips              | ✅            | ❌         | ❌         | ✅         | ✅              |
+| vk videos & clips              | ✅            | ❌         | ✅         | ✅         | ✅              |
 | youtube videos, shorts & music | ✅            | ✅         | ✅         | ✅         | ✅              |
 
 | emoji   | meaning                 |
diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js
index c3091709..3e38c4db 100644
--- a/src/modules/processing/match.js
+++ b/src/modules/processing/match.js
@@ -24,6 +24,7 @@ import streamable from "./services/streamable.js";
 import twitch from "./services/twitch.js";
 import rutube from "./services/rutube.js";
 import dailymotion from "./services/dailymotion.js";
+import loom from "./services/loom.js";
 
 let freebind;
 
@@ -187,6 +188,11 @@ export default async function(host, patternMatch, lang, obj) {
             case "dailymotion":
                 r = await dailymotion(patternMatch);
                 break;
+            case "loom":
+                r = await loom({
+                    id: patternMatch.id
+                });
+                break;
             default:
                 return createResponse("error", {
                     t: loc(lang, 'ErrorUnsupported')
diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js
index 42a35f1a..f7ed3da9 100644
--- a/src/modules/processing/matchActionDecider.js
+++ b/src/modules/processing/matchActionDecider.js
@@ -129,6 +129,7 @@ export default function(r, host, userFormat, isAudioOnly, lang, isAudioMuted, di
                 case "tumblr":
                 case "pinterest":
                 case "streamable":
+                case "loom":
                     responseType = "redirect";
                     break;
             }
diff --git a/src/modules/processing/services/loom.js b/src/modules/processing/services/loom.js
new file mode 100644
index 00000000..ecb6c534
--- /dev/null
+++ b/src/modules/processing/services/loom.js
@@ -0,0 +1,39 @@
+import { genericUserAgent } from "../../config.js";
+
+export default async function({ id }) {
+    const gql = await fetch(`https://www.loom.com/api/campaigns/sessions/${id}/transcoded-url`, {
+        method: "POST",
+        headers: {
+            "user-agent": genericUserAgent,
+            origin: "https://www.loom.com",
+            referer: `https://www.loom.com/share/${id}`,
+            cookie: `loom_referral_video=${id};`,
+
+            "apollographql-client-name": "web",
+            "apollographql-client-version": "14c0b42",
+            "x-loom-request-source": "loom_web_14c0b42",
+        },
+        body: JSON.stringify({
+            force_original: false,
+            password: null,
+            anonID: null,
+            deviceID: null
+        })
+    })
+    .then(r => r.status === 200 ? r.json() : false)
+    .catch(() => {});
+
+    if (!gql) return { error: 'ErrorEmptyDownload' };
+
+    const videoUrl = gql?.url;
+
+    if (videoUrl?.includes('.mp4?')) {
+        return {
+            urls: videoUrl,
+            filename: `loom_${id}.mp4`,
+            audioFilename: `loom_${id}_audio`
+        }
+    }
+
+    return { error: 'ErrorEmptyDownload' }
+}
diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json
index c0a11817..ae4cd9f0 100644
--- a/src/modules/processing/servicesConfig.json
+++ b/src/modules/processing/servicesConfig.json
@@ -1,5 +1,5 @@
 {
-    "audioIgnore": ["vk", "ok"],
+    "audioIgnore": ["vk", "ok", "loom"],
     "hlsExceptions": ["dailymotion", "vimeo", "rutube"],
     "config": {
         "bilibili": {
@@ -112,6 +112,11 @@
             "alias": "dailymotion videos",
             "patterns": ["video/:id"],
             "enabled": true
+        },
+        "loom": {
+            "alias": "loom videos",
+            "patterns": ["share/:id"],
+            "enabled": true
         }
     }
 }
diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js
index a4770c17..ddeea31f 100644
--- a/src/modules/processing/servicesPatternTesters.js
+++ b/src/modules/processing/servicesPatternTesters.js
@@ -8,7 +8,10 @@ export const testers = {
     "instagram": (patternMatch) =>
         patternMatch.postId?.length <= 12
         || (patternMatch.username?.length <= 30 && patternMatch.storyId?.length <= 24),
-    
+
+    "loom": (patternMatch) =>
+        patternMatch.id?.length <= 32,
+
     "ok": (patternMatch) =>
         patternMatch.id?.length <= 16,
 
@@ -29,7 +32,7 @@ export const testers = {
 
     "streamable": (patternMatch) =>
         patternMatch.id?.length === 6,
-    
+
     "tiktok": (patternMatch) =>
         patternMatch.postId?.length <= 21 || patternMatch.id?.length <= 13,
 
diff --git a/src/test/tests.json b/src/test/tests.json
index 36044cde..501ac2c0 100644
--- a/src/test/tests.json
+++ b/src/test/tests.json
@@ -1131,5 +1131,34 @@
             "code": 200,
             "status": "stream"
         }
+    }],
+    "loom": [{
+        "name": "1080p video",
+        "url": "https://www.loom.com/share/313bf71d20ca47b2a35b6634cefdb761",
+        "params": {},
+        "expected": {
+            "code": 200,
+            "status": "redirect"
+        }
+    }, {
+        "name": "1080p video (muted)",
+        "url": "https://www.loom.com/share/313bf71d20ca47b2a35b6634cefdb761",
+        "params": {
+            "isAudioMuted": true
+        },
+        "expected": {
+            "code": 200,
+            "status": "stream"
+        }
+    }, {
+        "name": "1080p video (audio only)",
+        "url": "https://www.loom.com/share/313bf71d20ca47b2a35b6634cefdb761",
+        "params": {
+            "isAudioOnly": true
+        },
+        "expected": {
+            "code": 200,
+            "status": "stream"
+        }
     }]
 }