Is Prowlarr Down? Real-Time Status & Outage Checker
Is Prowlarr Down? Real-Time Status & Outage Checker
Prowlarr is an open-source indexer manager and proxy for the *arr suite with 4,000+ GitHub stars. It centralizes indexer management for Sonarr, Radarr, Lidarr, and Readarr — supporting 500+ Usenet and torrent indexers and syncing configuration automatically to all connected *arr apps via API. Prowlarr replaces the older Jackett proxy and is the hub of any automated media server stack. When Prowlarr goes down, all connected *arr apps lose their indexer access simultaneously: Sonarr can't find new TV episodes, Radarr can't find new movies, and the entire automated media pipeline stalls.
Prowlarr runs on port 9696 and exposes a v1 REST API. Because a single Prowlarr failure cascades to every downstream *arr app, it is the highest-priority component to monitor in a home media server stack.
Quick Status Check
#!/bin/bash
# Prowlarr health check
# Usage: PROWLARR_API_KEY=your_key ./prowlarr-check.sh
PROWLARR_HOST="${PROWLARR_HOST:-http://localhost:9696}"
PROWLARR_API_KEY="${PROWLARR_API_KEY:-your_api_key_here}"
PASS=0
FAIL=0
echo "=== Prowlarr Health Check ==="
echo "Host: $PROWLARR_HOST"
echo ""
# 1. Check process is running
if pgrep -x "Prowlarr" > /dev/null 2>&1 || pgrep -f "Prowlarr.exe" > /dev/null 2>&1; then
echo "[OK] Prowlarr process is running"
PASS=$((PASS+1))
else
echo "[FAIL] Prowlarr process not found"
FAIL=$((FAIL+1))
fi
# 2. Check port 9696 is open
if nc -z localhost 9696 2>/dev/null; then
echo "[OK] Port 9696 is open"
PASS=$((PASS+1))
else
echo "[FAIL] Port 9696 is not reachable"
FAIL=$((FAIL+1))
fi
# 3. Check system status API
STATUS=$(curl -sf --max-time 10 \
-H "X-Api-Key: $PROWLARR_API_KEY" \
"$PROWLARR_HOST/api/v1/system/status")
if [ $? -eq 0 ]; then
VERSION=$(echo "$STATUS" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
echo "[OK] API responding — Prowlarr v$VERSION"
PASS=$((PASS+1))
else
echo "[FAIL] /api/v1/system/status did not respond"
FAIL=$((FAIL+1))
fi
# 4. Check health endpoint for WARNING/ERROR items
HEALTH=$(curl -sf --max-time 10 \
-H "X-Api-Key: $PROWLARR_API_KEY" \
"$PROWLARR_HOST/api/v1/health")
if [ $? -eq 0 ]; then
ISSUE_COUNT=$(echo "$HEALTH" | grep -o '"type":"' | wc -l | tr -d ' ')
if [ "$ISSUE_COUNT" -eq 0 ]; then
echo "[OK] Health check clean — no issues reported"
else
echo "[WARN] Health check returned $ISSUE_COUNT issue(s):"
echo "$HEALTH" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 | while read -r msg; do
echo " - $msg"
done
fi
PASS=$((PASS+1))
else
echo "[FAIL] /api/v1/health did not respond"
FAIL=$((FAIL+1))
fi
# 5. Check indexer count
INDEXERS=$(curl -sf --max-time 10 \
-H "X-Api-Key: $PROWLARR_API_KEY" \
"$PROWLARR_HOST/api/v1/indexer")
if [ $? -eq 0 ]; then
COUNT=$(echo "$INDEXERS" | grep -o '"id":' | wc -l | tr -d ' ')
echo "[OK] $COUNT indexer(s) configured"
PASS=$((PASS+1))
else
echo "[FAIL] /api/v1/indexer did not respond"
FAIL=$((FAIL+1))
fi
echo ""
echo "=== Result: $PASS passed, $FAIL failed ==="
[ "$FAIL" -eq 0 ] && exit 0 || exit 1
Python Health Check
#!/usr/bin/env python3
"""
Prowlarr health check
Checks system status, health issues, indexer count, connected *arr apps, and live search.
"""
import os
import sys
import json
import urllib.request
import urllib.error
PROWLARR_HOST = os.environ.get("PROWLARR_HOST", "http://localhost:9696")
PROWLARR_API_KEY = os.environ.get("PROWLARR_API_KEY", "your_api_key_here")
HEADERS = {
"X-Api-Key": PROWLARR_API_KEY,
"Accept": "application/json",
}
results = []
failures = 0
def check(label, ok, detail=""):
global failures
status = "OK " if ok else "FAIL"
if not ok:
failures += 1
msg = f"[{status}] {label}"
if detail:
msg += f" — {detail}"
results.append(msg)
print(msg)
def api_get(path, timeout=15):
url = f"{PROWLARR_HOST}{path}"
req = urllib.request.Request(url, headers=HEADERS)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
return json.loads(resp.read().decode())
except urllib.error.HTTPError as e:
raise RuntimeError(f"HTTP {e.code} from {path}")
except Exception as e:
raise RuntimeError(f"Request failed: {e}")
print("=== Prowlarr Python Health Check ===")
print(f"Host: {PROWLARR_HOST}\n")
# 1. System status — version and OS
try:
status = api_get("/api/v1/system/status")
version = status.get("version", "unknown")
branch = status.get("branch", "unknown")
os_name = status.get("osName", "unknown")
check("System status API", True, f"v{version} ({branch}) on {os_name}")
except RuntimeError as e:
check("System status API", False, str(e))
# 2. Health endpoint — list WARNING or ERROR items
try:
health = api_get("/api/v1/health")
issues = [h for h in health if h.get("type") in ("warning", "error")]
if not issues:
check("Health endpoint", True, "no issues reported")
else:
check("Health endpoint", False, f"{len(issues)} issue(s) found")
for issue in issues:
print(f" [{issue.get('type','?').upper()}] {issue.get('message','')}")
except RuntimeError as e:
check("Health endpoint", False, str(e))
# 3. Indexer count — total and enabled
try:
indexers = api_get("/api/v1/indexer")
total = len(indexers) if isinstance(indexers, list) else 0
enabled = sum(1 for i in indexers if i.get("enable", False))
ok = enabled > 0
check(
"Indexers",
ok,
f"{total} configured, {enabled} enabled"
+ ("" if ok else " — no enabled indexers!"),
)
except RuntimeError as e:
check("Indexers", False, str(e))
# 4. Connected *arr apps
try:
apps = api_get("/api/v1/applications")
total_apps = len(apps) if isinstance(apps, list) else 0
synced = sum(1 for a in apps if a.get("syncLevel") not in (None, "disabled"))
check("Connected *arr apps", True, f"{total_apps} app(s) configured, {synced} with sync enabled")
except RuntimeError as e:
check("Connected *arr apps", False, str(e))
# 5. Live search test — verify at least one indexer responds
try:
results_data = api_get(
"/api/v1/search?query=test&indexerIds=0&type=search", timeout=30
)
hit_count = len(results_data) if isinstance(results_data, list) else 0
ok = hit_count > 0
check(
"Live search test",
ok,
f"{hit_count} result(s) returned"
+ ("" if ok else " — all indexers may be failing"),
)
except RuntimeError as e:
check("Live search test", False, str(e))
# Summary
print(f"\n=== Result: {len(results) - failures} passed, {failures} failed ===")
sys.exit(0 if failures == 0 else 1)
Common Prowlarr Outage Causes
| Symptom | Likely Cause | Resolution |
|---|---|---|
| Sonarr and Radarr both return zero search results | All Prowlarr indexers failing simultaneously | Check Prowlarr → Indexers → test each; look for red error icons indicating indexer-side issues |
| New indexer config not appearing in Sonarr/Radarr | App sync broken — API connection to *arr apps failed | Settings → Apps → test each connection; verify API keys match in both Prowlarr and the *arr app |
| Prowlarr crashes on startup or loses config | Database corruption after unclean shutdown | Stop Prowlarr; run sqlite3 prowlarr.db "PRAGMA integrity_check"; restore from backup |
| Specific indexers fail with 401/403 errors | Authentication failure — cookies or credentials expired on indexer site | Re-enter login credentials or refresh session cookies for the affected indexer in Prowlarr settings |
| Cloudflare-protected indexers all fail | FlareSolverr not running or misconfigured | Check FlareSolverr container is running; verify URL in Prowlarr → Settings → Indexers → FlareSolverr |
| Indexer returns errors after heavy use | Rate limiting by indexer — too many search requests | Reduce RSS sync frequency; enable search limits per indexer; stagger *arr app sync intervals |
Architecture Overview
| Component | Function | Failure Impact |
|---|---|---|
| Prowlarr Core (C#/.NET) | Main process — indexer proxy, API, app sync | Total failure; all downstream *arr apps lose indexer access |
| SQLite Database | Stores indexer definitions, credentials, and sync state | Crash on startup; indexer config and history lost if corrupted |
| Indexer Proxy Layer | Translates *arr Newznab/Torznab queries to indexer-specific formats | Searches succeed at API level but return no results from indexers |
| App Sync Engine | Pushes indexer config changes to connected Sonarr/Radarr/etc. | New or updated indexers not propagated to *arr apps |
| FlareSolverr Integration | Solves Cloudflare challenges for protected indexer sites | All CF-protected indexers fail; others continue working |
| RSS Sync Scheduler | Polls indexer RSS feeds on configured intervals | New releases not detected automatically; manual searches still work |
Uptime History
| Date | Incident Type | Duration | Impact |
|---|---|---|---|
| 2026-02 | FlareSolverr container crash | ~18 hrs undetected | All Cloudflare-protected indexers failed silently; Sonarr/Radarr returned no results |
| 2025-11 | App sync API key mismatch after Radarr upgrade | ~6 hrs | New indexers added to Prowlarr not reflected in Radarr |
| 2025-09 | Major indexer mass-credential expiry | ~4 hrs | 80% of indexers returned 401; searches severely degraded until cookies refreshed |
| 2025-07 | SQLite corruption after host reboot | ~1 hr (restore from backup) | Prowlarr offline; all indexer configuration required restore |
Monitor Prowlarr Automatically
Prowlarr is the single point of indexer failure for your entire *arr stack — when it goes down or its indexers silently start returning errors, Sonarr and Radarr both stop finding content, but neither app surfaces a clear alert. ezmon.com monitors your Prowlarr endpoints from multiple external probes and alerts your team via Slack, PagerDuty, or SMS the moment the API stops responding or health checks detect indexer failures.