{"id":48879127,"url":"https://github.com/ellite/scrob","last_synced_at":"2026-04-16T02:00:51.404Z","repository":{"id":351654899,"uuid":"1211907833","full_name":"ellite/scrob","owner":"ellite","description":"Scrob - Self-hosted media tracking app. It syncs your libraries from Jellyfin, Plex, and Emby, tracks your watch history, ratings, and personal lists — Your own private Letterboxd + Trakt","archived":false,"fork":false,"pushed_at":"2026-04-16T00:04:12.000Z","size":28309,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T00:26:25.129Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Astro","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ellite.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-15T21:47:59.000Z","updated_at":"2026-04-16T00:04:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ellite/scrob","commit_stats":null,"previous_names":["ellite/scrob"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ellite/scrob","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ellite%2Fscrob","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ellite%2Fscrob/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ellite%2Fscrob/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ellite%2Fscrob/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ellite","download_url":"https://codeload.github.com/ellite/scrob/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ellite%2Fscrob/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31867712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"online","status_checked_at":"2026-04-16T02:00:06.042Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-16T02:00:31.254Z","updated_at":"2026-04-16T02:00:51.382Z","avatar_url":"https://github.com/ellite.png","language":"Astro","funding_links":["https://github.com/sponsors/ellite"],"categories":["Python","*Arr Stack \u0026 Automation","Astro"],"sub_categories":["Hosting Providers (VPS, Seedbox..)"],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"frontend/public/scrob.png\" alt=\"Scrob Logo\" width=\"120\" /\u003e\n  \u003ch1\u003eScrob\u003c/h1\u003e\n  \u003cp\u003eOpen-source, self-hosted media tracking — your personal Letterboxd + Trakt.\u003c/p\u003e\n\n  [![GitHub Stars](https://img.shields.io/github/stars/ellite/scrob?style=flat-square)](https://github.com/ellite/scrob/stargazers)\n  [![Docker Pulls](https://img.shields.io/docker/pulls/bellamy/scrob?style=flat-square)](https://hub.docker.com/r/bellamy/scrob)\n  [![GitHub Contributors](https://img.shields.io/github/contributors/ellite/scrob?style=flat-square)](https://github.com/ellite/scrob/graphs/contributors)\n  [![GitHub Sponsors](https://img.shields.io/github/sponsors/ellite?style=flat-square)](https://github.com/sponsors/ellite)\n  [![Latest Release](https://img.shields.io/github/v/release/ellite/scrob?style=flat-square)](https://github.com/ellite/scrob/releases/latest)\n\u003c/div\u003e\n\n---\n\nScrob syncs your libraries from **Jellyfin**, **Plex**, and **Emby**, tracks your watch history, ratings, and personal lists, and lets you push your activity back to **Trakt** — all from a clean, app-like web interface that installs as a PWA on any device.\n\n## Table of Contents\n\n- [Features](#features)\n- [Screenshots](#screenshots)\n- [Getting Started](#getting-started)\n  - [Docker Compose](#docker-compose)\n  - [Docker Run](#docker-run)\n  - [First Setup](#first-setup)\n  - [Updating](#updating)\n- [Configuration](#configuration)\n- [Development](#development)\n- [Webhooks](#webhooks-real-time-scrobbling)\n- [OIDC / Single Sign-On](#oidc--single-sign-on)\n- [Contributing](#contributing)\n- [Contributors](#contributors)\n- [License](#license)\n\n## Features\n\n- **Multi-source sync**: Import your full library, watch history, and ratings from Jellyfin, Plex, and Emby. Incremental syncs keep everything up to date.\n- **Real-time scrobbling**: Webhooks from Jellyfin, Plex, and Emby update your watch state as you play — no manual sync needed.\n- **Trakt integration**: Sync your watched history and ratings from Trakt, and push Scrob activity back to Trakt automatically.\n- **Watch history \u0026 ratings**: Track every movie and episode you've watched. Rate them on a 10-point scale with optional reviews.\n- **Season ratings**: Rate individual seasons separately from the overall show.\n- **Personal lists**: Create and curate lists of movies and shows. Mark them public to share with other users on the same instance.\n- **Comments**: Leave comments on movies, shows, seasons, and episodes.\n- **Social**: Follow other users and see their activity.\n- **TMDB integration**: Rich metadata for every title — posters, backdrops, cast, crew, trailers, collections, and more.\n- **Search**: Search TMDB across movies, shows, people, and collections, merged with your local library data.\n- **Trending \u0026 Airing Today**: Daily trending movies and shows from TMDB, plus episodes airing today filtered to your collection.\n- **Continue Watching \u0026 Next Up**: Dashboard cards showing in-progress items and the next episode to watch in each series.\n- **Season \u0026 episode tracking**: Detailed season views with per-episode watched state and progress.\n- **Cast \u0026 crew pages**: Full filmography for any person, linked to your library.\n- **Radarr \u0026 Sonarr integration**: Add movies and shows to Radarr/Sonarr directly from the Scrob UI.\n- **Two-Factor Authentication**: TOTP-based 2FA with backup codes, managed from the settings page.\n- **OIDC / SSO**: Authenticate with any OpenID Connect provider (Authelia, Authentik, Keycloak, etc.).\n- **Progressive Web App**: Install Scrob on any device — Android, iOS, or desktop — for a native app feel.\n- **Single container**: Frontend and backend ship as one image on one port. No separate services to manage.\n\n## Screenshots\n\n\u003cdetails\u003e\n\u003csummary\u003eView screenshots\u003c/summary\u003e\n\n**Dashboard**\n\u003cimg src=\"docs/screenshots/scrob-dashboard-dark.png\" alt=\"Dashboard\" width=\"800\" /\u003e\n\n**Explore**\n\u003cimg src=\"docs/screenshots/scrob-explore-light.png\" alt=\"Explore\" width=\"800\" /\u003e\n\n**Movie**\n\u003cimg src=\"docs/screenshots/scrob-movie-light.png\" alt=\"Movie\" width=\"800\" /\u003e\n\n**Show**\n\u003cimg src=\"docs/screenshots/scrob-show-dark.png\" alt=\"Show\" width=\"800\" /\u003e\n\n**Season**\n\u003cimg src=\"docs/screenshots/scrob-season-dark.png\" alt=\"Season\" width=\"800\" /\u003e\n\n**Episode**\n\u003cimg src=\"docs/screenshots/scrob-episode-dark.png\" alt=\"Episode\" width=\"800\" /\u003e\n\n**Search**\n\u003cimg src=\"docs/screenshots/scrob-search-light.png\" alt=\"Search\" width=\"800\" /\u003e\n\n**History (mobile)**\n\u003cimg src=\"docs/screenshots/scrob-history-dark-mobile.png\" alt=\"History mobile\" width=\"800\" /\u003e\n\n**Lists (mobile)**\n\u003cimg src=\"docs/screenshots/scrob-lists-light-mobile.png\" alt=\"Lists mobile\" width=\"800\" /\u003e\n\n**Settings**\n\u003cimg src=\"docs/screenshots/scrob-settings-dark.png\" alt=\"Settings\" width=\"800\" /\u003e\n\n\n\u003c/details\u003e\n\n## Getting Started\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/)\n- A [TMDB API key](https://www.themoviedb.org/settings/api) (free) — used for metadata, search, and images\n\n### Docker Compose\n\n\u003e Images are hosted on **Docker Hub** (`bellamy/scrob`). A mirror is also available on GHCR (`ghcr.io/ellite/scrob`) if you prefer.\n\n1. Download the compose file:\n\n```bash\ncurl -o docker-compose.yaml https://raw.githubusercontent.com/ellite/scrob/main/docker-compose.yaml\n```\n\n2. Edit `docker-compose.yaml` and replace the required values:\n\n```yaml\nservices:\n  scrob-db:\n    container_name: scrob-db\n    image: postgres:16-alpine\n    restart: unless-stopped\n    environment:\n      POSTGRES_USER: scrob\n      POSTGRES_PASSWORD: changeme        # ← change this\n      POSTGRES_DB: scrob\n    volumes:\n      - db_data:/var/lib/postgresql/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U scrob -d scrob\"]\n      interval: 5s\n      timeout: 5s\n      retries: 10\n\n  scrob:\n    container_name: scrob\n    image: bellamy/scrob:latest\n    restart: unless-stopped\n    depends_on:\n      scrob-db:\n        condition: service_healthy\n    ports:\n      - \"7330:7330\"\n    environment:\n      DATABASE_URL: postgresql+asyncpg://scrob:changeme@scrob-db:5432/scrob   # ← match password above\n      SECRET_KEY: changeme               # ← generate with: openssl rand -hex 32\n      TZ: UTC\n    volumes:\n      - scrob_data:/app/backend/data\n\nvolumes:\n  db_data:\n  scrob_data:\n```\n\n3. Start:\n\n```bash\ndocker compose up -d\n```\n\n### Docker Run\n\n```bash\n# Create a dedicated network\ndocker network create scrob-net\n\n# Start the database\ndocker run -d \\\n  --name scrob-db \\\n  --network scrob-net \\\n  --restart unless-stopped \\\n  -e POSTGRES_USER=scrob \\\n  -e POSTGRES_PASSWORD=changeme \\\n  -e POSTGRES_DB=scrob \\\n  -v scrob_db:/var/lib/postgresql/data \\\n  postgres:16-alpine\n\n# Start Scrob\ndocker run -d \\\n  --name scrob \\\n  --network scrob-net \\\n  --restart unless-stopped \\\n  -p 7330:7330 \\\n  -e DATABASE_URL=\"postgresql+asyncpg://scrob:changeme@scrob-db:5432/scrob\" \\\n  -e SECRET_KEY=\"$(openssl rand -hex 32)\" \\\n  -e TZ=UTC \\\n  bellamy/scrob:latest\n```\n\n### First Setup\n\n1. Open `http://localhost:7330` and create your account.\n2. Go to **Settings → Integrations** to add your TMDB API key and connect Jellyfin, Plex, or Emby.\n3. Select which libraries to sync, then trigger your first sync from **Settings → Sync**.\n\n### Updating\n\n```bash\ndocker compose pull \u0026\u0026 docker compose up -d\n```\n\nDatabase migrations run automatically on startup — no manual steps required.\n\n## Configuration\n\n| Variable | Default | Description |\n|---|---|---|\n| `SECRET_KEY` | — | **Required.** JWT signing key. Generate with `openssl rand -hex 32`. |\n| `DATABASE_URL` | — | **Required.** PostgreSQL connection string (`postgresql+asyncpg://...`). |\n| `ENABLE_REGISTRATIONS` | `true` | Allow new users to register. The first user can always register regardless of this setting. |\n| `REGISTRATION_MAX_ALLOWED_USERS` | `0` | Maximum number of registered users. `0` = unlimited. |\n| `TZ` | `UTC` | Container timezone (e.g. `Europe/Lisbon`). |\n| `PUID` | `1000` | User ID to run the process as. |\n| `PGID` | `1000` | Group ID to run the process as. |\n| `BACKEND_PORT` | `7331` | Internal port the backend binds to. Override only if `7331` conflicts on bare metal. |\n| `OIDC_ENABLED` | `false` | Enable OIDC login. |\n| `OIDC_DISABLE_PASSWORD_LOGIN` | `false` | Enforce OIDC-only login (disables username/password). |\n\nSee `docker-compose.yaml` for the full list of OIDC variables and other variables.\n\n### Reverse proxy\n\nScrob listens on port `7330`. Place a reverse proxy (Caddy, Nginx, Traefik) in front for HTTPS — required for the PWA install prompt on non-localhost addresses.\n\n```\n# Caddyfile\nscrob.yourdomain.com {\n    reverse_proxy localhost:7330\n}\n```\n\n### External PostgreSQL\n\nRemove the `scrob-db` service and set `DATABASE_URL` to your existing instance:\n\n```yaml\nDATABASE_URL: postgresql+asyncpg://user:password@your-db-host:5432/scrob\n```\n\n## Webhooks (Real-time Scrobbling)\n\nWebhooks update your watch history and Continue Watching in real time. Each user's webhook URL is shown in **Settings** next to the relevant integration.\n\n```\nhttps://your-scrob-url/api/proxy/webhooks/{jellyfin|plex|emby}?api_key=YOUR_API_KEY\n```\n\n### Jellyfin\n\n1. In Jellyfin, go to **Dashboard → Plugins → Catalogue**, install **Webhook**, then restart.\n2. Go to **Dashboard → Plugins → Webhook → Add Generic Destination**.\n3. Paste your Scrob Jellyfin webhook URL.\n4. Enable notification types: `Playback Start`, `Playback Progress`, `Playback Stop`, `Mark Played`.\n5. Enable item types: `Movies` and `Episodes`.\n6. **Leave the Template field blank** and check **\"Send all properties (ignore templates)\"**.\n\n\u003e Do not use a custom template — Jellyfin's template engine produces invalid JSON. \"Send all properties\" sends a well-formed payload that Scrob parses correctly.\n\n### Plex\n\nPlex webhooks require a **Plex Pass** subscription.\n\n1. Go to [plex.tv/account](https://www.plex.tv/account/) → **Webhooks → Add Webhook**.\n2. Paste your Scrob Plex webhook URL.\n3. In Scrob → Settings, enter your **Plex username** so events are attributed to the right account.\n\n### Emby\n\n1. In Emby, go to **Dashboard → Notifications → Add Notification → Webhook**.\n2. Paste your Scrob Emby webhook URL.\n3. Enable events: `Playback Start`, `Playback Progress`, `Playback Stop`.\n\n## OIDC / Single Sign-On\n\nScrob supports any OpenID Connect provider (Authelia, Authentik, Keycloak, Google, etc.).\n\n```yaml\nOIDC_ENABLED: \"true\"\nOIDC_PROVIDER_NAME: \"Authelia\"\nOIDC_CLIENT_ID: \"scrob\"\nOIDC_CLIENT_SECRET: \"your-secret\"\nOIDC_AUTH_URL: \"https://auth.yourdomain.com/api/oidc/authorization\"\nOIDC_TOKEN_URL: \"https://auth.yourdomain.com/api/oidc/token\"\nOIDC_USERINFO_URL: \"https://auth.yourdomain.com/api/oidc/userinfo\"\nOIDC_REDIRECT_URL: \"https://scrob.yourdomain.com/oidc-callback\"\nOIDC_AUTO_CREATE_USERS: \"true\"\n# OIDC_DISABLE_PASSWORD_LOGIN: \"true\"  # uncomment to enforce SSO-only\n```\n\nRegister Scrob as a client in your provider with redirect URI: `https://scrob.yourdomain.com/oidc-callback`\n\n## Contributing\n\nContributions are welcome — whether it's a bug report, a feature request, or a pull request.\n\n- **Issues**: Open an issue for bugs, questions, or feature ideas.\n- **Pull Requests**: Fork the repo, create a branch, and submit a PR. Please follow the existing code style (Astro components for UI, FastAPI for backend) and make sure all browser-initiated API calls go through `/api/proxy/`.\n\nCommit messages follow [Conventional Commits](https://www.conventionalcommits.org/) — `feat:`, `fix:`, `chore:` — as releases and changelogs are generated automatically from them.\n\n## Contributors\n\n\u003ca href=\"https://github.com/ellite/scrob/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=ellite/scrob\" /\u003e\n\u003c/a\u003e\n\n## Development\n\n\u003cdetails\u003e\n\u003csummary\u003eView instructions\u003c/summary\u003e\n\n### Requirements\n\n- Python 3.12+, [uv](https://docs.astral.sh/uv/)\n- Node.js 22+\n- PostgreSQL 16 (via Docker is easiest)\n\n### Setup\n\n```bash\ngit clone https://github.com/ellite/scrob.git\ncd scrob\n\n# Start a local database\ndocker compose -f docker-compose-test-db.yaml up -d\n\n# Copy and fill in the environment file\ncp .env.exanple .env\n# Edit .env — set POSTGRES_* and SECRET_KEY at minimum\n```\n\n### Backend\n\n```bash\ncd backend\nuv sync\nuv run alembic upgrade head\nuv run uvicorn main:app --reload --port 7331\n```\n\n### Frontend\n\n```bash\ncd frontend\nnpm install\nnpm run dev\n```\n\nThe frontend dev server starts on `http://localhost:4321` and proxies API calls to the backend on `7331`.\n\n\u003c/details\u003e\n\n## License\n\nScrob is licensed under the [GNU General Public License v3.0](LICENSE).\n\nYou are free to use, modify, and distribute Scrob, provided that any derivative works are also released under the GPLv3.\n\n## Links\n\n- The author: [henrique.pt](https://henrique.pt)\n- Scrob Landingpage: [scrob.app](https://scrob.app)\n- Join the conversation: [Discord Server](https://discord.gg/anex9GUrPW)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fellite%2Fscrob","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fellite%2Fscrob","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fellite%2Fscrob/lists"}