How Invidious Handles User Privacy: A Technical Breakdown
Invidious minimizes personal data collection by storing only bcrypt-hashed passwords, random session tokens, and essential user preferences, while avoiding IP logging, tracking cookies, and advertising analytics entirely.
Invidious, the open-source alternative YouTube frontend maintained by iv-org, implements a privacy-first architecture that limits data retention to only the essentials required for functionality. The Crystal-based codebase explicitly avoids the surveillance patterns common in commercial video platforms, instead storing minimal account metadata, encrypting sensitive fields, and giving users complete control over their data deletion. Understanding how Invidious handles user privacy requires examining three distinct layers of data interaction: directly-provided account information, passive request logging, and browser-stored session tokens.
Directly-Provided Account Data
When you create an account, Invidious stores only the necessary fields to enable core features. The create_user function in src/invidious/users.cr (lines 10-20) populates an Invidious::User struct with your account name, a bcrypt-hashed password, a randomly generated user ID, subscription lists, watched video IDs, user preferences, and an RSS-feed token.
Password security is handled through the Crypto::Bcrypt::Password.create method, ensuring plaintext passwords never touch the PostgreSQL database. Session tokens are generated using Base64.urlsafe_encode(Random::Secure.random_bytes(32)), creating cryptographically secure random strings that authenticate requests without exposing user credentials.
Passive Request Logging Without Identification
Invidious explicitly rejects the data harvesting techniques used by tracking-heavy platforms. The server logs only request timestamps, HTTP methods, URLs, and response status codes with durations—no IP addresses, User-Agent strings, cookies, or browser fingerprints are retained.
This logging policy is documented in the privacy page template at src/invidious/views/privacy.ecr (lines 25-34), which explains that Kemal's built-in middleware handles these minimal logs purely for troubleshooting. Because these entries contain no identifying information and are not linked to user accounts, they cannot be used to reconstruct browsing histories or identify individual visitors.
Browser-Stored Session Management
Client-side storage is limited to a single authentication cookie containing your account token. Configured through Kemal's session middleware, this implementation stores only the randomly generated token server-side, as detailed in privacy.ecr (lines 42-48).
Anonymous users receive an optional preferences cookie for interface customization, but this contains no identifying data. Users can revoke session tokens instantly by logging out or deleting browser cookies, forcing re-authentication without compromising the underlying account security.
Playlist Privacy Enforcement
Content privacy is enforced at the database level using a PostgreSQL enum defined in src/invidious/database/migrations/0008_create_playlists_table.cr (lines 6-9). The migration creates a privacy enum type that restricts playlist visibility to public or private states, validated at startup by Invidious::Database.check_enum in src/invidious/database/base.cr (line 12).
API endpoints enforce these restrictions through explicit authorization checks. In src/invidious/routes/api/v1/misc.cr (line 61), the code validates access with the logic playlist.privacy.private? && playlist.author != user.try &.email, ensuring private playlists return unauthorized errors for anyone except the creator.
You can test playlist privacy through the API using bearer token authentication:
curl -H "Authorization: Bearer $TOKEN" \
https://your-instance.tld/api/v1/playlists/$PLAYLIST_ID
User-Controlled Data Deletion
Invidious provides explicit mechanisms for data removal that do not require administrative intervention. Watch history can be cleared via the /clear_watch_history endpoint, which renders the template at src/invidious/views/user/clear_watch_history.ecr and truncates the watched video association.
<form action="/clear_watch_history" method="post">
<button type="submit">Clear watch history</button>
</form>
Complete account deletion is available through /delete_account (template: src/invidious/views/user/delete_account.ecr), which removes the user row from PostgreSQL and cascades the deletion to related data. This eliminates subscription lists, preferences, and session tokens permanently without retaining backups.
<form action="/delete_account" method="post">
<button type="submit">Delete my account</button>
</form>
Transparency and External Dependencies
The /privacy route defined in src/invidious/routes/misc.cr (lines 31-34) serves a static HTML page generated from privacy.ecr that documents all data handling practices. View this page directly to verify the privacy policy:
curl https://your-instance.tld/privacy
This includes disclosure that video streams originate from googlevideo.com, maintaining transparency about the single external domain contact required for functionality.
Summary
- Passwords are stored as bcrypt hashes in
src/invidious/users.cr, never in plaintext - Session tokens are cryptographically random 32-byte strings encoded in URL-safe Base64
- No tracking occurs: IP addresses, User-Agent headers, and fingerprints are explicitly excluded from logs
- Playlist privacy is enforced via PostgreSQL enums and API-level authorization checks in
src/invidious/routes/api/v1/misc.cr - Data deletion is user-initiated through
/clear_watch_historyand/delete_accountendpoints with immediate effect - Transparency is maintained through the static
/privacypage documenting all collection practices
Frequently Asked Questions
Does Invidious store IP addresses or use tracking cookies?
No. The source code explicitly avoids collecting IP addresses, User-Agent strings, or browser fingerprint data. The only cookie stored is a single authentication token for logged-in users, and logging middleware in Kemal records only request metadata (timestamp, method, URL, status) without identifiers.
How does Invidious protect user passwords?
Passwords are hashed using Crypto::Bcrypt::Password.create during account creation in src/invidious/users.cr. The bcrypt algorithm stores only the hash and salt, making password cracking computationally expensive while allowing the application to verify credentials without ever storing or comparing plaintext.
Can I permanently delete my Invidious account and all associated data?
Yes. Visiting /delete_account triggers a PostgreSQL cascade delete that removes your user row, subscription lists, watch history, preferences, and session tokens. This is implemented in the backend logic associated with src/invidious/views/user/delete_account.ecr and executes immediately without approval delays.
How does Invidious handle private playlists versus public ones?
Private playlists use a PostgreSQL enum defined in migration 0008_create_playlists_table.cr that restricts access at the API level. The check playlist.privacy.private? && playlist.author != user.try &.email in src/invidious/routes/api/v1/misc.cr (line 61) ensures only the playlist author can retrieve private content through authenticated requests.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →