Repository navigation
Privacy and Hosting
What the web interface loads and keeps in a visitor's browser, what the storage notice is, and what your own hosting adds on top. This page describes what the software does. It is not legal advice, and it cannot tell you what you have to do: every installation is run by its own admin, who knows where it runs and who uses it. The app's defaults aim to leave as little behind as possible; what that means for your setup is your call, and a lawyer or your data protection contact can answer it where this page cannot.
A visitor's browser talks only to the server the app runs on. The interface's fonts are bundled with it and served from that same origin; nothing is fetched from a font service or any other third party. The frontend container's Content-Security-Policy backs that up: it names no external source at all, so a stray external script, style, font or image would be blocked rather than loaded.
The server side is separate. The backend contacts what you configure or use: your TeamSpeak servers, an OpenID Connect provider if you set one up, GitHub for the update check, YouTube through yt-dlp, and whatever URLs you put into bot flows. None of that involves a visitor's browser.
How to check it yourself: open the browser's developer tools, switch to the Network tab, reload the login page (and a widget page), and look at the domain of every request. With a default setup there is only your own domain.
The application sets no HTTP cookies. What it keeps is in the browser's localStorage, and all of it is there to make the interface work: the login session, the selected server, display choices such as theme and sidebar, the language, which notices were dismissed, and a few page preferences. Nothing is kept in sessionStorage or IndexedDB. The exact list:
| Key | Holds |
|---|---|
ts6-auth |
the login session: access and refresh token and the user's profile |
ts6-server |
the selected server and virtual server |
ts6-ui |
display state: personal layout, theme and accent, sidebar and collapsed sections |
ts6-language |
the interface language (also the fallback before logging in) |
ts6-privacy-notice |
whether the storage notice was dismissed |
ts6-update-banner, ts6-yt-cookie-banner
|
which update and YouTube-cookie notices were dismissed |
ts6-client-database |
the Client Database page's columns and hidden groups |
ts6-flow-editor-help-seen |
that the Bot Flow editor's usage dialog is not to be shown again |
ts6-history-timezone, ts6-history-show-slots, ts6-history-metric
|
display choices of the statistics History tab |
ts6-2fa-device-<username> |
the "remember this device" token for two-factor login |
ts6-console-events-<id>, ts6-console-history-<id>
|
the Query console's chosen event categories and its command history, one pair per user account (a command carrying a password is never kept) |
The public widget page (/widget/<token>), which is meant to sit in an iframe on other sites, stores nothing at all and does not show the storage notice.
Two consequences worth knowing:
- Clearing a browser's site data removes all of it. A user is logged out and any personal choice is back to the installation default. The dashboard layout is the exception: it is stored with the user's account on the server, not in the browser, so it survives this and follows the user to other browsers.
- The login session lives in
localStorage, not in a cookie, so signing out on a shared computer matters.
The same check works here: the developer tools' Application tab lists the cookies and the local storage of the site.
The interface shows a small dismissible bar, on the login page and inside the app, saying in plain words that it only stores what it needs to work, that the application sets no cookies of its own and uses no tracking or analytics service, and that the fonts come from the same server. It exists in English, German and French, following the user's language.
- It is informational. There is nothing to accept or decline, and nothing is blocked or waits until it is clicked. The button only hides it, and that is remembered in that one browser.
- Admins switch it on or off under Settings → WebGui. It is on by default. The switch applies to everyone, including visitors who are not logged in; for that, the one value is readable without a login.
- The text is fixed. It is not editable in the interface. If your situation calls for different wording, that is a reason to switch it off and use your own.
- It is not shown on the public widget page (see below).
Whether to show it at all, and whether it is enough for your installation, is yours to decide. The app only makes sure that what it says is true of the app itself.
Separate from the browser: the backend writes a row to its own database for every sign-in event at the web interface - the password step, the second factor, single sign-on, and requests the sign-in limit turned away. A row holds the time, the event and its result, a short reason, the IP address the backend takes for the visitor, the account name, and the browser's User-Agent. For a name that no account has, the name is stored as it was typed, which can be a password entered in the wrong field.
The same journal also keeps one row per client that joins a TeamSpeak server this app is connected to: the nickname, unique ID and IP address TeamSpeak reports for it, the client version and platform, which server, and when it joined and left. That is on by default for every connection and switched off per connection (Settings → Connections) or for the whole journal. ServerQuery clients and this app's own music bots are left out unless you ask for them.
-
Only admins can read it, on the Connection Journal page. No address is sent anywhere. Each row also stores the country (with the City database the region and city) of its address, looked up in a database file on your own server (how); the one outbound request is the download of that file from
download.db-ip.com, which an admin starts with a click or, if switched on, the monthly update, and which carries nothing about your installation. - Bans are kept as well. An address banned from the journal is stored with who set it, when, why and until when, and how many requests it has turned away; it is removed when the ban ends or is lifted (how). A TeamSpeak ban lives in the TeamSpeak server's own ban list, not in this app.
- It is kept 30 days and at most 100 000 entries by default. Both are set on that page, which also switches the recording off and empties the journal.
-
The address is only as good as your proxy setup. Behind a reverse proxy it is what the backend reads from
X-Forwarded-For(Deployment).
IP addresses count as personal data in many places, and how long you keep them, and what you tell people about it, is your decision. This page is not legal advice.
A widget page is meant to sit in an iframe on somebody else's site. It does not show the storage notice and does not even ask for the setting, and it stores nothing in the visitor's browser: no cookie, no localStorage, no sessionStorage. The SVG and PNG variants are plain images served from your server.
Like any request, a visit still reaches your server, and with it the visitor's IP address (see the next section). What the embedding site tells its own visitors is that site's business.
The app cannot see, and this page cannot cover, what sits around it. Things worth a look, in general terms:
- Access logs. A web server or reverse proxy in front of the app usually records the visitor's IP address and browser with every request. Check what yours logs, where, and for how long it keeps it. The proxy in front of the app is yours; see Deployment.
- Anything your proxy or CDN adds. A CDN, a bot filter or a login gateway may set its own cookies or load its own resources. That happens outside this app and is not covered by the statements above.
- Anything you inject yourself. An analytics snippet or a chat widget added at the proxy would be blocked by the frontend container's Content-Security-Policy as shipped, unless you loosen it, and it would then make the notice's wording untrue for your installation.
- What the app shows to your admins. The manager presents what your TeamSpeak server reports, for example the Client Database page's last IP address column. That is data from your TeamSpeak server, visible to your admins, and subject to how you run that server. A widget with the client list enabled makes the nicknames of who is online public; see Widgets.
-
Backups.
data/holds every setting, user and connection, with credentials encrypted. See Deployment → What to back up.
The bundled fonts and the notice arrived with the frontend, so an installation updated the usual way (see Deployment → Updating) has them after the rebuild. There is nothing to configure.
v0.9, last edited 15.10.2026
Getting started
Using the app
Running it
When something is odd
Contributing