diff --git a/services/raycast/installs.service.js b/services/raycast/installs.service.js
new file mode 100644
index 0000000000000000000000000000000000000000..9bbde6bcf4c83936133848be9be60283edc8420d
--- /dev/null
+++ b/services/raycast/installs.service.js
@@ -0,0 +1,55 @@
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, pathParams } from '../index.js'
+import { renderDownloadsBadge } from '../downloads.js'
+
+const schema = Joi.object({
+  download_count: nonNegativeInteger,
+}).required()
+
+export default class RaycastInstalls extends BaseJsonService {
+  static category = 'downloads'
+
+  static route = {
+    base: 'raycast/dt',
+    pattern: ':user/:extension',
+  }
+
+  static openApi = {
+    '/raycast/dt/{user}/{extension}': {
+      get: {
+        summary: 'Raycast extension downloads count',
+        parameters: pathParams(
+          { name: 'user', example: 'Fatpandac' },
+          { name: 'extension', example: 'bilibili' },
+        ),
+      },
+    },
+  }
+
+  static render({ downloads }) {
+    return renderDownloadsBadge({ downloads })
+  }
+
+  async fetch({ user, extension }) {
+    return this._requestJson({
+      schema,
+      url: `https://www.raycast.com/api/v1/extensions/${user}/${extension}`,
+      httpErrors: {
+        404: 'user/extension not found',
+      },
+    })
+  }
+
+  transform(json) {
+    const downloads = json.download_count
+
+    return { downloads }
+  }
+
+  async handle({ user, extension }) {
+    const json = await this.fetch({ user, extension })
+    const { downloads } = this.transform(json)
+    return this.constructor.render({ downloads })
+  }
+}
diff --git a/services/raycast/installs.tester.js b/services/raycast/installs.tester.js
new file mode 100644
index 0000000000000000000000000000000000000000..e6e8e957f04933b436dbd24fb216fb5700cefa28
--- /dev/null
+++ b/services/raycast/installs.tester.js
@@ -0,0 +1,30 @@
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+
+export const t = await createServiceTester()
+
+t.create('installs (invalid user)')
+  .get('/fatpandac/bilibili.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'user/extension not found',
+  })
+
+t.create('installs (not existing extension)')
+  .get('/Fatpandac/safdsaklfhe.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'user/extension not found',
+  })
+
+t.create('installs (not existing user and extension)')
+  .get('/fatpandac/safdsaklfhe.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'user/extension not found',
+  })
+
+t.create('installs (valid)').get('/Fatpandac/bilibili.json').expectBadge({
+  label: 'downloads',
+  message: isMetric,
+})