Skip to content

Hikvision Cameras & NVRs

Hikvision is a production-tier adapter . It communicates with cameras and NVRs through Hikvision’s ISAPI HTTP+XML protocol with full Digest authentication. The adapter includes input validation on channel/track/snapshot IDs, an SSRF guard on NVR credential resolution, and tenant scoping on every NVR lookup.

FeatureNotes
Live MJPEG / snapshot streaming_SnapshotCache shares one ISAPI fetch per channel across all concurrent viewers
PTZ controlPan / tilt / zoom continuous move, presets (read, set, go-to), patrols
Recording playbackTimeline search, segment download
NVR import wizardAuto-discover channels, inherit credentials per-channel with org scoping
Motion / line-crossing / intrusion eventsIngest via long-poll alertStream
License-plate recognition (LPR)Event tagging on supported cameras
Camera groups, recording templates, view layoutsFull CRUD

Hik-Connect cloud relay is not supported - local ISAPI only. Two-way audio (G.711u) is supported on compatible cameras via POST /api/v1/cameras/{id}/audio/start and POST /api/v1/cameras/{id}/audio/stop.

DGCBRRTSSSRFRG

See Adapter Contract for what each column means.

  • Hikvision camera or NVR firmware V4.x or later (ISAPI support)
  • HTTP (port 80) or HTTPS (port 443) access from the FreeSDN host
  • An admin-level account or a dedicated operator account with remote login enabled
  1. In FreeSDN, open Video Surveillance → Cameras and click Add Camera.
  2. Select vendor Hikvision, enter the camera IP/hostname, port, and credentials.
  3. FreeSDN tests the ISAPI connection. On success the camera appears in the camera list.

To add via the API directly:

Terminal window
# Add the camera - supply credentials directly in the same request body
curl -X POST https://freesdn.example.com/api/v1/cameras/ \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"name": "Lobby",
"ip_address": "10.0.1.50",
"port": 80,
"vendor": "hikvision",
"username": "freesdn",
"password": "s3cr3t",
"site_id": "<site-uuid>"
}'

The NVR import wizard is a four-step process: test connection → discover channels → configure → import.

Terminal window
curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/test-connection \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"host": "10.0.1.64",
"port": 80,
"username": "freesdn",
"password": "s3cr3t"
}'

Response includes device_name, model, firmware_version, serial_number.

Terminal window
curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/discover \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"host": "10.0.1.64",
"port": 80,
"username": "freesdn",
"password": "s3cr3t"
}'

Returns a channels list (channel ID, name, online status, PTZ flag, RTSP main/sub URLs) and a storage summary (total/used GB per disk).

The adapter queries three ISAPI endpoints in order and uses the first that responds:

  1. GET /ISAPI/ContentMgmt/InputProxy/channels (most NVRs)
  2. GET /ISAPI/System/Video/inputs/channels
  3. GET /ISAPI/Streaming/channels (fallback)
Terminal window
curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/import \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"host": "10.0.1.64",
"port": 80,
"username": "freesdn",
"password": "s3cr3t",
"site_id": "<site-uuid>",
"name": "Office NVR",
"selected_channels": [1, 2, 3, 4]
}'

selected_channels is optional - omit it to import all enabled channels. The import is idempotent on external_device_id; re-importing the same NVR automatically re-syncs its channels and returns a normal 201 response with "synced": true - no error is raised and no manual sync call is required.

After the initial import, sync re-queries the NVR for current channels, adds new cameras, marks missing cameras offline, and updates storage stats:

Terminal window
curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/<nvr-uuid>/sync \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>"

Returns {"added": N, "removed": N, "updated": N}.

The adapter constructs RTSP URLs using Hikvision’s NVR channel-numbering convention:

StreamURL pattern
Main stream, channel Nrtsp://user:pass@{host}:554/Streaming/Channels/{N*100+1}
Sub stream, channel Nrtsp://user:pass@{host}:554/Streaming/Channels/{N*100+2}
Standalone camera mainrtsp://user:pass@{host}:554/Streaming/Channels/101

Snapshot:

GET /ISAPI/Streaming/channels/{N*100+1}/picture

PTZ is available on supported cameras via the cameras module:

Terminal window
# Continuous move (pan right) - action and speed are query params
curl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz?action=right&speed=50' \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>"
# Go to a saved preset - action=preset with the preset number as a query param
curl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz?action=preset&preset=1' \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>"
# Save (set) a new preset at the current camera position - preset number and name are query params
curl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz/presets?preset=1&name=Lobby+Default' \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>"

Search recordings by time range:

Terminal window
curl -H "Cookie: freesdn_access=<token>" -H "X-CSRF-Token: <csrf>" \
"https://freesdn.example.com/api/v1/cameras/recordings/search?camera_id=<id>&start_time=2026-06-01T00:00:00Z&end_time=2026-06-01T06:00:00Z"

Returns a list of recording segments with start/end times and a playback URL per segment.

The adapter subscribes to the long-poll ISAPI alertStream and ingests motion, line-crossing, intrusion, and LPR events into the FreeSDN event bus. Events appear on the Events page and can trigger Fabric connections.

  • Credentials are encrypted at rest with Fernet (derived from ENCRYPTION_SALT).
  • Adapter responses are passed through the central redact_secrets function (~89 sensitive keys plus Proxmox ipconfig0-ipconfig31 prefix patterns, camelCase-aware) before returning to the UI. Any credential-bearing fields in ISAPI responses are stripped at this layer.
  • Channel IDs, track IDs, and snapshot IDs are validated ([0-9]+, bounded) before being interpolated into ISAPI URL paths.
  • SSRF guard: the NVR host field is validated to block loopback, link-local, and cloud metadata endpoints. RFC 1918 private ranges are allowed by default (on-prem deployments). Set BLOCK_PRIVATE_CAMERA_SUBNETS=1 to also block private ranges; use ALLOWED_CAMERA_SUBNETS (comma-separated CIDRs) to add custom allowlist entries.
  • CamerasPage - camera grid with live thumbnail previews
  • CameraDetailPage - live stream, PTZ, events, recordings tabs
  • CameraWallPage - multi-camera wall view
  • NVRListPage / NVRDetailPage - NVR list and per-NVR channel view
  • MultiPlaybackPage - synchronized multi-channel playback

All cameras-module endpoints mount under /api/v1/cameras/. Sub-routers include nvrs, events, groups, views, recording-templates, access, streams/hls, reports, and lpr.

All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.