Huntarr2 tells your *arr apps to search for missing items and quality upgrades so you don't have to do it manually.
It connects to Sonarr, Radarr, Lidarr, and Whisparr (v2 and v3), finds monitored items with no file and items that haven't reached their quality cutoff, then triggers searches for them on a schedule. That's it. There is a web UI for configuration and viewing what it's doing.
- You add your *arr instances (URL + API key) through the web UI.
- On each instance's schedule, Huntarr2 checks its library for monitored items with no file and items below their quality cutoff.
- It tells the *arr app to search for a batch of those items, skipping anything searched recently.
- The pace adapts: empty results back off, large backlogs speed up, and an hourly search limit caps API load.
Batch size, cooldowns, search intervals, hourly limits, and search windows are all configurable globally or per instance.
Huntarr2 does not download anything itself. It just tells your existing *arr apps to look for items you are missing and better versions of what you already have.
Huntarr2 is meant to run as a Docker container alongside your *arr stack.
docker compose up -dThe web UI will be at http://localhost:9706.
On first start, an encryption key is generated automatically and saved to /config/encryption.key inside the container. This key encrypts your *arr API keys in the database. Keep the /config volume intact or you will lose access to stored API keys.
services:
huntarr2:
image: ghcr.io/refringe/huntarr2:latest
ports:
- '9706:9706'
volumes:
- huntarr2_config:/config
environment:
PUID: 1000
PGID: 1000
TZ: Etc/UTC
restart: unless-stopped
volumes:
huntarr2_config:Set the environment variables through your platform's UI. The container image has sensible defaults for everything. You just need to map /config to persistent storage and expose port 9706.
| Variable | Default | What it does |
|---|---|---|
PORT |
9706 |
HTTP listen port |
LOG_LEVEL |
info |
debug, info, warn, or error |
DATABASE_PATH |
/config/huntarr2.db |
Path to the SQLite database file |
SCHEDULER_TICK_SECS |
30 |
Seconds between scheduler ticks (minimum 5) |
ENCRYPTION_KEY |
auto-generated | 32-byte key as 64-char hex or base64. Auto-generated and persisted in /config/encryption.key if not set. Generate your own with openssl rand -hex 32 |
AUTH_USERNAME |
(empty) | HTTP Basic Auth username. Set both username and password to enable |
AUTH_PASSWORD |
(empty) | HTTP Basic Auth password |
PUID |
1000 |
UID to run as inside the container |
PGID |
1000 |
GID to run as inside the container |
TZ |
UTC |
Container timezone |
Optional. Set both AUTH_USERNAME and AUTH_PASSWORD to require HTTP Basic Authentication on all routes except the health check (/api/health). Leave both empty to run without authentication.
If you are exposing Huntarr2 to the internet, put it behind a reverse proxy with HTTPS.
nginx:
server {
listen 443 ssl;
server_name huntarr.example.com;
location / {
proxy_pass http://127.0.0.1:9706;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Caddy:
huntarr.example.com {
reverse_proxy 127.0.0.1:9706
}
Requires Go 1.27 or later.
make build # produces bin/huntarr2
make test # runs tests with the race detector
make lint # runs golangci-lint
make fmt-check # checks gofmt formattingFor local development with Docker:
docker compose down && make docker-build && make docker-upSee CONTRIBUTING.md.
