How to Export Recordings Using Frigate's Export API: Complete REST Guide
Frigate provides a FastAPI-based REST API in frigate/api/export.py that allows authenticated users to queue video exports, monitor job status via /jobs/export/{export_id}, and download archived cases as streaming ZIP files.
The export system in the blakeblackshear/frigate repository enables programmatic extraction of surveillance footage from any configured camera. Built around the ExportJob class in frigate/jobs/export.py, the API manages FFmpeg processing, storage path generation, and batch operations through a set of authenticated HTTP endpoints.
Export API Architecture
The export workflow operates through three distinct stages implemented across the codebase.
Authentication and Authorization
All export endpoints require valid user authentication. The require_camera_access decorator (defined in frigate/api/auth.py) validates that the requesting user has read access to the specified camera. Administrative privileges are required for operations that modify export cases or delete records.
Job Creation and Queuing
When you submit an export request, the API creates an ExportJob object through the _build_export_job helper function. This configuration includes the camera name, Unix timestamp range, optional friendly name, thumbnail image path, and playback source (either recordings or previews). The start_export_job function then enqueues this job onto Frigate's dedicated export queue for background processing.
Result Retrieval
After queuing, the API returns a unique export_id. You can query /jobs/export/{export_id} to track progress through states including queued, running, completed, or failed. Final files are accessible individually or bundled intoexport cases downloadable via the /cases/{case_id}/download endpoint.
Core Export Endpoints
The following routes in frigate/api/export.py handle all export operations:
Single Recording Export
The standard export endpoint creates MP4 clips from specific time ranges.
POST /api/export/{camera_name}/start/{start_time}/end/{end_time}
This route accepts an ExportRecordingsBody JSON payload defined in frigate/api/defs/request/export_recordings_body.py. Parameters include source (enum: recordings or previews), name (max 256 characters), image_path for thumbnails, and optional export_case_id for grouping.
Custom FFmpeg Export
For advanced users needing specific encoding parameters, the custom endpoint accepts additional FFmpeg arguments.
POST /api/export/custom/{camera_name}/start/{start_time}/end/{end_time}
This accepts ExportRecordingsCustomBody, extending the base model with ffmpeg_input_args, ffmpeg_output_args, and a boolean cpu_fallback flag. The validation logic in frigate/record/export.py ensures these arguments are properly formatted before job creation.
Batch Export Operations
To export multiple time ranges or cameras simultaneously, use the batch endpoint:
POST /api/exports/batch
This accepts a BatchExportBody (defined in frigate/api/defs/request/export_bulk_body.py) containing an array of BatchExportItem objects. Each item specifies camera, start/end times, and optional metadata. The endpoint can automatically create a new export case by providing new_case_name and new_case_description in the request body.
Request Payload Models
Frigate uses Pydantic models for automatic request validation. Invalid payloads return HTTP 422 before job creation.
ExportRecordingsBody structure:
# frigate/api/defs/request/export_recordings_body.py
class ExportRecordingsBody(BaseModel):
source: PlaybackSourceEnum = Field(default=PlaybackSourceEnum.recordings)
name: Optional[str] = Field(default=None, max_length=256)
image_path: Union[str, None] = None
export_case_id: Optional[str] = None
ExportRecordingsCustomBody adds:
ffmpeg_input_args: Optional[str] = None
ffmpeg_output_args: Optional[str] = None
cpu_fallback: bool = False
Practical Export Examples
Export a Single Recording
Request a 10-second clip from the front_door camera:
curl -X POST "https://frigate.example.com/api/export/front_door/start/1698211200/end/1698211210" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"source": "recordings",
"name": "Front Door Clip",
"image_path": "/media/frigate/exports/thumbs/front_door_001.jpg"
}'
Response (202 Accepted):
{
"export_id": "front_door_abc123",
"message": "Export queued"
}
Export with Custom FFmpeg Arguments
Apply specific encoding settings using the custom endpoint:
curl -X POST "https://frigate.example.com/api/export/custom/front_door/start/1698211200/end/1698211210" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"source": "recordings",
"name": "Custom Clip",
"ffmpeg_input_args": "-f lavfi -i testsrc=size=1280x720:rate=30",
"ffmpeg_output_args": "-c:v libx264 -crf 23",
"cpu_fallback": true
}'
Batch Export Multiple Cameras
Create a case containing exports from multiple cameras:
curl -X POST "https://frigate.example.com/api/exports/batch" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"camera": "front_door",
"start_time": 1698211200,
"end_time": 1698211210,
"friendly_name": "Front Door 1"
},
{
"camera": "garage",
"start_time": 1698211300,
"end_time": 1698211315,
"friendly_name": "Garage Motion"
}
],
"new_case_name": "Weekend Review",
"new_case_description": "Exports for Saturday night"
}'
The response includes export_case_id, an array of export_ids, and per-item success status.
Monitoring Jobs and Downloading Results
Check Export Status
Poll for completion using the export ID:
curl -H "Authorization: Bearer <TOKEN>" \
"https://frigate.example.com/api/jobs/export/<export_id>"
The response includes status fields and download URLs for completed MP4 files.
Download Case Archives
Retrieve all exports from a case as a single ZIP file:
curl -L -H "Authorization: Bearer <TOKEN>" \
"https://frigate.example.com/api/cases/<case_id>/download" \
-o case_export.zip
The _stream_case_archive function in frigate/api/export.py (lines 13-38) generates this ZIP on-the-fly using Python's zipfile module with streaming support, ensuring minimal memory usage during large archive creation.
List All Exports
Query existing exports with optional filters:
GET /api/exports?camera=front_door&case_id=<id>&start_date=<timestamp>&end_date=<timestamp>
This queries the Export and ExportCase models defined in frigate/models.py.
Summary
- Authentication: All endpoints require valid tokens and camera-specific access rights enforced by
require_camera_accessinfrigate/api/auth.py. - Job Creation: The
_build_export_jobfunction infrigate/jobs/export.pyconstructs export configurations with camera names, timestamps, and playback sources. - Standard vs Custom: Use
/export/for simple exports or/export/custom/when providing specific FFmpeg input/output arguments. - Batch Operations: The
/exports/batchendpoint accepts multiple items and can automatically organize them into export cases. - Retrieval: Monitor progress via
/jobs/export/{export_id}and download completed cases as streaming ZIP archives from/cases/{case_id}/download.
Frequently Asked Questions
What authentication is required to use Frigate's export API?
All export endpoints require the caller to be an authenticated user with a valid Bearer token. The require_camera_access decorator ensures the user has read permissions for the requested camera, while administrative operations on export cases require elevated privileges.
How can I check if my export job is complete?
Send a GET request to /api/jobs/export/{export_id} to retrieve the current status, which returns states including queued, running, completed, or failed. The endpoint queries the active job queue managed in frigate/jobs/export.py.
Can I customize FFmpeg settings when exporting recordings?
Yes. Use the /api/export/custom/{camera_name}/start/{start_time}/end/{end_time} endpoint with an ExportRecordingsCustomBody payload containing ffmpeg_input_args and ffmpeg_output_args strings. Set cpu_fallback: true to force CPU encoding if hardware acceleration fails.
How do I download multiple exported clips at once?
Group exports into a case using the export_case_id parameter or the new_case_name field in batch requests. Then use the /api/cases/{case_id}/download endpoint to stream a ZIP archive containing all related MP4 files, generated efficiently without loading the entire archive into memory.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →