diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3ea4358..446f59a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
* Builtin Prosody, Share chat url: ability to show/hide the scrollbar in readonly mode.
* Builtin Prosody: display Peertube users avatars.
+* Builtin Prosody: display random avatars for anonymous users.
### Minor changes and fixes
diff --git a/package.json b/package.json
index feec7814..6a64abdc 100644
--- a/package.json
+++ b/package.json
@@ -83,7 +83,7 @@
"clean:light": "rm -rf dist/*",
"prepare": "npm run clean && npm run build",
"build:converse": "bash conversejs/build-conversejs.sh",
- "build:images": "mkdir -p dist/client/images && npx svgo -f public/images/ -o dist/client/images/",
+ "build:images": "mkdir -p dist/client/images && npx svgo -f public/images/ -o dist/client/images/ && npx svgo -f public/images/avatars/ -o dist/server/avatars/",
"build:webpack": "webpack --mode=production",
"build:server": "npx tsc --build server/tsconfig.json",
"build:serverconverse": "mkdir -p dist/server/conversejs && cp conversejs/index.html dist/server/conversejs/",
diff --git a/prosody-modules/mod_random_vcard_peertubelivechat/README.md b/prosody-modules/mod_random_vcard_peertubelivechat/README.md
new file mode 100644
index 00000000..05a3f178
--- /dev/null
+++ b/prosody-modules/mod_random_vcard_peertubelivechat/README.md
@@ -0,0 +1,5 @@
+# mod_random_vcard_peertubelivechat
+
+This module is a custom module that allows Prosody to generate random vCards avatars for anonymous users.
+
+This module is part of peertube-plugin-livechat, and is under the same LICENSE.
diff --git a/prosody-modules/mod_random_vcard_peertubelivechat/mod_random_vcard_peertubelivechat.lua b/prosody-modules/mod_random_vcard_peertubelivechat/mod_random_vcard_peertubelivechat.lua
new file mode 100644
index 00000000..e65574b3
--- /dev/null
+++ b/prosody-modules/mod_random_vcard_peertubelivechat/mod_random_vcard_peertubelivechat.lua
@@ -0,0 +1,55 @@
+local st = require "util.stanza";
+local path = require "util.paths";
+local b64 = require "util.encodings".base64.encode;
+local jid = require "util.jid";
+
+module:add_feature("vcard-temp");
+
+local avatars_dir = assert(module:get_option_string("peertubelivechat_random_vcard_avatars_path", nil), "'peertubelivechat_random_vcard_avatars_path' is a required option");
+local avatars = {};
+local function load_avatar(filename)
+ local file = assert(io.open(path.join(avatars_dir, filename), "r"));
+ local result = {
+ type = 'image/svg+xml',
+ content = b64(file:read("*a"))
+ };
+ file:close();
+ return result;
+end
+local AVATARS_COUNT = 10;
+for i = 1, AVATARS_COUNT do
+ avatars[i] = load_avatar(i .. '.svg');
+end
+
+module:hook("iq-get/bare/vcard-temp:vCard", function (event)
+ local origin, stanza = event.origin, event.stanza;
+
+ -- module:log("debug", "From '%s', To '%s', username '%s'.", stanza.attr.from, stanza.attr.to, origin.username);
+
+ local who = jid.split(stanza.attr.to) or origin.username;
+ if not who then
+ module:log("debug", "No who, will not generate random vCard");
+ origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
+ return true;
+ end
+
+ module:log("debug", "random vCard request for %s", who);
+
+ local n = 1;
+ for c in who:gmatch"." do
+ n = math.fmod(n + c:byte(), AVATARS_COUNT) + 1;
+ end
+
+ module:log("debug", "%s will have the avatar number %s.", who, n);
+
+ local vcard_temp = st.stanza("vCard", { xmlns = "vcard-temp" });
+ -- vcard_temp:text_tag("FN", who);
+ -- vcard_temp:text_tag("NICKNAME", who);
+ vcard_temp:tag("PHOTO");
+ vcard_temp:text_tag("TYPE", avatars[n].type);
+ vcard_temp:text_tag("BINVAL", avatars[n].content);
+ vcard_temp:up();
+
+ origin.send(st.reply(stanza):add_child(vcard_temp));
+ return true;
+end);
diff --git a/public/images/avatars/1.svg b/public/images/avatars/1.svg
new file mode 100644
index 00000000..8266249a
--- /dev/null
+++ b/public/images/avatars/1.svg
@@ -0,0 +1,297 @@
+
+
diff --git a/public/images/avatars/10.svg b/public/images/avatars/10.svg
new file mode 100644
index 00000000..6049d1bc
--- /dev/null
+++ b/public/images/avatars/10.svg
@@ -0,0 +1,340 @@
+
+
diff --git a/public/images/avatars/2.svg b/public/images/avatars/2.svg
new file mode 100644
index 00000000..0fc6f45a
--- /dev/null
+++ b/public/images/avatars/2.svg
@@ -0,0 +1,297 @@
+
+
diff --git a/public/images/avatars/3.svg b/public/images/avatars/3.svg
new file mode 100644
index 00000000..d45689ed
--- /dev/null
+++ b/public/images/avatars/3.svg
@@ -0,0 +1,319 @@
+
+
diff --git a/public/images/avatars/4.svg b/public/images/avatars/4.svg
new file mode 100644
index 00000000..eeac56ef
--- /dev/null
+++ b/public/images/avatars/4.svg
@@ -0,0 +1,320 @@
+
+
diff --git a/public/images/avatars/5.svg b/public/images/avatars/5.svg
new file mode 100644
index 00000000..27269113
--- /dev/null
+++ b/public/images/avatars/5.svg
@@ -0,0 +1,282 @@
+
+
diff --git a/public/images/avatars/6.svg b/public/images/avatars/6.svg
new file mode 100644
index 00000000..08e7e731
--- /dev/null
+++ b/public/images/avatars/6.svg
@@ -0,0 +1,282 @@
+
+
diff --git a/public/images/avatars/7.svg b/public/images/avatars/7.svg
new file mode 100644
index 00000000..6e1bfb14
--- /dev/null
+++ b/public/images/avatars/7.svg
@@ -0,0 +1,312 @@
+
+
diff --git a/public/images/avatars/8.svg b/public/images/avatars/8.svg
new file mode 100644
index 00000000..94f2d519
--- /dev/null
+++ b/public/images/avatars/8.svg
@@ -0,0 +1,312 @@
+
+
diff --git a/public/images/avatars/9.svg b/public/images/avatars/9.svg
new file mode 100644
index 00000000..57058a16
--- /dev/null
+++ b/public/images/avatars/9.svg
@@ -0,0 +1,340 @@
+
+
diff --git a/server/lib/prosody/config.ts b/server/lib/prosody/config.ts
index 5c5e4785..01f579ec 100644
--- a/server/lib/prosody/config.ts
+++ b/server/lib/prosody/config.ts
@@ -60,7 +60,8 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise