Find the movies and TV shows missing from your media library — and fill the gaps in one click.
GAPS 2 connects to your Plex, Jellyfin, or Emby server, looks at what you own, and tells you what's missing from each collection or franchise. Own Alien (1979)? It flags Aliens (1986) and Alien³ (1992). Own Yellowstone? It surfaces 1883 and 1923. Then it can hand those titles straight to Radarr or Sonarr to download.
A modern, full-stack rewrite of the original GAPS (Gaps A Plex Server) — Python/Flask backend, Angular 19 frontend.
- Discover gaps automatically — point it at a library and it finds every incomplete collection (movies) and franchise (TV) for you
- Act on them instantly — send missing titles to Radarr/Sonarr to download, without leaving the app
- Set it and forget it — scheduled scans keep watch and notify you (Discord, Telegram, Email) when new gaps appear
- Runs anywhere — one-click Windows .exe, a single Docker container, or local dev — all from one port
Find what's missing
- Multi-server support — Plex (OAuth), Jellyfin, and Emby
- Find missing movies from TMDB collections, and missing TV shows from TheTVDB's official franchise lists
- Discover similar movies from a title you own, with owned/missing status powered by TMDB IDs
- Unified "Missing" view with a Movies / TV Shows toggle — browse a library, scan it for gaps, or click a single title to check just its collection/franchise
- Find gaps by actor/actress — search a performer (e.g. Will Smith) on the Actors page and see their full filmography split into what you own and what you're missing
Act on the results
- Send to Radarr / Sonarr — add missing movies (by TMDB id) and shows (by TheTVDB id) directly from the results
- Filter & refine — show/hide owned, hide future (unreleased) titles, ignore individual titles or whole collections
- Export gap lists to CSV/Excel
Automate & stay informed
- Independent scheduled scans for movies and TV, each with its own cadence
- Notifications via Discord, Telegram, and Email
- User preferences — default library, items per page, language, hide owned, and more
Deploy your way
- Responsive dark-themed UI (Angular 19 + Bootstrap 5)
- Dockerized deployment with persistent, encrypted configuration
- Windows standalone executable (single .exe via PyInstaller)
- Automated releases via GitHub Actions (Windows exe + Docker Hub + GitHub Container Registry)
Download GAPS-2.exe from the latest release and run it. The app opens in your browser at http://localhost:4277.
Pull from Docker Hub:
docker run -d -p 4277:4277 -v gaps2-data:/app/data primetime43/gaps-2:latestThe same image is also published to the GitHub Container Registry if you prefer to pull from there:
docker run -d -p 4277:4277 -v gaps2-data:/app/data ghcr.io/primetime43/gaps-2:latestOr use Docker Compose:
docker compose -f docker/docker-compose.yml up -dThe app will be available at http://localhost:4277.
Development builds: unreleased changes on the develop branch are published to both Docker Hub and the GitHub Container Registry on every push. Use these for testing upcoming features — they are not considered stable.
docker pull primetime43/gaps-2:develop
# or
docker pull ghcr.io/primetime43/gaps-2:developPersist
/app/data. GAPS encrypts saved settings (API keys, tokens, server URLs) inbackend/data/config.enc. The encryption key lives next to it as.config.key, so both files must be on a persistent volume — otherwise every container recreation generates a fresh key and the old config becomes unreadable. Thedocker runexample above and the Compose file already mount/app/data; if you write your own command (e.g. an unRAID template), make sure the mount is there. To override the key explicitly — for moving between hosts or sharing a config across replicas — set theGAPS2_CONFIG_KEYenvironment variable to a Fernet key (output ofpython -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())").
One-command launch:
- Windows: Double-click
run-dev.bat - Linux/Mac/Git Bash:
./run-dev.sh
This automatically sets up a Python virtual environment, installs all dependencies, and starts both servers.
Manual setup:
Prerequisites: Python 3.9+, Node.js 20+, a TMDB API key (for movies), and optionally a free TheTVDB v4 API key (for TV franchise scanning)
# Backend
cd backend
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate.bat # Windows
pip install -r requirements.txt
python run.py# Frontend
cd frontend
npm install
npm startThe Angular dev server starts at http://localhost:4200 and proxies API requests to the Flask backend at http://localhost:4277.
- Go to Settings > TMDB and enter your TMDB API key (required for movies)
- (Optional, for TV) Go to Settings > TheTVDB and enter your free TheTVDB API key
- Go to Settings > Plex/Jellyfin/Emby and connect your media server
- Go to Missing, choose Movies or TV Shows, pick a library, and click Scan for Gaps — or click a single title to check just its collection/franchise
- Go to Actors, search an actor or actress, and see which of their movies you own vs. are missing
- (Optional) Configure Radarr and/or Sonarr in Settings to send missing titles straight to your downloaders
- (Optional) Configure scheduled scans (separate cadences for movies and TV) and notifications in Settings
TheTVDB API key: create a free key on your TheTVDB dashboard. Some keys are tied to the User Subscription funding model and require your subscriber PIN; if so, GAPS will tell you, and you can enter the PIN on the TheTVDB settings page.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.










