Is SABnzbd Down? Real-Time Status & Outage Checker
Is SABnzbd Down? Real-Time Status & Outage Checker
SABnzbd is an open-source Usenet binary newsreader and download manager with 3,000+ GitHub stars and the standard Usenet download client for home media servers. It automates the full download pipeline — fetching NZB files, connecting to Usenet news servers, downloading, repairing with par2, and extracting with unrar. SABnzbd integrates with Sonarr, Radarr, Lidarr, and other *arr apps via its REST API, provides a web UI, RSS automation, and category-based post-processing. When SABnzbd goes down or loses its Usenet server connection, every *arr app loses its primary download backend and the entire automated media pipeline stalls.
SABnzbd exposes its REST API on port 8080. Monitoring the process, queue state, server connectivity, and disk space is the fastest way to catch the silent failures that can leave your download queue paused or stalled for hours undetected.
Quick Status Check
#!/bin/bash
# SABnzbd health check
# Usage: SAB_API_KEY=your_key ./sabnzbd-check.sh
SAB_HOST="${SAB_HOST:-http://localhost:8080}"
SAB_API_KEY="${SAB_API_KEY:-your_api_key_here}"
PASS=0
FAIL=0
echo "=== SABnzbd Health Check ==="
echo "Host: $SAB_HOST"
echo ""
# 1. Check process is running
if pgrep -f "SABnzbd" > /dev/null 2>&1 || pgrep -f "sabnzbd" > /dev/null 2>&1; then
echo "[OK] SABnzbd process is running"
PASS=$((PASS+1))
else
echo "[FAIL] SABnzbd process not found"
FAIL=$((FAIL+1))
fi
# 2. Check port 8080 is open
if nc -z localhost 8080 2>/dev/null; then
echo "[OK] Port 8080 is open"
PASS=$((PASS+1))
else
echo "[FAIL] Port 8080 is not reachable"
FAIL=$((FAIL+1))
fi
# 3. Check version API
VERSION_RESP=$(curl -sf --max-time 10 \
"$SAB_HOST/api?mode=version&apikey=$SAB_API_KEY&output=json")
if [ $? -eq 0 ]; then
VERSION=$(echo "$VERSION_RESP" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
echo "[OK] API responding — SABnzbd v$VERSION"
PASS=$((PASS+1))
else
echo "[FAIL] /api?mode=version did not respond"
FAIL=$((FAIL+1))
fi
# 4. Check queue state (paused is a warning)
QUEUE_RESP=$(curl -sf --max-time 10 \
"$SAB_HOST/api?mode=queue&apikey=$SAB_API_KEY&output=json")
if [ $? -eq 0 ]; then
PAUSED=$(echo "$QUEUE_RESP" | grep -o '"paused":[a-z]*' | cut -d: -f2)
SPEED=$(echo "$QUEUE_RESP" | grep -o '"kbpersec":"[^"]*"' | cut -d'"' -f4)
if [ "$PAUSED" = "true" ]; then
echo "[WARN] Queue is PAUSED — no downloads in progress"
else
echo "[OK] Queue is active — speed: ${SPEED:-0} KB/s"
fi
PASS=$((PASS+1))
else
echo "[FAIL] /api?mode=queue did not respond"
FAIL=$((FAIL+1))
fi
# 5. Check status (Usenet server connectivity)
STATUS_RESP=$(curl -sf --max-time 10 \
"$SAB_HOST/api?mode=status&apikey=$SAB_API_KEY&output=json")
if [ $? -eq 0 ]; then
echo "[OK] Status API accessible"
PASS=$((PASS+1))
else
echo "[FAIL] /api?mode=status 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
"""
SABnzbd health check
Checks version, download queue state, recent history fail rate, disk space,
and Usenet server connectivity.
"""
import os
import sys
import json
import urllib.request
import urllib.error
SAB_HOST = os.environ.get("SAB_HOST", "http://localhost:8080")
SAB_API_KEY = os.environ.get("SAB_API_KEY", "your_api_key_here")
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(mode, extra_params="", timeout=10):
url = f"{SAB_HOST}/api?mode={mode}&apikey={SAB_API_KEY}&output=json{extra_params}"
req = urllib.request.Request(url)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
data = json.loads(resp.read().decode())
# SABnzbd wraps errors in a "status": false response
if isinstance(data, dict) and data.get("status") is False:
raise RuntimeError(data.get("error", "API returned status: false"))
return data
except urllib.error.HTTPError as e:
raise RuntimeError(f"HTTP {e.code} from mode={mode}")
except RuntimeError:
raise
except Exception as e:
raise RuntimeError(f"Request failed: {e}")
print("=== SABnzbd Python Health Check ===")
print(f"Host: {SAB_HOST}\n")
# 1. Version — confirms API is reachable and key is valid
try:
version_data = api_get("version")
version = version_data.get("version", "unknown")
check("Version API", True, f"SABnzbd v{version}")
except RuntimeError as e:
check("Version API", False, str(e))
# 2. Queue — paused state, speed, and remaining data
try:
queue_data = api_get("queue")
queue = queue_data.get("queue", {})
paused = queue.get("paused", False)
speed = queue.get("kbpersec", "0")
mb_left = queue.get("mbleft", "0")
noofslots = int(queue.get("noofslots", 0))
ok = not paused
check(
"Download queue",
ok,
f"{noofslots} slot(s), {mb_left} MB remaining, {speed} KB/s"
+ (" [PAUSED]" if paused else ""),
)
if paused:
print(" [WARN] Queue is paused — downloads will not proceed until resumed")
except RuntimeError as e:
check("Download queue", False, str(e))
# 3. History — check recent fail rate
try:
history_data = api_get("history", "&limit=10")
slots = history_data.get("history", {}).get("slots", [])
failed = [s for s in slots if s.get("status") in ("Failed", "RepairFailed", "UnpkFailed")]
total = len(slots)
fail_count = len(failed)
ok = fail_count < 3
check(
"Recent history (last 10)",
ok,
f"{fail_count} failed of {total} recent downloads"
+ ("" if ok else " — high fail rate, check par2/unrar or server connection"),
)
for f in failed:
print(f" [FAIL] {f.get('name', 'unknown')} — {f.get('fail_message', 'unknown error')}")
except RuntimeError as e:
check("Recent history", False, str(e))
# 4. Status — disk space and Usenet server connectivity
try:
status_data = api_get("status")
status = status_data.get("status", {})
# Disk space
disk_free = status.get("diskspace1_norm", "unknown")
disk_total = status.get("diskspacetotal1_norm", "unknown")
# Server connectivity
servers = status.get("servers", [])
disconnected = [s for s in servers if not s.get("active", True)]
disk_ok = True
try:
free_gb = float(disk_free.split()[0]) if isinstance(disk_free, str) else disk_free
disk_ok = free_gb > 5
except (ValueError, TypeError, AttributeError):
pass
check(
"Disk free space",
disk_ok,
f"{disk_free} free of {disk_total}"
+ ("" if disk_ok else " — critically low, downloads may stop mid-way"),
)
server_ok = len(disconnected) == 0
check(
"Usenet server connectivity",
server_ok,
f"{len(servers) - len(disconnected)} of {len(servers)} server(s) connected"
+ ("" if server_ok else f" — {len(disconnected)} server(s) disconnected"),
)
for s in disconnected:
print(f" [WARN] Server '{s.get('serverId', 'unknown')}' is not active")
except RuntimeError as e:
check("Status (disk/servers)", False, str(e))
# Summary
print(f"\n=== Result: {len(results) - failures} passed, {failures} failed ===")
sys.exit(0 if failures == 0 else 1)
Common SABnzbd Outage Causes
| Symptom | Likely Cause | Resolution |
|---|---|---|
| All downloads fail with "480 Authentication required" | Usenet server credentials expired — username or password no longer valid | Config → Servers → update credentials; verify with your Usenet provider's account portal |
| Downloads stop mid-file, queue stalls | Disk full — no space remaining on the download drive | Run df -h; free space; check SABnzbd's disk space low threshold in Config → General |
| Downloads complete but archives not extracted | par2 repair failure — too many missing articles to reconstruct file | Check history for repair errors; try alternate Usenet providers for better retention; verify par2 is installed |
| Downloads complete but folders remain as .rar files | unrar not installed or broken — extraction step fails silently | Verify unrar is installed (which unrar); reinstall if missing; check SABnzbd logs for extraction errors |
| Usenet server connects but downloads fail with SSL errors | SSL certificate for Usenet news server expired or hostname mismatch | Config → Servers → verify SSL certificate settings; disable certificate verification temporarily to confirm; contact provider |
| Sonarr/Radarr report SABnzbd connection failed | API key changed in SABnzbd — *arr apps using old key | Copy new API key from SABnzbd Config → General; update in each *arr app under Settings → Download Clients |
Architecture Overview
| Component | Function | Failure Impact |
|---|---|---|
| SABnzbd Core (Python) | Main process — web UI, API, download scheduler, post-processing | Total failure; all downloads, repairs, and extractions stop |
| Usenet News Server Connection | NNTP connection to provider servers to fetch binary articles | All downloads fail immediately; queue builds up but no progress made |
| par2 Repair Engine | Repairs incomplete or corrupted Usenet article sets using parity data | Downloads with missing articles fail; complete downloads unaffected |
| unrar Extraction | Extracts multi-part RAR archives after successful download and repair | Downloaded files remain as compressed archives; media unusable by *arr apps |
| Download Storage | Temporary disk space for in-progress and completed downloads before import | Downloads stop when disk is full; mid-download files corrupted if abruptly stopped |
| *arr App Integration (REST API) | Receives NZB jobs from Sonarr/Radarr and reports completion status | *arr apps can't send new downloads or track completion; import pipeline stalls |
Uptime History
| Date | Incident Type | Duration | Impact |
|---|---|---|---|
| 2026-02 | Usenet server credentials expired | ~16 hrs undetected | All downloads failed with 480 authentication errors; large queue backlog accumulated |
| 2025-11 | Download disk reached capacity | ~4 hrs | In-progress downloads stopped mid-file; incomplete archives required re-download |
| 2025-09 | SABnzbd API key regenerated — *arr apps disconnected | ~8 hrs | Sonarr and Radarr unable to submit NZB files; grabbed releases queued internally only |
| 2025-07 | Usenet server SSL certificate expired | ~3 hrs | Encrypted connections to news server failed; all active downloads dropped |
Monitor SABnzbd Automatically
SABnzbd failures often go unnoticed for hours — the process runs normally while the Usenet server rejects credentials with a 480 error, the download queue sits paused, or disk space runs out and files stop mid-transfer. ezmon.com monitors your SABnzbd endpoints from multiple external probes and alerts your team via Slack, PagerDuty, or SMS the moment the API stops responding or the queue enters a paused or error state.