Enhanced subtitle management built on Bazarr
No tracking · Provider priority · OpenSubtitles.org web scraper · AI translation via OpenRouter (300+ LLMs) · API key encryption · batch translation · mass subtitle sync · 11 bulk operations · subtitle viewer · advanced table filters · security hardening · Python 3.14 · navy + amber dark theme
- Migration can be as simple as replacing the container image with
ghcr.io/lavx/bazarr:latestand starting the container - Back up your
/configdirectory first - Bazarr+ uses independent versioning starting at v2.0.0, unrelated to upstream version numbers
- Config changes made by Bazarr+ are not backwards-compatible with upstream Bazarr, so switching back requires restoring your backup
- Recommended: test with a copy of your config before committing to the switch
| Feature | Upstream Bazarr | Bazarr+ |
|---|---|---|
| Provider Priority | Rejected (62 votes) | Dual mode: priority order with early stop, or classic simultaneous |
| OpenSubtitles.org (Scraper) | Not available | Self-hosted FastAPI microservice via CloudScraper |
| AI Subtitle Translator (OpenRouter) | Not available | 300+ LLMs + any custom model ID |
| API Key Encryption | Not available | AES-256-GCM encryption for keys in transit |
| Translate from Missing Menu | Not available | Action menu on missing subs with source language picker |
| Batch Translation | Not available | Translate entire series/libraries from Wanted pages |
| Mass Subtitle Sync | Rejected (249 votes) | Bulk sync from Tasks page or Mass Edit, skips already-synced |
| Bulk Operations | One-at-a-time only | 11 batch actions: sync, translate, OCR fixes, common fixes, remove HI, remove tags, fix uppercase, reverse RTL, scan disk, search missing, upgrade (up to 10k items) |
| Dedicated Translator Settings | Not available | 4-zone page with pricing, cost estimates, status panel |
| No Tracking | GA4 + legacy UA phone home to Google | All telemetry removed, nothing phones home |
| Security Hardening | MD5, no CSRF/SSRF/rate limiting | PBKDF2 (600k iter), CSRF, SSRF, brute-force, 4 more |
| Subtitle Viewer | Not available | Read-only subtitle preview with SRT/VTT/ASS parsing, cue table, and format detection |
| Audio Language Display | Not shown in tables | Badges in all table views |
| Advanced Table Filters | No filters | Include/exclude audio, missing subtitle, title search |
| Floating Save + Ctrl+S | Not available | Sticky save button with 3-option unsaved changes modal |
| Navy + Amber Theme | Purple | #121125 navy to #fff8e1 cream, amber accents |
| OpenSubtitles.com (API) | Available | Available |
| Docker images | linuxserver.io / hotio | ghcr.io/lavx (self-built, multi-arch) |
| Python runtime | 3.8-3.13 | 3.14 |
# Clone with the scraper submodule
git clone --recursive https://github.com/LavX/bazarr.git
cd bazarr
# Configure your media paths in docker-compose.yml, then:
docker compose up -d
# Access Bazarr at http://localhost:6767# Pull all images
docker pull ghcr.io/lavx/bazarr:latest
docker pull ghcr.io/lavx/opensubtitles-scraper:latest
docker pull ghcr.io/lavx/ai-subtitle-translator:latest| Series with batch actions | Mass translate dialog |
|---|---|
![]() |
![]() |
| Series detail with fanart | Subtitle viewer |
|---|---|
![]() |
![]() |
| AI Translator settings |
|---|
![]() |
Feature Details
OpenSubtitles.org shut down their XML-RPC API for all third-party apps, VIP included. Bazarr+ ships a self-hosted FastAPI microservice that scrapes OpenSubtitles.org directly via CloudScraper with optional FlareSolverr fallback. It provides search, subtitle listing, and download endpoints (/api/v1/search, /api/v1/subtitles, /api/v1/download/subtitle) and integrates into Bazarr's provider system through a mixin class. No API key or VIP subscription needed.
Upstream Bazarr queries all subtitle providers simultaneously and picks the highest-scored result. There's no way to prefer one provider over another. This has been requested for 6 years (62 votes), but upstream rejected it as "won't happen," calling it a "major rework" that "would take months of development."
Bazarr+ solves it with a Provider Priority toggle in Settings > Providers. When enabled, providers are queried sequentially in the order you've arranged them. If a provider returns subtitles meeting the minimum score, Bazarr+ stops searching and uses those results. Your preferred providers (curated community sites, specialized language sources) always get first shot. When disabled, the original behavior is preserved: all providers queried simultaneously, best score wins.
Upstream has Google Translate, Gemini, and Lingarr. Bazarr+ adds OpenRouter as a fourth translator engine, giving access to 300+ LLMs (Claude, Gemini, GPT, LLaMA, Grok, and more) plus any custom model ID from openrouter.ai. It runs as a separate microservice with an async job queue supporting 1-5 concurrent jobs and 1-8 parallel batches. Features include:
- Translate from the subtitle action menu: click (...) on a missing subtitle row, pick an existing source subtitle to translate from
- Batch translation for entire series/movie libraries from the Wanted pages
- Dedicated settings page with 4 zones: engine picker, connection config, model tuning (temperature, reasoning mode, parallel batches), and a live status panel showing queue stats, job progress, token usage, cost, and speed
- Model details fetched live from the OpenRouter API with per-million token pricing, per-episode/movie cost estimates, context length, and prompt caching indicators
- AES-256-GCM encryption for API keys in transit between Bazarr and the translator service, with a Test Connection button that validates encryption and API key status before saving
- Auto disk scan triggers Sonarr/Radarr to rescan after translation completes
Read-only subtitle preview accessible from the subtitle action menu. Supports SRT, VTT, and ASS/SSA formats with automatic format detection. Shows a cue table with timestamps and text, file size, and format badge. Useful for quickly checking subtitle content and timing without downloading.
- Table filters on Wanted and Library pages: include/exclude audio language (multi-select), missing subtitle language filter, title search, with active filter chips and a collapsible filter panel
- Floating save button with Ctrl+S/Cmd+S keyboard shortcut, visible only when settings have unsaved changes
- Three-button unsaved changes modal: Save & Leave, Discard, or Keep Editing (upstream only has Leave/Stay)
- Navy + amber dark theme: custom color palette from
#121125(navy black) to#fff8e1(cream), with amber brand accents (#e68a00to#b36b00) - Audio language display as blue badges in all table views
Upstream lets you sync subtitles one at a time, or per-series via Mass Edit. But there's no way to sync your entire library at once. This has been requested for years (249 votes), but upstream rejected it as "won't happen," saying "Bazarr isn't a batch tool."
Bazarr+ adds two entry points for bulk sync:
- System Tasks page: a "Mass Sync All Subtitles" task with a Run button that syncs every subtitle in your library
- Mass Edit pages: a "Sync Subtitles" button for both Movies and Series editors, so you can select specific items and sync their subtitles in bulk
Both use the existing ffsubsync engine. Already-synced subtitles are skipped by default (with a force re-sync option). Configurable max offset, Golden-Section Search, and framerate correction settings.
Select multiple movies or series from the library pages and apply operations in batch. Available from the toolbar that appears when items are selected, or from the System Tasks page for library-wide runs. Confirmation is required for operations on 100+ items. Up to 10,000 items per batch.
Subtitle modifications (applied to all existing subtitles of selected items):
- Sync -- align subtitle timing to audio using ffsubsync, with configurable max offset (1-600s), Golden-Section Search, framerate correction, and force re-sync
- OCR Fixes -- correct common optical character recognition errors
- Common Fixes -- apply standard subtitle formatting and whitespace corrections
- Remove Hearing Impaired -- strip
[music],(doorbell rings), and similar HI annotations - Remove Style Tags -- remove
<i>,<b>,<font>and other formatting tags - Fix Uppercase -- convert ALL CAPS subtitles to proper case
- Reverse RTL -- fix right-to-left punctuation for Arabic, Hebrew, and similar languages
- Translate -- batch translate subtitles using any configured translator engine (Google, Gemini, Lingarr, or OpenRouter with 300+ LLMs)
Media operations (search and scan actions for selected items):
- Scan Disk -- rescan selected items for on-disk subtitle files
- Search Missing -- search all configured providers for missing subtitles
- Upgrade -- replace low-scoring subtitles with better matches from providers
Profile management:
- Bulk profile assignment -- select multiple movies or series and assign a language profile to all of them at once
Upstream Bazarr ships two analytics systems that phone home to Google: a GA4 property (G-3820T18GE3) in bazarr/utilities/analytics.py that reports your Bazarr version, Python version, Sonarr/Radarr versions, OS, subtitle provider usage, every download action, and languages searched, plus a legacy Universal Analytics tracker (UA-86466078-1) in the SubZero library dependency. Bazarr+ has removed both entirely. No usage data leaves your server.
8 areas upstream doesn't address:
- Password hashing: PBKDF2-SHA256 with 600,000 iterations and 16-byte random salt (upstream uses plain MD5)
- CSRF protection: cryptographic state tokens (
secrets.token_urlsafe(32)) on Plex OAuth with timing-safe validation - SSRF blocking: DNS pinning with IP validation, blocks loopback and link-local addresses, fails closed
- Brute-force protection: 5 failed attempts trigger 300-second lockout per IP, tracks up to 10,000 IPs with thread-safe OrderedDict
- Shell injection: replaced naive character escaping with
shlex.quote()(POSIX) andsubprocess.list2cmdline()(Windows) - Filesystem sandboxing: blocks
/proc,/sys,/dev,/etc,/root,/tmpand 4 others from the filesystem browser, resolves symlinks - eval() removal: replaced
eval()in throttled provider cache withjson.loads()to prevent arbitrary code execution - API key comparison:
hmac.compare_digest()for constant-time comparison (upstream uses Pythoninoperator, which is timing-dependent)
Dockerfile uses python:3.14-slim-bookworm. Upstream supports Python 3.8-3.13 and relies on third-party Docker images (LinuxServer.io, hotio). Bazarr+ builds and publishes its own multi-arch image to GHCR.
Installation and Configuration
Create a docker-compose.yml file:
services:
# FlareSolverr - Handles browser challenges for web scraping
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
restart: unless-stopped
ports:
- "8191:8191"
environment:
- LOG_LEVEL=info
opensubtitles-scraper:
image: ghcr.io/lavx/opensubtitles-scraper:latest
container_name: opensubtitles-scraper
restart: unless-stopped
depends_on:
- flaresolverr
ports:
- "8000:8000"
environment:
- FLARESOLVERR_URL=http://flaresolverr:8191/v1
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# AI Subtitle Translator Service (required for AI translation)
ai-subtitle-translator:
image: ghcr.io/lavx/ai-subtitle-translator:latest
container_name: ai-subtitle-translator
restart: unless-stopped
ports:
- "8765:8765"
environment:
# OpenRouter API key (can also be configured in Bazarr UI)
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
- OPENROUTER_DEFAULT_MODEL=google/gemini-2.5-flash-lite-preview-09-2025
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8765/health"]
interval: 30s
timeout: 10s
retries: 3
# Bazarr+
bazarr:
image: ghcr.io/lavx/bazarr:latest
container_name: bazarr
restart: unless-stopped
depends_on:
opensubtitles-scraper:
condition: service_healthy
ai-subtitle-translator:
condition: service_healthy
ports:
- "6767:6767"
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Budapest
# Point to the scraper service (port 8000)
- OPENSUBTITLES_SCRAPER_URL=http://opensubtitles-scraper:8000
volumes:
- ./config:/config
- /path/to/movies:/movies
- /path/to/tv:/tv
networks:
default:
name: bazarr-networkThen run:
docker compose up -d| Variable | Default | Description |
|---|---|---|
PUID |
1000 |
User ID for file permissions |
PGID |
1000 |
Group ID for file permissions |
TZ |
UTC |
Timezone (e.g., Europe/Budapest) |
OPENSUBTITLES_SCRAPER_URL |
http://opensubtitles-scraper:8000 |
OpenSubtitles.org scraper service URL (port 8000, not 8765) |
| Path | Description |
|---|---|
/config |
Bazarr configuration and database |
/movies |
Movies library (match your Radarr path) |
/tv |
TV shows library (match your Sonarr path) |
- Go to Settings > Providers
- Enable "OpenSubtitles.org" (not OpenSubtitles.com, that's the API version)
- Set the scraper service URL (or use the
OPENSUBTITLES_SCRAPER_URLenv var) - Save and test with a manual search
- Go to Settings > AI Translator
- Select "AI Subtitle Translator" as the translator engine
- Enter your OpenRouter API Key (get one at openrouter.ai/keys)
- Choose your preferred AI Model (Google: Gemini 2.5 Flash Lite Preview 09-2025 recommended)
- Save and test with a manual translation
Architecture
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Docker Network │
│ │
│ ┌────────────────────────┐ ┌───────────────────────┐ ┌─────────────┐ │
│ │ Bazarr │ │ OpenSubtitles Scraper │ │ AI Sub │ │
│ │ (Bazarr+) │ │ (Port 8000) │ │ Translator │ │
│ │ │ │ │ │ (Port 8765) │ │
│ │ ┌──────────────────┐ │ HTTP │ ┌─────────────────┐ │ │ │ │
│ │ │ OpenSubtitles.org│──┼──────┼──│ Search API │ │ │ ┌─────────┐ │ │
│ │ │ Provider │ │ API │ │ Download API │ │ │ │Translate│ │ │
│ │ └──────────────────┘ │ │ └─────────────────┘ │ │ │ API │ │ │
│ │ │ │ │ │ │ │Job Queue│ │ │
│ │ ┌──────────────────┐ │ HTTP │ ▼ │ │ └────┬────┘ │ │
│ │ │ AI Subtitle │──┼──────┼──────────────────────────────┼──────┘ │ │
│ │ │ Translator │ │ API │ ┌─────────────────┐ │ │ │ │ │
│ │ └──────────────────┘ │ │ │ Web Scraper │ │ │ ▼ │ │
│ │ │ │ │opensubtitles.org│ │ │ ┌─────────┐ │ │
│ │ Port 6767 (WebUI) │ │ └─────────────────┘ │ │ │OpenRoute│ │ │
│ └────────────────────────┘ └───────────────────────┘ │ │ API │ │ │
│ │ └─────────┘ │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
Note: The scraper service can optionally use FlareSolverr (port 8191) to handle browser challenges. See the Docker Compose example above for the full setup.
Troubleshooting
# Check if scraper is healthy
curl http://localhost:8000/health
# Check scraper logs
docker logs opensubtitles-scraper
# Test a search (POST request format)
curl -X POST http://localhost:8000/search \
-H "Content-Type: application/json" \
-d '{"criteria":[{"imdbid":"0111161"}]}'| Issue | Solution |
|---|---|
| "Connection refused" | Ensure scraper is running and healthy |
| "No subtitles found" | Check IMDB ID is correct, try different language |
| Provider not showing | Enable it in Settings > Providers |
| Wrong file permissions | Check PUID/PGID match your user |
Supported Subtitle Providers
Includes all upstream providers plus fork additions:
- Addic7ed
- AnimeKalesi
- Animetosho (requires AniDb HTTP API client)
- AnimeSub.info
- Assrt
- AvistaZ, CinemaZ
- BetaSeries
- BSplayer
- Embedded Subtitles
- Gestdown.info
- GreekSubs
- GreekSubtitles
- HDBits.org
- Hosszupuska
- Karagarga.in
- Ktuvit (Get
hashed_passwordusing method described here) - LegendasDivx
- Legendas.net
- Napiprojekt
- Napisy24
- Nekur
- OpenSubtitles.com
- OpenSubtitles.org (Bazarr+ web scraper, no API needed)
- Podnapisi
- RegieLive
- Sous-Titres.eu
- SubX
- subf2m.co
- Subs.sab.bz
- Subs4Free
- Subs4Series
- Subscene
- Subscenter
- SubsRo
- Subsunacs.net
- SubSynchro
- Subtitrari-noi.ro
- subtitri.id.lv
- Subtitulamos.tv
- Supersubtitles
- Titlovi
- Titrari.ro
- Titulky.com
- Turkcealtyazi.org
- TuSubtitulo
- TVSubtitles
- Whisper (requires whisper-asr-webservice)
- Wizdom
- XSubs
- Yavka.net
- YIFY Subtitles
- Zimuku
About the Maintainer
This fork is maintained by LavX. Explore more projects and services:
- LavX Managed Systems -- Enterprise AI solutions, RAG systems, and LLMOps.
- LavX News -- Latest insights on AI, Open Source, and emerging tech.
- LMS Tools -- 140+ free, privacy-focused online tools for developers and researchers.
- AI Subtitle Translator -- LLM-powered subtitle translator using OpenRouter API.
- OpenSubtitles Scraper -- Web scraper for OpenSubtitles.org (no VIP required).
- JFrog to Nexus OSS -- Automated migration tool for repository managers.
- WeatherFlow -- Multi-platform weather data forwarding (WU to Windy/Idokep).
- Like4Like Suite -- Social media automation and engagement toolkit.
- Fork Maintenance Guide - How sync works
- OpenSubtitles Scraper - Scraper docs
- AI Subtitle Translator - AI translator docs
- Bazarr Wiki - General Bazarr documentation
Contributions are welcome! See CONTRIBUTING.md for the full guide.
- Fork this repository
- Create a feature branch from
development - Submit a PR targeting
development
For major changes, please open an issue first to discuss.
- GNU GPL v3
- Based on Bazarr by morpheus65535
- Fork modifications Copyright 2025-2026 LavX






