developer-tools

Is Frigate NVR Down? Real-Time Status & Outage Checker

Is Frigate NVR Down? Real-Time Status & Outage Checker

Frigate is an open-source network video recorder with real-time AI object detection, boasting over 20,000 GitHub stars. Built by Blake Blashear and maintained by a growing community, it is designed from the ground up for Home Assistant integration — emitting MQTT events that trigger automations when people, cars, or animals are detected. Frigate uses Google Coral TPU or GPU acceleration for hardware-accelerated inference, keeping detection latency under 10 ms per frame on supported hardware. It supports RTSP camera streams with sub-stream detection for efficiency, stores clips and snapshots locally, and provides a polished web UI for reviewing events. Used by home security enthusiasts, small business owners, and smart home builders who want private, cloud-free surveillance.

Frigate failures are especially high-stakes because they are often silent: a camera feed can drop to 0 FPS while the UI still loads, the Coral TPU can fail over to CPU without an alert, and a full disk stops recording without notifying anyone. Proactive monitoring of camera FPS, detector inference time, and storage capacity is essential for reliable home security coverage.

Quick Status Check

#!/bin/bash
# Frigate NVR health check
# Usage: bash check-frigate.sh [host] [port]

HOST="${1:-localhost}"
PORT="${2:-5000}"
BASE_URL="http://${HOST}:${PORT}"

echo "=== Frigate NVR Health Check ==="
echo "Target: ${BASE_URL}"
echo ""

# 1. Check Frigate version endpoint
echo "[1/5] Checking Frigate version..."
VERSION=$(curl -sf --max-time 5 "${BASE_URL}/api/version" 2>/dev/null)
if [ -n "${VERSION}" ]; then
  echo "  OK  Version: ${VERSION}"
else
  echo "  FAIL  /api/version unreachable — Frigate may be down"
fi

# 2. Check stats endpoint and camera FPS
echo "[2/5] Checking camera stats..."
STATS=$(curl -sf --max-time 8 "${BASE_URL}/api/stats" 2>/dev/null)
if [ -n "${STATS}" ]; then
  echo "  OK  /api/stats responded"
  # Check for any camera with fps=0
  if echo "${STATS}" | grep -q '"camera_fps":0'; then
    echo "  WARN  One or more cameras reporting 0 FPS — RTSP feed may be lost"
  else
    echo "  OK  All cameras reporting non-zero FPS"
  fi
else
  echo "  FAIL  /api/stats unreachable"
fi

# 3. Check process / Docker container
echo "[3/5] Checking process/container..."
if docker ps --format '{{.Names}}' 2>/dev/null | grep -qi "frigate"; then
  echo "  OK  Frigate Docker container is running"
elif pgrep -f "frigate" > /dev/null 2>&1; then
  echo "  OK  Frigate process is running"
else
  echo "  WARN  No Frigate container or process detected"
fi

# 4. Check MQTT if configured (port 1883)
echo "[4/5] Checking MQTT broker connectivity..."
MQTT_HOST="${MQTT_HOST:-localhost}"
if nc -z -w3 "${MQTT_HOST}" 1883 2>/dev/null; then
  echo "  OK  MQTT broker reachable at ${MQTT_HOST}:1883"
else
  echo "  WARN  MQTT broker not reachable at ${MQTT_HOST}:1883 — Home Assistant events will not fire"
fi

# 5. Check port is listening
echo "[5/5] Checking port ${PORT}..."
if nc -z -w3 "${HOST}" "${PORT}" 2>/dev/null; then
  echo "  OK  Port ${PORT} is open"
else
  echo "  FAIL  Port ${PORT} not reachable"
fi

echo ""
echo "=== Check complete ==="

Python Health Check

#!/usr/bin/env python3
"""
Frigate NVR health check
Verifies API availability, per-camera FPS, detector performance,
configuration integrity, and storage usage.
"""

import sys
import json
import urllib.request
import urllib.error

BASE_URL = "http://localhost:5000"
TIMEOUT = 10
FPS_WARN = 0          # warn if camera FPS at or below this
INFERENCE_WARN_MS = 100  # warn if detector inference time exceeds this
STORAGE_WARN_PCT = 90    # warn if recordings storage used > this percent


