How to Use Frigate's Profile System for Camera State Management: A Complete Guide

Frigate's profile system lets you define named configuration overrides for cameras and switch between them dynamically at runtime without restarting, enabling modes like "armed," "disarmed," or "night" through the activate_profile() method in ProfileManager.

Frigate's profile system provides a powerful mechanism for runtime camera state management, allowing users to toggle between predefined operating modes instantly. This feature eliminates the need to restart the service when changing detection sensitivity, enabling cameras, or modifying zone configurations. By leveraging the ProfileManager class and CameraProfileConfig models defined in the source code, you can implement complex security scenarios like home/away modes directly through the API or configuration files.

Architecture of the Profile System

The profile implementation centers on two core modules that handle configuration snapshots and state transitions:

  • frigate/config/camera/profile.py – Defines the CameraProfileConfig Pydantic model that holds optional overrides for each configurable camera section (detect, motion, objects, zones, etc.)
  • frigate/config/profile_manager.py – Orchestrates snapshotting of original camera configs, applying selected profiles, resetting to base configurations, and dispatching ZMQ updates to downstream components

When ProfileManager initializes, it immediately calls _snapshot_base_configs() to capture the unmodified state of every camera. This creates two internal stores: _base_configs containing the raw dictionary representations and _base_api_configs holding JSON-ready versions of detect, motion, record, zones, and other sections.

How Profile Activation Works

The activate_profile(name) method in ProfileManager executes a three-phase transition process:

  1. Reset Phase – Calls _reset_to_base() to restore every camera to its original snapshot state, including enabled flags and zone definitions
  2. Apply Phase – Invokes _apply_profile_overrides(name) which walks each camera's profiles dictionary, merges the specified profile's sections onto the base configs using deep_merge, and updates camera objects via apply_section_update
  3. Publish Phase – Triggers _publish_updates() to emit ZMQ messages only for sections that actually changed, notifying detection, motion, and recording components

Passing None to activate_profile() triggers a full reset to base configuration with no active profile. After successful activation, the manager persists the active profile name to CONFIG_DIR/.profiles (the PERSISTENCE_FILE), restoring it automatically on startup via load_persisted_profile().

Configuring Profiles in YAML

Define profiles in your top-level config.yml under the profiles key. Each profile specifies a friendly_name and per-camera overrides for any supported section:

profiles:
  armed:
    friendly_name: "Armed"
    camera:
      front:
        enabled: true
        motion:
          threshold: 0.5
        zones:
          driveway:
            coordinates: [[0,0],[640,0],[640,480],[0,480]]
  disarmed:
    friendly_name: "Disarmed"
    camera:
      front:
        enabled: false

Only sections listed in PROFILE_SECTION_UPDATES support overrides: audio, birdseye, detect, face_recognition, lpr, motion, notifications, objects, record, review, snapshots, and zones. Overrides are partial—any field left unset (None) inherits the camera's original base value.

Programmatic Profile Management

Interact with the profile system programmatically using the ProfileManager class alongside CameraConfigUpdatePublisher for ZMQ communication:


# Activate a profile from Python code

from frigate.config.profile_manager import ProfileManager
from frigate.config.config import FrigateConfig
from frigate.config.camera.updater import CameraConfigUpdatePublisher

# Assume `config` is the parsed FrigateConfig and `updater` is running

pm = ProfileManager(config, CameraConfigUpdatePublisher())
error = pm.activate_profile("armed")
if error:
    print("Failed:", error)
else:
    print("Profile 'armed' activated")

Reset all cameras to base configuration by passing None:


# Deactivate any active profile (reset to base)

pm.activate_profile(None)   # Resets all cameras to original config

Query current state through API helper methods:


# Query the currently active profile via the API helper

active = pm.get_profile_info()
print("Active profile:", active["active_profile"])
print("Available profiles:", [p["name"] for p in active["profiles"]])

Zone Handling and Merging Behavior

Zones require special handling during profile application because they are stored as ZoneConfig objects rather than plain dictionaries. When _apply_profile_overrides() processes zone overrides, it:

  • Merges the profile's zone dictionary onto the base zones configuration
  • Calls generate_contour to ensure each zone has valid coordinates
  • Preserves the original zone color if the profile omits the color field

This ensures that temporary profiles can modify zone geometry or disable specific zones without losing visual styling defined in the base configuration.

REST API Integration

The ProfileManager exposes helper methods that feed the REST API and WebSocket interfaces:

  • get_base_configs_for_api() – Returns the original unmodified configuration for reference
  • get_available_profiles() – Lists all profiles defined in the top-level configuration
  • get_profile_info() – Returns the active profile name and available options

These methods support the /api/config endpoint, allowing external home automation systems to query state and trigger profile changes via HTTP POST requests to /config/set with a profile parameter.

Summary

  • ProfileManager in frigate/config/profile_manager.py handles all runtime profile switching through activate_profile(), maintaining base configuration snapshots and managing ZMQ update publication.
  • CameraProfileConfig in frigate/config/camera/profile.py defines the override structure for per-camera settings including detect, motion, objects, and zones.
  • Profiles support partial overrides—unspecified fields inherit from base configuration, while specified fields replace base values completely.
  • The system persists active profiles to CONFIG_DIR/.profiles and automatically restores the last active state on Frigate startup.
  • Zone configurations merge specially to preserve contours and colors while allowing coordinate overrides.

Frequently Asked Questions

What sections of the camera configuration can profiles override?

Profiles can override any of the following sections as defined in PROFILE_SECTION_UPDATES: audio, birdseye, detect, face_recognition, lpr, motion, notifications, objects, record, review, snapshots, and zones. Each profile defines per-camera overrides for only the sections you want to change, leaving other settings at their base values.

How do I temporarily disable all detection without restarting Frigate?

Create a "disarmed" profile in your config.yml that sets enabled: false for your cameras, then activate it via the API or Python code using pm.activate_profile("disarmed"). To restore normal operation, call pm.activate_profile(None) to reset to base configuration or activate your "armed" profile.

Are profile changes persistent across Frigate restarts?

Yes. The ProfileManager automatically writes the active profile name to a hidden persistence file at CONFIG_DIR/.profiles after each successful activation. On startup, load_persisted_profile() reads this file and restores the last active profile, ensuring your cameras return to their intended state after system reboots.

Can I modify zones dynamically using profiles?

Yes. Profiles support zone overrides in the zones section. When applying a profile, the system merges your zone configuration onto the base zones, regenerates contours, and preserves original colors if not specified. This allows you to enable/disable specific zones or adjust their coordinates for different security modes without touching the base configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →