developer-tools

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

SymptomLikely CauseResolution
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

ComponentFunctionFailure 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

DateIncident TypeDurationImpact
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.

Set up SABnzbd monitoring free at ezmon.com →

sabnzbdusenetdownload-clientnzbself-hostedstatus-checker