Beat Scrobble
A modern, colorful, self-hosted music analytics platform that puts your listening data under your control. Your music, your data, your insights โ powered by smart AI with zero wasted tokens, built on Beat-Scrobble: a Koito-based, themeable scrobbler that works with any program compatible with ListenBrainz.
๐ Table of Contents
โจ Features
| Feature |
Description |
| ๐ ListenBrainz Compatible |
Seamless integration with any LB-compatible scrobbler. Just point your client to your server URL. |
| ๐ฅ Multi-Source Import |
One-click import from Spotify, Last.fm, ListenBrainz, and Maloja. Smart Deduplication handles cross-service syncing intelligently. |
| ๐ก Relay Mode |
Automatically forward your live scrobbles to other services like ListenBrainz or Maloja (Proxy Mode). Note: Manual imports/ad-hoc backups are not forwarded. |
| ๐ Full Data Ownership |
Self-hosted architecture. Your data stays 100% yours, stored locally in PostgreSQL. |
| ๐ฅ Multi-User Support |
Complete user isolation. Admins can manage users, roles, and quotas via a dedicated UI. |
๐ค AI-Powered Features
๐ง AI Music Intelligence (Critique & Analysis)
Get witty, personalized AI reviews of your tracks and listening habits. Beat Scrobble now provides the AI with rich context, enabling "roasts" or critiques that feel genuinely insightful.
-
Track Critiques: AI commentary on individual songs derived from metadata and audio features.
-
Profile Critique: Deep analysis of your listening personality based on your history.
-
Deep Context Awareness (New!):
- User Obsessions: It knows how many times you've played a track (Total vs This Week).
- Temporal Context: It knows the Time of Day and Day of Week (e.g., critiquing you for listening to Sadcore at 8 AM).
-
Privacy Fences (๐ก๏ธ New!):
- Granular Control: You decide exactly what data leaves your server via Toggle Fences in Settings.
- Toggles: Individually enable/disable sharing of
Metadata, Play Stats, Context, or Listening History.
- Safe by Design: If a fence is up, that data is stripped from the payload before it ever touches the API.
-
Smart Caching: Critiques are cached indefinitely. Zero wasted tokens on repeat generation.
-
OpenRouter Integration: Use GPT-4, Claude, Gemini, or any LLM of your choice.
๐ต AI Playlists (7 Types)
| Playlist |
Description |
| ๐ญ Mood Mix |
Curated tracks perfectly matching a specific emotional tone. |
| ๐ธ Genre Dive |
Deep exploration into the nuances of specific genres. |
| ๐ก Discover Weekly |
Fresh new music recommendations based on your taste. |
| โณ Time Capsule |
A nostalgic throwback to a randomly selected past era. |
| ๐ป Artist Radio |
Continuous mix of similar artists to your favorites. |
| ๐
Decade Mix |
The absolute best tracks from a specific decade. |
| ๐ Hidden Gems |
Underplayed tracks in your library that deserve more love. |
๐ฎ Semantic Search (pgvector)
- Vector Embeddings: Tracks, artists, and albums are stored as vectors.
- Vibe-Based Search: Search for "Sad songs from the 90s" or "Upbeat workout music".
- Similar Users: Find other users on your instance with compatible taste.
๐ Analytics & Visualizations
Beat Scrobble offers 15+ interactive visualizations to explore your listening data.
๐๏ธ Activity & History
| Visualization |
Description |
| ๐งฉ Activity Grid |
GitHub-style heatmap showing listening intensity. Darker = more listens. |
| ๐ Timeline View |
Infinite-scroll chronological history with art thumbnails and swipe-to-delete. |
| ๐ง Listening Sessions |
Smart grouping of consecutive listens into sessions with duration analysis. |
๐ Rankings & Charts
| Visualization |
Description |
| ๐ TopListChart |
Animated horizontal bar chart for top tracks/albums/artists (Day/Week/Month/Year). |
| ๐ ListeningTrends |
SVG area chart showing volume evolution over time. |
| ๐งฑ The Wall |
Aesthetic grid layout of top 50 artists with hover stats. |
๐จ Creative Visualizations
| Visualization |
Description |
| ๐ซง ArtistBubbles |
Physics-based circle-packing diagram. Size = Play Count. |
| ๐ผ๏ธ AlbumQuilt |
Mosaic collage of top album covers with glow effects. |
| ๐ StreamGraph |
Stacked area waves showing artist popularity battles over time. |
| โ๏ธ Genre Cloud |
Word cloud of your top genres. Larger text = Higher frequency. |
๐ Data Insights
| Visualization |
Description |
| ๐ ScatterPlot |
Time-of-day vs Day-of-week analysis of your listening habits. |
| ๐น๏ธ Music Decades |
Retro striped bar chart showing distribution by release decade. |
| ๐ฉ Music Ratio |
Radial breakdown of unique tracks vs albums vs artists. |
| ๐งฌ Listening Fingerprint |
Radar chart visualizing audio features (Energy, Danceability, etc). |
๐ฏ Dashboard Features
| Feature |
Description |
| ๐๏ธ Control Room |
Unified dashboard with Now Playing, metrics, and mini-charts. |
| ๐ Yearly Recap |
"Spotify Wrapped" style annual summary with shareable stats. |
| ** Period Filters** |
Instant filtering: Today, Week, Month, Year, All Time. |
| โถ๏ธ Now Playing |
Real-time player with AI critique and quick actions. |
๐ก๏ธ Security & Privacy
Beat Scrobble puts your data safety first with enterprise-grade security practices standard in every deployment.
| Feature |
Description |
| ๐ Secret Masking |
API keys and secrets are automatically redacted before being sent to the client, preventing leakage via XSS or browser inspection. |
| ๐ช Secure Sessions |
Authentication uses HttpOnly, Secure, and SameSite=Lax cookies to prevent session hijacking and CSRF attacks. |
| ๐ก๏ธ Brute Force Shield |
Intelligent Rate Limiting on Login and Signup endpoints prevents credential stuffing attacks. |
| ๐ Resource Protection |
Global Rate Limiting (300 req/min) and Request Size Limits (10MB) on all API routes prevent DoS attacks and resource exhaustion. |
| ๐งฑ File Upload Hardening |
Magic-byte verification ensures only valid image files are processed, preventing Polyglot/XSS payload uploads. |
| ๐ต๏ธ User Isolation |
Strict Row-Level Security ensures users can never access each other's data in multi-user instances. |
| ๐ฎ Role-Based Access |
Granular RBAC ensures only verified Admins can modify global settings or manage users. |
| ๐ณ Container Security |
Runs as a non-root user (beatscrobble) inside Docker for minimized attack surface. |
| ๐ป Zero Telemetry |
No tracking, no analytics, no "phone home". Your browsing habits and listening data never leave your server. |
| ๐ง AI Privacy Fences |
Granular control over what context sends to AI. Strip metadata, timestamps, or play counts with a toggle before analysis. |
| ๐ Local First |
100% Self-hosted. Your database, your rules. No third-party data mining. |
๐ Quick Start
Docker (Recommended)
# Clone the repository
git clone https://github.com/SaturnX-Dev/Beat-Scrobble.git
cd Beat-Scrobble
# Configure environment
cp .env.example .env
# Edit .env with your settings
# Start with Docker Compose
docker compose -f docker-compose.prod.yml up -d
Docker Compose (Simple)
Ideal for quick deployment.
services:
beat-scrobble:
image: saturnxdev/beat-scrobble:latest
container_name: beat-scrobble
restart: unless-stopped
ports:
- "4110:4110"
environment:
- BEAT_SCROBBLE_DATABASE_URL=postgres://postgres:password@db:5432/beatscrobble
- BEAT_SCROBBLE_ALLOWED_HOSTS=localhost,127.0.0.1
volumes:
- ./data:/app/data
- ./config:/etc/beat_scrobble
depends_on:
- db
db:
image: pgvector/pgvector:pg16
container_name: beat-scrobble-db
restart: unless-stopped
environment:
POSTGRES_DB: beatscrobble
POSTGRES_PASSWORD: password
volumes:
- ./db-data:/var/lib/postgresql/data
Docker Compose (Complete / Advanced)
Full configuration showcasing all available capabilities.
services:
beat-scrobble:
image: saturnxdev/beat-scrobble:latest
container_name: beat-scrobble
restart: unless-stopped
ports:
- "4110:4110"
environment:
# --- Core Configuration ---
- BEAT_SCROBBLE_DATABASE_URL=postgres://postgres:password@db:5432/beatscrobble
- BEAT_SCROBBLE_LISTEN_PORT=4110
- BEAT_SCROBBLE_BIND_ADDR=0.0.0.0
- BEAT_SCROBBLE_ALLOWED_HOSTS=beatscrobble.local,localhost
- BEAT_SCROBBLE_CORS_ALLOWED_ORIGINS=http://beatscrobble.local,http://localhost:4110
- BEAT_SCROBBLE_CONFIG_DIR=/etc/beat_scrobble
# --- Security & Auth ---
- BEAT_SCROBBLE_DEFAULT_USERNAME=admin
- BEAT_SCROBBLE_DEFAULT_PASSWORD=changeme
- BEAT_SCROBBLE_LOGIN_GATE=true # If true, blocks public routes until login
- PUID=1000 # User ID for file permissions
- PGID=1000 # Group ID for file permissions
# --- External Services ---
- BEAT_SCROBBLE_MUSICBRAINZ_URL=https://musicbrainz.org
- BEAT_SCROBBLE_MUSICBRAINZ_RATE_LIMIT=1 # Requests per second
- BEAT_SCROBBLE_DISABLE_MUSICBRAINZ=false
- BEAT_SCROBBLE_DISABLE_COVER_ART_ARCHIVE=false
- BEAT_SCROBBLE_DISABLE_DEEZER=false
# --- Performance ---
- BEAT_SCROBBLE_ENABLE_FULL_IMAGE_CACHE=true
- BEAT_SCROBBLE_THROTTLE_IMPORTS_MS=0 # Delay between import batches (0 = fast)
- BEAT_SCROBBLE_ENABLE_STRUCTURED_LOGGING=true
- BEAT_SCROBBLE_LOG_LEVEL=info # debug, info, warn, error, fatal
# --- Relay Mode (ListenBrainz) ---
- BEAT_SCROBBLE_ENABLE_LBZ_RELAY=false
# - BEAT_SCROBBLE_LBZ_RELAY_URL=https://api.listenbrainz.org
# - BEAT_SCROBBLE_LBZ_RELAY_TOKEN=your_token_here
# --- Custom Import Logic ---
- BEAT_SCROBBLE_SKIP_IMPORT=false
- BEAT_SCROBBLE_FETCH_IMAGES_DURING_IMPORT=true
- BEAT_SCROBBLE_ARTIST_SEPARATORS_REGEX=\s+ยท\s+;;\s+feat\.\s+
volumes:
- ./data:/app/data
- ./config:/etc/beat_scrobble
- ./import:/etc/beat_scrobble/import # Place files here for auto-import
depends_on:
- db
db:
image: pgvector/pgvector:pg16
container_name: beat-scrobble-db
restart: unless-stopped
shm_size: 256mb # Recommended for larger databases
environment:
POSTGRES_DB: beatscrobble
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
volumes:
- ./db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Build from Source
# Backend
go build -o beat-scrobble ./cmd/api
# Frontend
cd client
corepack enable # Enables pnpm
pnpm install
pnpm run build
๐จ Premium UI & Customization
| Feature |
Description |
| ๐ฑ Mobile-First |
Optimized bottom nav and responsive layouts. |
| โจ Aura Styles |
32+ dynamic visual effects and gradients. |
| ๐ Auto Theme |
Smart time-based automatic Day/Night switching. |
| ๐ผ๏ธ Backgrounds |
Support for custom uploaded images or looping videos. |
| ๐ Glassmorphism |
Modern, sleek glass card aesthetics. |
Built-in Themes
Midnight, Snow, Ocean, Forest, Sunset, Neon, Retro, Minimal, and more...
๐ต Spotify Integration
Enrich your library with Spotify metadata.
| Feature |
Description |
| ๐ค Artist Metadata |
Genres, popularity score |
| ๐ฟ Album Metadata |
Genres, popularity, release date, record label |
| ๐ผ Track Metadata |
Spotify ID linking, popularity score |
| ๐ก Fetch Terminal |
Real-time SSE-powered bulk metadata fetching terminal |
| ๐พ Import |
Independent backup/restore for your Spotify metadata mapping |
Data Display:
- Artist Page: Genres badges, popularity %
- Album Page: Genres badges, popularity %, release date, label
- Track Page: Popularity score, listening history
Bulk Fetch Optimization (2-Phase Priority):
- Phase 1 - Priority Fetch: Top 100 Artists โ Top 100 Albums โ Top 100 Tracks (fast, 100ms rate limit)
- Phase 2 - Deep Scan: Remaining library processed in background (calm, 200ms rate limit)
- Smart Progress: Real-time SSE progress bar showing items processed vs total
- Background Sync: New scrobbles trigger automatic metadata fetching
- Auto-Search & Link: Tracks without Spotify ID are automatically searched and linked
Setup:
- Create app at Spotify Developer Dashboard
- Enter Client ID & Secret in Settings โ APIs โ Spotify
- Click "Open Fetch Terminal" for bulk metadata fetch
โ๏ธ Server-Side Storage
All preferences sync across devices:
- โ
Themes & Aura settings
- โ
Custom colors & backgrounds
- โ
Profile images
- โ
AI cache & preferences
๐ Public Profiles
Share your stats at /u/username:
- Visitors see YOUR theme and customizations
- Profile image displayed
- Full stats visible
Beat Scrobble is engineered for speed with millions of scrobbles:
Backend Optimizations
| Optimization |
Impact |
| ๐ฆ Materialized Views |
Pre-aggregated stats for instant reporting |
| ๐ Full-Text Search |
tsvector w/ triggers for <10ms search results |
| โก Compound Indexes |
Optimized (user_id, listened_at) lookups |
| ๐ก๏ธ User Isolation |
Row-level security logic via user_id filters |
| ๐๏ธ Gzip Compression |
10x smaller API JSON payloads |
| ๐ฑ Connection Pooling |
Tuned pgx pool for high-concurrency |
| ๐งต Async Workers |
Go channels for non-blocking background imports |
Frontend Optimizations
| Optimization |
Impact |
| ๐ Virtualization |
Efficient rendering of massive lists (10k+ items) |
| โ๏ธ Code Splitting |
React Router 7 file-based routing for fast initial load |
| โก Optimistic UI |
Instant feedback before server confirmation |
| ๐พ Persistent Cache |
TanStack Query syncing to IndexedDB |
| ๐ผ๏ธ Lazy Images |
Native loading="lazy" for viewport-only loading |
โ๏ธ Configuration
User Management
Admins have access to a dedicated Users tab in Settings.
- Create/Delete Users: Manage access to your instance.
- Roles: Assign
User or Admin roles.
- Quotas:
MAX_USERS env var limits signups.
- Isolation: Each user has their own isolated listen history, sources, and imports.
Environment Variables
| Variable |
Description |
Default |
BEAT_SCROBBLE_DATABASE_URL |
PostgreSQL connection string |
Required |
BEAT_SCROBBLE_ALLOWED_HOSTS |
Comma-separated allowed hosts |
localhost |
BEAT_SCROBBLE_LISTEN_PORT |
Application server port |
4110 |
PUID |
User ID for permission handling |
1000 |
PGID |
Group ID for permission handling |
1000 |
OPENAI_API_KEY |
Key for AI features (OpenRouter) |
- |
BEAT_SCROBBLE_LOGIN_GATE |
Block public routes until login |
true |
BEAT_SCROBBLE_DEFAULT_USERNAME |
Admin username for first setup |
admin |
๐ค AI Setup
- Get an API key from OpenRouter
- Go to Settings โ API Keys
- Enter your OpenRouter key
- Enable: AI Critique, Profile Critique, AI Playlists
Smart Caching (Token Saver)
| Feature |
Refresh Interval |
Condition |
| ๏ฟฝ Now Playing |
Forever |
Generated once per track, cached indefinitely |
| ๐ค Profile (Day) |
4 hours |
Updates only if new listens occur |
| ๐ค Profile (Week) |
3 days |
Updates only if new listens occur |
| ๐ค Profile (Long) |
7 days |
Updates only if new listens occur |
| ๐ถ AI Playlists |
7 days |
Regenerates weekly or on manual request |
๐ฆ Backup & Import
Beat Scrobble supports a robust import system that respects user isolation.
| Source |
Format |
Notes |
| Beat Scrobble V2 |
Full JSON Backup |
Includes listens, preferences, theme, and AI cache. |
| Koito (Legacy) |
V1 JSON Export |
Listens only. Legacy format support. |
| Last.fm |
Official CSV Export |
Imports scrobbles with timestamps. |
| ListenBrainz |
Official JSON Export |
Full history import. |
| Spotify |
Streaming History (JSON) |
"Extended Streaming History" recommended. |
| Maloja |
Native JSON Backup |
Compatible with Maloja exports. |
How to Import
- Navigate to Settings โ Backup.
- Upload your export file.
- The system will automatically detect the format (V2 vs Legacy vs External).
- V2 Backups restore your entire profile state (Themes, AI Settings).
- Files are queued and processed in the background by the Worker.
๐ ๏ธ API Reference
See the complete API Documentation for detailed endpoint usage.
| Component |
Base Path |
Description |
| Web API |
/apis/web/v1 |
Core application endpoints (Auth, Data, AI) |
| ListenBrainz |
/apis/listenbrainz/1 |
Compatible scrobble submission endpoint |
| Static |
/images, /profile-images |
Optimized asset delivery |
๐ณ Production Deployment
With Nginx (Recommended)
docker compose -f docker-compose.prod.yml up -d
Includes:
- Nginx - Reverse proxy with edge caching
- App - Beat Scrobble (Alpine, ~50MB)
- DB - PostgreSQL 16 with pgvector
Edge Caching
The included nginx.conf provides:
- 30-day image cache - Album/artist images
- Gzip compression - All text responses
- Rate limiting - API protection
- Security headers - XSS, clickjacking protection
๐๏ธ Architecture

๐ผ๏ธ Image Loading Flow
When images are missing or have invalid URLs, Beat Scrobble automatically searches external providers:

๐ธ Screenshots
๐ฅ๏ธ Desktop
๐ฑ Mobile
๐ Credits
๐ License
MIT License - See LICENSE for details.
Beat Scrobble - Star us on GitHub!