Element Web
Glossy Matrix client for the web and desktop
Element Web is the flagship Matrix client, providing a polished interface for chat, voice, and video over the Matrix protocol. It can be self-hosted alongside a homeserver for a fully owned communication stack.
Key features
- Full-featured Matrix client
- End-to-end encryption
- Voice and video calls
- Customizable branding
Pros & cons
Strengths
- Most mature Matrix client
- Active development
Trade-offs
- Heavier than minimal clients
- Best paired with own homeserver
Element Web replaces
Last reviewed Aug 26, 2026 · 807 words
Serve Element Web from a different hostname than your homeserver. That is the one rule the project's own documentation is loudest about, and the one new Matrix operators break most often: Element on chat.example.com, Synapse on matrix.example.com, never both on the same origin. A homeserver serves user-uploaded content, and a web client sharing that origin gives any uploaded HTML file a path to your session. Get that right and the rest of hosting Element is 128 MB of RAM and one JSON file.
The client is the easy tenth of a Matrix stack
Element Web is static files. An nginx process inside the container serves them, your browser runs them, and every hard part of Matrix lives elsewhere: in the homeserver (Synapse for the full feature set, Conduit if you want something that idles in well under 100 MB), in federation, and in the TURN server for calls. So the catalogue's "Easy" rating is accurate for this component and misleading for the project you are actually undertaking, which is running a homeserver. Budget an evening for Element and a weekend for the rest of the Matrix category. The 128 MB in the catalogue is generous, too: the nginx in that container idles at a fraction of it, and the real memory cost of Element is in the browser tab, which on a busy account with many encrypted rooms can reach several hundred megabytes.
Two files and you are serving it
services:
element:
image: vectorim/element-web:latest
ports:
- "8080:80"
volumes:
- ./config.json:/app/config.json:ro
restart: unless-stopped
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.example.com",
"server_name": "example.com"
}
},
"disable_custom_urls": true,
"disable_guests": true,
"brand": "Example Chat"
}
Put a reverse proxy with TLS in front of port 8080; Element needs a secure context for its encryption code, like any app built on the Web Crypto API. default_server_config makes your homeserver the preselected option on the login screen, disable_custom_urls removes the "other homeserver" field so your users cannot wander off, and disable_guests closes guest access. Those three keys are most of what people mean by "our own Element". The rest of config.json is documented in the repository and can stay at defaults. Element fetches the file on page load rather than at container start, so applying a change is a restart of the container plus a hard refresh in the browser; if an edit seems to have no effect, the browser cache is the usual reason.
Voice and video are a separate project
One-to-one calls in Element use WebRTC, and WebRTC across NAT needs a TURN relay. Without one, calls between two people on the same LAN work and calls between anyone else fail silently after ringing, which is a maddening thing to debug. Run coturn with a shared secret, hand that secret to Synapse in its turn_uris and turn_shared_secret settings, and open UDP 3478 plus a relay port range on the firewall. Group calls go through Element Call, which is yet another service. None of this is Element Web's fault, but people install the client, see the call button, and assume it will work.
Why bother when app.element.io exists
The hosted client at app.element.io talks to any homeserver, including yours, so self-hosting the client is optional in a way that self-hosting the server is not. Three things still push me to do it. A pinned homeserver and a custom brand make onboarding a family or a small team obvious: one URL, one login form, nothing to explain. Your users' browsers fetch the client from you rather than from a third party. And you control the update cadence, which matters because Element ships often and a release occasionally changes behaviour you relied on.
The cost is that you now own updates. Pin the image tag rather than latest if people depend on it, read the release notes, and remember that a cached old build in someone's browser can usually talk to a new homeserver but not always the reverse. Element is also the heaviest Matrix client by a distance; the catalogue is right that minimal clients such as Cinny load faster, though none of them match Element's coverage of encryption key backup and device verification, which are the features that stop a family losing their message history.
What I'd do
Synapse on matrix.example.com, Element Web on chat.example.com behind Caddy, the four-key config.json above, and coturn on a public IP from day one so nobody ever asks why calls fail. Pin the Element tag, update monthly alongside Synapse, and treat the client as what it is: a light, replaceable front end on top of the part that actually holds your messages.
Compare Element Web
26 head-to-head comparisons.
- Element Web vs Tinode
- Element Web vs ejabberd
- Element Web vs Dendrite
- Element Web vs Synapse
- Element Web vs Cinny
- Element Web vs Converse.js
- Element Web vs Openfire
- Element Web vs Nheko
- Element Web vs Dino
- Element Web vs Conduit
- Element Web vs Movim
- Element Web vs MongooseIM
- Element Web vs gomuks
- Element Web vs Profanity
- Element Web vs Convos
- Element Web vs Syphon
- Element Web vs Dendrite Lite
- Element Web vs Fractal
- Element Web vs JSXC
- Element Web vs Continuwuity
- Element Web vs Gajim
- Element Web vs SchildiChat
- Element Web vs Construct
- Element Web vs Commet
- Element Web vs Prose
- Element Web vs conduwuit
Similar matrix & xmpp apps
Tinode
Matrix & XMPPOpen-source instant messaging server
Replaces WhatsApp, Slack
ejabberd
Matrix & XMPPRobust, scalable XMPP messaging server
Replaces Slack, WhatsApp
Dendrite
Matrix & XMPPSecond-generation Matrix homeserver written in Go
Replaces Slack, Discord
Synapse
Matrix & XMPPReference homeserver for the Matrix network
Replaces Slack, Discord
Cinny
Matrix & XMPPSimple, elegant and secure Matrix client
Replaces Slack, Discord
Converse.js
Matrix & XMPPWeb-based XMPP/Jabber chat client
Replaces Slack