def fetch(url):
    try:
        req = urllib.request.Request(url, headers={"Accept": "application/json"})
        with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        return {"_error": f"HTTP {e.code}"}
    except Exception as e:
        return {"_error": str(e)}


results = []
print("=== Frigate NVR Health Check ===")
print(f"Target: {BASE_URL}\n")

# 1. Version
print("[1/5] API version...")
r = fetch(f"{BASE_URL}/api/version")
if "_error" in r:
    print(f"  [FAIL] /api/version: {r['_error']}")
    results.append(False)
else:
    version = r if isinstance(r, str) else r.get("version", str(r))
    print(f"  [OK  ] Frigate version: {version}")
    results.append(True)

# 2. Stats — per-camera FPS and detector inference time
print("[2/5] Camera FPS & detector stats...")
r = fetch(f"{BASE_URL}/api/stats")
if "_error" in r:
    print(f"  [FAIL] /api/stats: {r['_error']}")
    results.append(False)
else:
    cameras = {k: v for k, v in r.items()
               if isinstance(v, dict) and "camera_fps" in v}
    detectors = r.get("detectors", {})
    service = r.get("service", {})

    camera_ok = True
    for cam_name, cam_data in cameras.items():
        fps = cam_data.get("camera_fps", 0)
        det_fps = cam_data.get("detection_fps", 0)
        skipped = cam_data.get("skipped_fps", 0)
        level = "OK  " if fps > FPS_WARN else "FAIL"
        print(f"  [{level}] Camera '{cam_name}': {fps:.1f} FPS capture, "
              f"{det_fps:.1f} FPS detection, {skipped:.1f} FPS skipped")
        if fps <= FPS_WARN:
            print(f"       Warning: camera '{cam_name}' FPS is 0 — RTSP stream may be lost")
            camera_ok = False

    if not cameras:
        print("  [WARN] No cameras found in stats — check Frigate config")
        camera_ok = False

    results.append(camera_ok)

    # Detector inference time
    det_ok = True
    for det_name, det_data in detectors.items():
        if isinstance(det_data, dict):
            inf_ms = det_data.get("inference_speed", 0) * 1000
            level = "OK  " if inf_ms < INFERENCE_WARN_MS else "WARN"
            print(f"  [{level}] Detector '{det_name}': {inf_ms:.1f} ms inference")
            if inf_ms >= INFERENCE_WARN_MS:
                print(f"       Warning: slow inference — Coral TPU may not be active (falling back to CPU)")
                det_ok = False
    results.append(det_ok)

    # Storage from service stats
    storage = service.get("storage", {})
    if storage:
        for path, info in storage.items():
            if isinstance(info, dict):
                total = info.get("total", 0)
                used = info.get("used", 0)
                pct = int(used / total * 100) if total > 0 else 0
                level = "OK  " if pct < STORAGE_WARN_PCT else "WARN"
                print(f"  [{level}] Storage '{path}': {pct}% used "
                      f"({used // (1024**3):.1f} GB / {total // (1024**3):.1f} GB)")
                if pct >= STORAGE_WARN_PCT:
                    print(f"       Warning: storage > {STORAGE_WARN_PCT}% — recordings may stop or clip retention aggressive")

# 3. Config — camera count
print("[3/5] Configuration...")
r = fetch(f"{BASE_URL}/api/config")
if "_error" in r:
    print(f"  [FAIL] /api/config: {r['_error']}")
    results.append(False)
else:
    cam_count = len(r.get("cameras", {}))
    detector_count = len(r.get("detectors", {}))
    print(f"  [OK  ] Config loaded: {cam_count} camera(s), {detector_count} detector(s) configured")
    results.append(True)

# 4. Per-camera recording check — query recent events
print("[4/5] Recent event activity...")
r = fetch(f"{BASE_URL}/api/events?limit=5")
if "_error" in r:
    print(f"  [WARN] /api/events: {r['_error']} — event history unavailable")
    results.append(True)  # non-critical
