Privacy policy
Miluven is an app, not a service. This page explains what the app sends where, which optional features involve a third party, and what the small website behind miluven.app keeps. It is written to match what the software does.
Miluven is made in Europe, by its developer in Amersfoort, the Netherlands, and written to meet European privacy law (the GDPR): collect as little as possible, name every recipient, keep the user in control.
The short version
- Miluven does not run a chat server and has no accounts. Your messages go to the XMPP server you sign in to, under that operator's privacy policy, and they are end-to-end encrypted so the server cannot read them.
- In Strict mode the app talks to your XMPP server and to nothing else — except OpenStreetMap, for the map tiles, when you open a map to send or look at a location.
- In Normal mode a few extras can involve other parties: polls, task lists and live locations (the Miluven poll service, which stores only encrypted text and positions, anonymous counts and per-item state) and GIF search (GIPHY, with your own key). Nothing else in the app talks to a third party.
- No analytics, no crash reporting, no advertising, no tracking, in the app or on this website. The website sets no cookies.
Who processes what
| Party | What it receives | When |
|---|---|---|
| Your XMPP server operator | Your account, contact list, encrypted messages and files, and delivery metadata (who, whom, when); in Normal mode also the edit keys of the polls and task lists you create (see Editing from your other devices) | Always. This is what a chat app needs. |
Miluven poll service (miluven.app) |
Encrypted poll question and options, vote counts, a salted per-poll voter hash; encrypted task-list title, items and names, per-item done and claimed state, a salted per-list voter hash | Normal mode only, when you create, vote in or use a poll or a task list |
Miluven poll service (miluven.app): live locations |
Your position, encrypted on your phone, replaced every two minutes; when it was last replaced and when the share ends; a hash of the sharing phone's token | Normal mode only, while you share a live location (at most 8 hours), and when someone views one |
| OpenStreetMap Foundation (map tiles) | Your IP address and which part of the map is shown | When a map is shown: the app's location screens, and the live-location web page |
| Backblaze (B2 storage, Amsterdam) | Your IP address and which file you asked for | Only when you download the app's source code through the link on the terms page |
| GIPHY | Your GIF search terms, your IP address, your own API key | Normal mode only, when you use GIF search |
Nobody else. The list of parties is complete.
Your XMPP server
Miluven signs in to an XMPP account you already have — from your family, your employer, a public provider, or a server you host yourself. Miluven does not provide accounts and never sees your password, your contacts or your messages. Everything a chat server keeps in order to work is kept by that operator, under their privacy policy, not by Miluven. Typically that is:
- Your address and credentials, your contact list, your group-chat bookmarks, and your display name and avatar if you set one.
- Your message archive, so other devices and a phone that was offline can catch up. Encrypted messages are archived in encrypted form.
- Files you send — photos, videos, voice messages, documents — for as long as that server keeps uploads. In an encrypted conversation the file is encrypted on your phone before upload.
- Delivery metadata: sender, recipient, time and size of each message, which group chats you are in, and your IP address in its connection logs.
- Calls are encrypted and go directly between the two phones where the network allows it. Otherwise they are relayed through a relay server (TURN) that your XMPP server advertises; it passes the encrypted stream along and cannot decrypt it.
How long any of this is kept, and how to export or delete it, is decided by your server operator. Ask them, or pick a server whose policy you agree with.
End-to-end encryption
Conversations are encrypted end to end with OMEMO. Encryption is on by default for one-to-one chats and for private group chats. Encrypting and decrypting happens on the phones involved; the keys never leave them. Your server, and anyone who gains access to it, only ever handles ciphertext.
A conversation is not encrypted when you switch encryption off for it, when you write to a contact whose app does not support OMEMO, or in public channels, which are unencrypted by design. The app shows a lock icon when a conversation is encrypted, and you can verify a contact's keys by scanning a QR code.
Strict and Normal mode
On first start the app asks which of two modes you want. Both can be switched at any time in Settings.
- Strict. Text, photos, files, voice messages, locations and calls. The app connects to your XMPP server and to nothing else, apart from OpenStreetMap's map tiles while a map is open (see Maps in the app). There is no GIF search and there are no polls, task lists or live locations: when someone sends you one, it shows as plain text with its link, and the app fetches nothing for it.
- Normal. Everything in Strict, plus polls, task lists, live location and GIF search. Each is described below.
Polls (Normal mode)
A poll is created from the attachment chooser in any chat, one-to-one or group: a question, two to ten options, single or multiple answers, and optionally a date and time at which it closes automatically. Because votes from many phones have to be counted somewhere, a poll lives on the Miluven poll service at miluven.app, not on your XMPP server. Here is exactly what that service holds:
- The question and options, encrypted. Your phone encrypts them with AES-256-GCM using a secret made up for that poll. The secret travels only inside the chat message, after the
#in the poll link, so it is protected by OMEMO like the rest of the message and is never sent to the poll service. The service stores ciphertext it cannot read. - Vote counts per option.
- A salted, per-poll voter hash, so that one person counts once and can change their vote. It differs for every poll and cannot be turned back into your address or linked across polls. No names are stored, and no IP addresses are stored with polls.
- A hash of the creator's edit token. The phone that creates a poll gets a random edit token back, once; it is never put in the chat message. The service stores only a SHA-256 hash of it, so the token cannot be recovered from the service. The token itself stays with you: on that phone, and in a private PEP node on your own XMPP account that only your account can read, so your other devices can edit the poll too (see Editing from your other devices).
- Timestamps: when the poll was created, if set when it closes, and when it was last edited.
With that token, and only with it, you can change the poll afterwards, from the phone that created it or from another device on the same XMPP account: the question, the options (edit, reorder, add or remove them), whether several answers are allowed (only as long as nobody has voted), and the close date, which can also reopen or close the poll. The new texts are encrypted with the same secret before they leave the phone. Votes stay with their option; votes on an option that is removed are deleted. Everyone who opens the poll sees the new version, marked Edited.
Votes are anonymous: neither the poll service nor the other people in the chat learn who chose what. The web page at miluven.app/p/… can only show the question and options when it is opened from the link in the chat, because the secret after # stays in the browser and is not sent to the server; without it the page shows nothing readable. People on other XMPP clients see a plain text message with the question and the link.
A poll and all of its votes are deleted 90 days after it was created, whether or not it closed earlier. There is no owner who could delete it sooner, so keep that in mind when you write one. In Strict mode nothing on this list happens: the poll feature is not there.
Task lists (Normal mode)
A task list is created from the attachment chooser in any chat: a title and one to twenty tasks. Everyone in the chat can tick a task off, and can claim a task beforehand so the others see who will do it. Like a poll, the list lives on the Miluven poll service at miluven.app, because its state has to be shared between phones. Here is exactly what that service holds:
- The title, the tasks and the names, encrypted. Your phone encrypts them with AES-256-GCM using a secret made up for that list, which travels only inside the chat message, after the
#in the list link, and is never sent to the service. When you claim or tick a task, the name the others see (your account's display name, or your nickname in a group chat) is encrypted the same way before it leaves your phone. The service stores ciphertext it cannot read. - Per task: whether it is done and whether it is claimed.
- A salted, per-list voter hash next to a claim or a tick, so that only the person who claimed a task can release it. It differs for every list, cannot be turned back into your address, and cannot be linked to a poll's voter hash or across lists. No IP addresses are stored with a list.
- A hash of the creator's edit token, as for polls: the token stays with you (on the phone that created the list and in a private PEP node on your own XMPP account), the service stores only its SHA-256 hash.
- Timestamps: when the list was created, when a task last changed, and when the list was last edited.
With that token, and only with it, you can change the list afterwards, from the phone that created it or from another device on the same XMPP account: the title and the tasks (edit, reorder, add or remove them), encrypted with the same secret. Who claimed or ticked a task stays with that task; the state of a removed task is deleted. Everyone who opens the list sees the new version, marked Edited.
Unlike a poll, a task list is not anonymous towards the people in the chat: they see who claimed and who did what, which is the point. Towards the service it is: it only sees ciphertext and hashes. The web page at miluven.app/t/… works like the poll page and needs the link from the chat; a name typed there is encrypted in the browser before it is sent. A list and its state are deleted 90 days after it was created. Templates (a title and tasks you keep to reuse, reachable by typing / in a chat) are stored on your phone only and never sent anywhere. In Strict mode the feature is not there.
Editing from your other devices
The edit key of a poll or task list you create is also kept in your own XMPP account's private storage — a private PEP node on your own XMPP account that only your account can read — so your other devices on the same account — another phone with Miluven, or Gajim with the Miluven plugin — can edit it too. Only your own logged-in sessions can read that node; nobody else in the chat ever gets the key. Your XMPP server can see the key. It only allows changing the poll or list, not reading it: the secret that decrypts the texts is never stored there. Expired keys are removed from it. Nothing extra goes to Miluven. If your server does not offer such private nodes, the key simply stays on the phone that created the poll or list.
Live location (Normal mode)
From the location screen of any chat, one-to-one or group, you can share your live location for 15 minutes, 1 hour or 8 hours. The other people in the chat see where you are, updated every two minutes, until the time runs out or you tap Stop — in the chat, or in the notification that shows for as long as you share. No location is sent anywhere unless you start a share, and the app never asks for location access in the background: the share runs only while its notification is visible (swiping the notification away, or turning notifications off, stops it, and without notifications a share does not start), and it does not come back after a restart. Because the position has to reach phones that cannot all be online at once, it lives on the Miluven poll service at miluven.app. Here is exactly what that service holds:
- Your position, encrypted. Your phone encrypts the latitude, longitude, accuracy and time of the fix with AES-256-GCM using a secret made up for that share, which travels only inside the chat message, after the
#in the link, and is never sent to the service. The service stores ciphertext it cannot read. Every two minutes your phone replaces it with the latest position; earlier positions are not kept, and the database backups made before an update of this site leave live locations out. The hosting provider's automatic disk snapshots, kept for five days, can hold the encrypted position of a share that was running when one was taken; without the link it cannot be read. - A hash of a token that only your phone holds, so that only your phone can replace or stop the share. The token itself is kept on your phone until the share ends.
- Timestamps: when the share started, when the position was last replaced, and when it ends.
The position is deleted as soon as you stop; if your phone cannot reach the service at that moment, it keeps trying every minute, and the app shows the share as running, with its Stop button, until the service has deleted it. If the time you chose runs out first, it can no longer be read from that moment and is deleted by the next request that starts a share. The people in the chat (the Miluven app, or the web page at miluven.app/l/… opened from the link) fetch it every two minutes while they look at it; like every request to the site, that reaches the server with their IP address, which is not stored with the location. The Miluven app of someone who viewed it keeps the last position it decrypted on that phone, so an ended share still shows where it ended.
Whoever has the link can follow the position until the share ends, which is why it belongs in an end-to-end encrypted chat. In a chat that is not encrypted (see End-to-end encryption for when that happens), the link and its key pass through your XMPP server readable, so whoever runs that server could follow you too.
The web page draws the position on a map from OpenStreetMap: once the position has been decrypted, the viewer's browser loads map tiles from tile.openstreetmap.org, which sees the viewer's IP address and the area of the map, under the OpenStreetMap Foundation's privacy policy. Only this site's address is sent along as referrer, never the link or its key. The page's "Open in OpenStreetMap" link puts the coordinates only after the #, which the browser does not send, so openstreetmap.org learns the position no more precisely than from the map tiles it then serves. The map library (Leaflet) is served from miluven.app itself. In Strict mode there is no live location: switching to Strict mode stops a share that is running, and the app's last request to the service deletes it.
Maps in the app
The screens where you pick a location to send, or look at one you received, show a map from OpenStreetMap. While such a screen is open, the app loads map tiles from OpenStreetMap's tile servers, which see your IP address and the area of the map, under the OpenStreetMap Foundation's privacy policy. Your own position is not sent to them, only which tiles are needed. This happens in both modes, and only when you open a map.
GIF search (Normal mode)
GIF search is off by default: it uses GIPHY (Giphy, Inc.) and works only with your own GIPHY API key, which the app asks for the first time you open the GIF picker and stores only on your phone; Miluven ships no key of its own. From then on, every search term you type is sent to GIPHY together with your IP address and your key, under GIPHY's privacy policy. The GIF you choose is downloaded to your phone and then sent through your own server like any other file, encrypted when the conversation is. The people you send it to never contact GIPHY. Until you enter a key, and in Strict mode always, nothing is sent to GIPHY.
Photos you send
Photos are resized and compressed on your phone before they are sent, by the app itself. No third party is involved: the photo goes to your own XMPP server like any other file, encrypted when the conversation is. An earlier version of the app offered optional compression through the outside service reSmush.it; that option was removed in September 2026 and no photo has left the app for it since.
Async mode
Async mode is for answering when it suits you. It is off by default and works the same in Strict and Normal mode; you turn it on in Settings. While it is on, the app changes what it tells others:
- Sent less: no typing notifications, no read receipts (the markers that show a message was read) and no last-seen time. Your own choices for these come back when you turn async off. Delivery receipts, which only say a message reached your phone, are still sent.
- Sent instead: the app shows you as away and sends a status text you choose (by default "Replies within a day"; leave it empty to send none). It goes to your own XMPP server and to your contacts, like any status message.
Everything else happens on your phone. Messages arrive as usual, but their notifications are held until the delivery times you pick. The inbox — which chats you moved to Later or Done, which you are waiting on a reply in and when to remind you, and which chats notify right away — is stored only on your phone, is not sent anywhere, and is left out of backups. Nobody learns that you are waiting on them. Nothing about async mode goes to Miluven.
What we don't do
The app contains no analytics, no crash reporting, no advertising and no tracking of any kind. It does not use Google's push notification service; it keeps its own connection to your server open instead, so no message data passes through Google. Nothing is sold or shared with data brokers. There are no proprietary SDKs in the app.
This website
The pages at miluven.app, and the poll service behind them, are hosted in Amsterdam, the Netherlands (Fly.io region ams). They set no cookies and load nothing from third parties, with one exception: the live-location page at /l/… loads map tiles from OpenStreetMap once it has decrypted a position (see Live location). The source code zip linked from the terms page is stored with Backblaze B2 in Amsterdam; your browser only contacts Backblaze if you follow that link. The web server keeps ordinary access logs (IP address, page requested, time) for a limited time for operational purposes; they are not linked to polls. The poll and task-list pages are the interactive part of the site: they run a small script served from this site, keep the secret in your browser rather than sending it to the server, and store a random voter code (and, for task lists, the name you typed) in your browser's local storage so you can change your vote. Still no cookies, and nothing leaves your browser except the vote.
The invite pages (/i/… and /j/…) only turn a link into an xmpp: address for whichever app you open it with; nothing is stored.
On your phone
Your messages, media, encryption keys and — in Normal mode — your GIPHY key are stored in the app's private storage on your phone. Uninstalling the app removes them. If you grant the Contacts permission, the app uses your address book to show names and photos next to contacts you already know; nothing from your address book is uploaded anywhere. With async mode on, its inbox and reminders are kept on the phone too, outside backups.
Your rights and how to reach me
- Your account and messages are held by your XMPP server operator. Requests to export, correct or delete them go to that operator. Deleting the account from within the app (Manage accounts, open the account, "Delete account") asks the server to remove it.
- Polls hold nothing that identifies you. They are deleted 90 days after creation; there is no earlier deletion.
- Live locations are deleted when you stop sharing, and are unreadable once the time you chose runs out.
- GIPHY and OpenStreetMap process data under their own policies; requests about that data go to them.
- For anything about Miluven itself, email d.seegers.mailgmail.com (written without a link on purpose, so address harvesters do not pick it up; type it into your mail app).
If you are in the European Union you also have the right to lodge a complaint with your national data protection authority; in the Netherlands that is the Autoriteit Persoonsgegevens.
Children
Miluven is not directed at children under 16. Since the app has no accounts of its own, whether a child may hold an XMPP account is a matter for the server operator.
Changes to this policy
When the app or the poll service changes in a way that affects what is described here, this page is updated in the same release and the effective date at the top moves. Material changes are also announced in the app's release notes.