Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision c4b24b3124b1464cef50b076ef0dee1b96d5f00c)
+++ src/services/ActivityPubService.js	(revision 9c9a3d96eb8e158f6fe12c09a790663c76a14afe)
@@ -3473,4 +3473,17 @@
       return out.length ? out.slice(0, 8) : undefined;
     })(),
+    // FEP-9098: de custom emoji van het antwoord (":shortcode:" -> plaatje).
+    // Zonder deze tags rendert een reply van een Mastodon-account zijn emoji
+    // als kale tekst (Barts punt, 8-8). Alleen naam + geschoond icoon-adres
+    // gaan door; de rest van de vreemde tag-array blijft achter.
+    tag: (() => {
+      const j = extractEmojiTags(o.tag);
+      if (!j) return undefined;
+      const out = JSON.parse(j)
+        .map((t) => ({ type: 'Emoji', name: t.name, icon: { type: 'Image', url: safeUrl(t.icon && (t.icon.url || (Array.isArray(t.icon) && t.icon[0] && t.icon[0].url))) } }))
+        .filter((t) => t.icon.url)
+        .slice(0, 30);
+      return out.length ? out : undefined;
+    })(),
     'shaer:author': actorInfo(authors.get(actorUri), actorUri),
   })).sort((a, b) => String(a.published || '').localeCompare(String(b.published || '')));
Index: test/thread.test.js
===================================================================
--- test/thread.test.js	(revision c4b24b3124b1464cef50b076ef0dee1b96d5f00c)
+++ test/thread.test.js	(revision 9c9a3d96eb8e158f6fe12c09a790663c76a14afe)
@@ -41,5 +41,12 @@
 const antwoorden = [
   reply(1, VREEMDE, '<p>Hoi! <script>alert(1)</script></p>', '2026-08-01T10:00:00Z'),
-  reply(2, TANTE, '<p>Dag lieverd</p>', '2026-08-01T09:00:00Z'),
+  { ...reply(2, TANTE, '<p>Dag lieverd :hartje:</p>', '2026-08-01T09:00:00Z'),
+    // FEP-9098 zoals Mastodon hem stuurt, plus een niet-Emoji-tag en een
+    // emoji zonder bruikbaar icoon: alleen de echte hoort erdoor te komen.
+    tag: [
+      { type: 'Emoji', name: ':hartje:', icon: { type: 'Image', url: 'https://203.0.113.20/emoji/hartje.png' } },
+      { type: 'Emoji', name: ':kapot:', icon: {} },
+      { type: 'Hashtag', name: '#muziek' },
+    ] },
   reply(3, GEBLOKT, '<p>naar bericht</p>', '2026-08-01T11:00:00Z'),
 ];
@@ -70,4 +77,11 @@
   assert.equal(uit.hidden, 0);
   assert.ok(uit.notes.every((n) => n.attributedTo !== GEBLOKT));
+  // FEP-9098: alleen de echte emoji komt door -- niet de hashtag, niet de
+  // emoji zonder icoon -- en het icoon-adres is geschoond.
+  const tags = uit.notes[0].tag;
+  assert.equal(tags.length, 1);
+  assert.equal(tags[0].name, ':hartje:');
+  assert.equal(tags[0].icon.url, 'https://203.0.113.20/emoji/hartje.png');
+  assert.ok(!uit.notes[1].tag, 'een antwoord zonder emoji draagt geen tag-veld');
 });
 
