Repository navigation
Using the Data
The whole dataset is committed to this repo and released under CC0: use it for anything, commercial or not, with no attribution required (a link back is appreciated). There's no API key, rate limit or build step.
| You want… | Use |
|---|---|
| Everything, for scripts or a database |
data/cameras.json: one array of every camera |
| A spreadsheet |
data/cameras.csv: flattened, one row per camera |
| A pinned, checksummed version |
cameras.zip attached to each release
|
| One camera or one brand, over HTTP | the static JSON API (below) |
| Only "what does this model look like" (FOV, resolution, type) |
data/model-enrichment.json: a small extract with no configs or notes |
| Brand-level RTSP path templates |
data/rtsp-patterns.json (see Stream URLs by Brand) |
The individual source records are in cameras/<brand>/<model>.json, one file per camera. The aggregated files are rebuilt from them on every release.
Hosted alongside the website. It's read-only, has no key and has no rate limit:
| Endpoint | Returns |
|---|---|
https://www.cctv-database.com/api/index.json |
API description, camera and brand counts, and when it was generated |
https://www.cctv-database.com/api/brands.json |
every brand, with its slug and camera count |
https://www.cctv-database.com/api/brands/{slug}.json |
one brand and a short list of its cameras |
https://www.cctv-database.com/api/cameras/{id}.json |
one full camera record |
Every record has a unique id (<brand>-<model-slug>, e.g. hikvision-ds-2cd2387g2-lu, axis-p1365). To match hardware you already know, look it up by model or any of the aliases, case-insensitively, and use brand to tell apart the rare cases where two brands share a model code.
Aliases matter: a manufacturer often sells one camera under several order numbers (lens size, housing colour, PAL/NTSC, a regional suffix like -GOV or /SL). The dataset keeps one record per camera and lists the other order numbers as aliases. See the FAQ.
const cameras = require('./data/cameras.json');
const norm = s => s.toUpperCase().replace(/[^A-Z0-9]/g, '');
function findCamera(code, brand) {
const key = norm(code);
return cameras.find(c =>
(!brand || c.brand.toLowerCase() === brand.toLowerCase()) &&
[c.model, ...(c.aliases || [])].some(m => norm(m) === key));
}
findCamera('DS-2CD2T86G2H-IS2U/SL', 'Hikvision');import json, re
cams = json.load(open("data/cameras.json"))
norm = lambda s: re.sub(r"[^A-Z0-9]", "", s.upper())
# 4K outdoor cameras with a verified Frigate config
hits = [c for c in cams
if (c.get("resolution") or {}).get("megapixels", 0) >= 8
and "outdoor" in (c.get("environment") or [])
and (c.get("configs") or {}).get("frigate", {}).get("verified")]Most fields are optional: a missing field means the datasheet doesn't state it, not that the feature is absent. Always use optional access (c.lens?.focal_length_mm). Only id, brand, model, type and resolution are always present.
| Field | Notes |
|---|---|
type |
bullet, dome, turret, ptz, box, fisheye, panoramic, dual-lens, covert, floodlight, doorbell
|
resolution |
{megapixels, max_width, max_height, label} |
field_of_view_deg |
a string, as the datasheet gives it ("104", "110-31", "2.8mm: 104 / 4mm: 89") |
night_vision |
type (ir, color, hybrid, none), range_m, min_lux (black-and-white), min_lux_color
|
video |
codecs, max_fps, and streams[] with each stream's resolution, fps and codec |
ndaa_compliant |
true / false only when there is an official basis; omitted otherwise (see the FAQ) |
configs |
ready-made frigate, home_assistant and blue_iris settings (see Stream URLs by Brand) |
sources |
the official URLs every value was taken from |
last_verified |
when a person last checked the record against its sources |
added |
when the camera first appeared in the dataset (from git history) |
The full list, with types and allowed values, is in schema/camera.schema.json. COVERAGE.md shows how complete each field is.
Releases follow MAJOR.MINOR.PATCH. New cameras and data fixes ship as minor releases, and each release's changes are listed in CHANGELOG.md. If you need reproducible results, pin a release's cameras.zip rather than reading main.
When a camera record is merged or renamed, its old id keeps working on the website (it redirects to the surviving record). If you store ids, re-check them against the changelog when you upgrade.
Use the data
Use the website
Contribute
- Reporting a Working Config
- Brand Sourcing Notes
- Brands Wanted and Not Addable
- Open an issue
- CONTRIBUTING.md
Ecosystem