else:
    event_count = len(r) if isinstance(r, list) else 0
    print(f"  [OK  ] Event API responded: {event_count} recent event(s) returned")
    results.append(True)

# 5. Summary check
passed = sum(results)
total = len(results)
print(f"\n=== Summary: {passed}/{total} checks passed ===")
if passed < total:
    print("Action required: review FAIL/WARN items above.")
    sys.exit(1)
else:
    print("Frigate NVR appears healthy.")
    sys.exit(0)

Common Frigate NVR Outage Causes

SymptomLikely CauseResolution
Camera shows 0 FPS in stats; no new clips or snapshots recorded RTSP stream lost — camera offline, network issue, or incorrect stream URL Test RTSP URL directly with VLC or ffprobe; check camera firmware; verify network path from Frigate host to camera
High CPU usage; detection inference time spikes to 500–1000 ms Coral TPU not detected — USB disconnect, driver issue, or container privilege missing Verify Coral USB is enumerated (lsusb); check container has privileged: true or correct device passthrough; reinstall Coral runtime
No new clips being saved; disk usage static despite active cameras Storage disk full — recordings disk at 100%, new clips cannot be written Increase retain settings to be more aggressive; add storage; check record.retain configuration; free disk space
Home Assistant automations not triggering on detections; no MQTT events MQTT broker disconnected — broker restarted, credentials changed, or network issue Verify MQTT broker is running; check Frigate MQTT config credentials; review Frigate logs for MQTT connection errors
Camera feed shows in UI but is delayed or frozen; CPU elevated ffmpeg crash — ffmpeg process died and failed to restart for a camera stream Check Frigate logs for ffmpeg errors; verify camera sub-stream settings; restart Frigate to force ffmpeg process recreation
Cameras active but no objects ever detected; detection FPS near 0 Detection model not loaded or detector process crashed on startup Check Frigate startup logs for model loading errors; verify model file integrity; confirm detector hardware is available and accessible

Architecture Overview

ComponentFunctionFailure Impact
Frigate Python service Orchestrates all camera processes, detection, recording, and API Complete loss of NVR functionality; no recording, detection, or UI
ffmpeg (per camera) Decodes RTSP streams; extracts frames for detection and recording Affected camera shows 0 FPS; no clips or snapshots for that feed
Object detector (Coral TPU / GPU / CPU) Runs TFLite model on frames to detect people, cars, animals No detections; high CPU if fallen back to CPU inference
MQTT broker Publishes detection events for Home Assistant automations HA automations stop firing; Frigate continues recording internally
Local storage (recordings) Stores video clips and snapshot images on local disk Disk full stops new recordings; events still detected but not saved
Frigate web UI Event browser, live view, camera stats, and configuration review Cannot review events or live feeds; background operation continues

Uptime History

DateIncident TypeDurationImpact
Feb 2026 Docker image update changed Coral runtime path; TPU not detected 2–8 hrs (until config fix) All detection fell back to CPU; 10–40x slower inference; high CPU load across all instances
Nov 2025 MQTT broker certificate renewal caused authentication failure 1–4 hrs Home Assistant stopped receiving detection events; recording continued normally
Sep 2025 Storage disk reached 100%; recording silently stopped for all cameras Variable (until disk freed) No new clips saved; events logged in UI but video unavailable; security gap during downtime
Jul 2025 Camera firmware update changed RTSP stream format; ffmpeg crash loop 30 min–3 hrs per camera Affected cameras showed 0 FPS; required manual RTSP URL or ffmpeg input arg update

Monitor Frigate NVR Automatically

Frigate has no built-in outage alerting — a camera dropping to 0 FPS, a full disk, or a Coral TPU falling back to CPU can go unnoticed for days in a home security context. ezmon.com monitors your Frigate NVR endpoints from multiple external probes and alerts your team via Slack, PagerDuty, or SMS the moment the stats API goes dark or a camera feed stops reporting frames.

Set up Frigate NVR monitoring free at ezmon.com →

frigatenvrhome-assistantobject-detectionsecurity-camerastatus-checker