License Plate Recognition Camera API (LPR/ALPR)
Viewtron AI security cameras include built-in license plate recognition (LPR/ALPR) that runs entirely on the camera hardware — no cloud service, external software, or third-party LPR engine required. When a vehicle passes through the camera's detection zone, the camera reads the license plate and sends an HTTP POST webhook to your server with the plate number, a cropped plate image, an overview image, and, depending on firmware, vehicle attributes including type, color, brand, and model. LPR-IP4 firmware 5.3.1 sends vehicle attributes in the camera's own post (carAttr), and the NVR v2.0 format carries them as carAttribute.
The API also supports managing an on-camera plate database with whitelist and blacklist entries, enabling automated gate access control without any middleware. Plates can be added with date ranges and owner information. The camera includes a Wiegand output for direct integration with gate controllers and access control panels. All Viewtron IP cameras and NVRs are NDAA compliant.
What You Can Build
- Automated gate access control — open gates and barriers when whitelisted plates are detected, using Wiegand output or webhook-triggered relay
- Vehicle access logs — record every plate read with timestamp, plate image, and authorization status for parking garages, gated communities, or corporate campuses
- Visitor management systems — pre-register expected visitor plates with date ranges using AddLicensePlates, automatically grant access on arrival
- Blacklist alerting — receive instant notifications when a blacklisted plate is detected on property
- Fleet tracking — monitor arrival/departure times for company vehicles across multiple camera locations
- Law enforcement integration — feed plate reads into stolen vehicle databases or BOLO systems in real time
- Parking enforcement — detect unauthorized vehicles and trigger alerts or record violations with plate crop images
How It Works
- Install an LPR camera at the vehicle entry point — position the camera to capture plates at the correct angle and distance
- Configure LPR detection on the camera — set the plate region (U.S.A, Canada, Europe, etc.), sensitivity, and detection zone
- Enable HTTP POST webhooks — point the camera or NVR at your server's IP and port
- Manage the plate database (optional) — add plates to the whitelist or blacklist using the AddLicensePlates API with owner info
- Your server receives XML when a plate is read — the POST includes the plate number, plate group status, plate crop image, and vehicle attributes
- Parse the event using the Viewtron Python SDK (
pip install viewtron) or raw XML parsing in any language - Take action — log the plate read, trigger a gate relay, send alerts, or update your database
Event Data
Each LPR webhook POST contains the fields below. Field names differ between a camera posting directly (IPC v1.x) and an NVR (v2.0), and some fields depend on firmware. See Firmware Differences.
| Field | Description |
|---|---|
smartType | IPC: VEHICE or VEHICLE, depending on firmware. NVR: vehicle |
plateNumber / licensePlateNumber | Detected plate text (e.g., JP116D) |
vehicleDirect | IPC: approach or away |
PlateConfidence | IPC: confidence in the count attribute, 0-10000 (count="9900" = 99%) |
vehicleListType | IPC: whiteList or blackList on firmware 5.3.1, absent if the plate is on no list. Never sent on firmware 5.1.x. temporaryList is documented but not yet confirmed in a captured post. |
licensePlateMatchInfo/groupName | NVR: user-defined group name (e.g., "Whitelist", "Residents"), or absent if not in database. Not yet confirmed in a captured post. |
plateColor / licensePlateAttribute/color | Plate color. IPC: a numeric code in the count attribute. NVR: a color name |
carAttr/type / carAttribute/carType | Vehicle type: saloon car (IPC 5.3.1), or sedan, suv, mpv, truck, etc. (NVR) |
carAttr/color / carAttribute/color | Vehicle color |
carAttr/brand / carAttribute/brand | Vehicle brand: GMC, Ford, Toyota, etc. |
carAttr/model / carAttribute/model | Vehicle model: GMC_SAVANA, etc. |
rect / corner points | NVR: plate bounding box (x1, y1, x2, y2). IPC: leftTop, rightTop, leftBottom, rightBottom, normalized 0-10000 |
targetBase64Data | Cropped plate JPEG image (base64 encoded, ~10-20 KB) |
| Overview image | Full-frame JPEG, base64 encoded. IPC: listInfo item 0 targetBase64Data (about 760 KB of base64 text in an LPR-IP4 firmware 5.3.1 post; there is no sourceDataInfo). NVR: sourceBase64Data |
currentTime | Detection timestamp, Unix microseconds from the device clock |
Decode the base64 text itself. The declared targetBase64Length did not match the actual text on LPR-IP4 firmware 5.3.1.
Parsing LPR Events
- Python SDK (Server)
- Node.js SDK
- NVR XML (v2.0)
- IPC XML (v1.x)
The simplest way to receive LPR events. The SDK's ViewtronServer handles HTTP connections, keepalives, XML parsing, and version detection — you just write the callback:
pip install viewtron
from viewtron import ViewtronServer
import os
IMG_DIR = "images"
os.makedirs(IMG_DIR, exist_ok=True)
def on_event(event, client_ip):
if event.category != "lpr":
return
plate = event.get_plate_number()
group = event.get_plate_group() # "whiteList", NVR group name, or ""
print(f"Plate: {plate} | Group: {group or 'Unknown'}")
# Save plate crop image
plate_jpg = event.get_target_image_bytes()
if plate_jpg:
with open(f"{IMG_DIR}/{plate}.jpg", "wb") as f:
f.write(plate_jpg)
# NVR v2.0 includes vehicle attributes
if event.get_alarm_type() == "vehicle":
print(f" Vehicle: {event.get_car_brand()} {event.get_car_model()}")
server = ViewtronServer(port=5002, on_event=on_event)
server.serve_forever()
See the Python SDK reference for the full list of methods and event classes.
npm install viewtron-sdk
const { ViewtronServer } = require('viewtron-sdk');
const fs = require('fs');
const path = require('path');
const IMG_DIR = 'images';
if (!fs.existsSync(IMG_DIR)) fs.mkdirSync(IMG_DIR);
const server = new ViewtronServer({ port: 5002 });
server.on('event', (event, clientIP) => {
if (event.category !== 'lpr') return;
console.log(`Plate: ${event.plateNumber} | Group: ${event.plateGroup || 'Unknown'}`);
// Save plate crop image
if (event.targetImageBytes) {
fs.writeFileSync(
path.join(IMG_DIR, `${event.plateNumber}.jpg`),
event.targetImageBytes
);
}
// NVR v2.0 includes vehicle attributes
if (event.vehicle) {
console.log(` Vehicle: ${event.vehicle.brand} ${event.vehicle.model}`);
}
});
server.start();
See the Node.js SDK reference for all event properties and server options.
The NVR v2.0 format uses licensePlateListInfo with detailed vehicle attributes and licensePlateMatchInfo for plate database group matching:
This NVR sample has not been confirmed against a current captured post. In particular, whether licensePlateMatchInfo/groupName appears, and its exact name, is unconfirmed. Log the raw post body from your NVR before you rely on these fields.
<?xml version="1.0" encoding="UTF-8"?>
<config version="2.0.0" xmlns="http://www.ipc.com/ver10">
<messageType>alarmData</messageType>
<deviceInfo>
<deviceName><![CDATA[Parking Entrance]]></deviceName>
<ip><![CDATA[192.168.0.60]]></ip>
<mac><![CDATA[58:5B:69:40:F4:0D]]></mac>
<channelId>2</channelId>
</deviceInfo>
<smartType>vehicle</smartType>
<currentTime>1772210268473000</currentTime>
<sourceDataInfo>
<sourceBase64Length>483768</sourceBase64Length>
<sourceBase64Data>... (base64 JPEG overview) ...</sourceBase64Data>
</sourceDataInfo>
<licensePlateListInfo>
<item>
<targetId>104</targetId>
<rect>
<x1>1104</x1><y1>546</y1>
<x2>1232</x2><y2>610</y2>
</rect>
<licensePlateAttribute>
<licensePlateNumber><![CDATA[JP116D]]></licensePlateNumber>
<color>white</color>
</licensePlateAttribute>
<licensePlateMatchInfo>
<groupName><![CDATA[Whitelist]]></groupName>
</licensePlateMatchInfo>
<carAttribute>
<carType><![CDATA[mpv]]></carType>
<color><![CDATA[white]]></color>
<brand><![CDATA[GMC]]></brand>
<model><![CDATA[GMC_SAVANA]]></model>
</carAttribute>
<targetImageData>
<targetBase64Length>2760</targetBase64Length>
<targetBase64Data>... (base64 JPEG plate crop) ...</targetBase64Data>
</targetImageData>
</item>
</licensePlateListInfo>
</config>
See the NVR Event Format reference for the complete v2.0 XML structure.
The IPC v1.x format puts everything in listInfo. There is no sourceDataInfo block. Item 0 is the overview image. Item 1 holds the plate number, direction, list status, confidence, vehicle attributes, and the plate crop. This shape was observed on LPR-IP4 firmware 5.3.1. Placeholder device values; IB36NL is a test plate:
<?xml version="1.0" encoding="UTF-8" ?>
<config version="1.7" xmlns="http://www.ipc.com/ver10">
<smartType type="openAlarmObj">VEHICE</smartType>
<subscribeOption type="subscribeRelationV1">FEATURE_RESULT</subscribeOption>
<currentTime type="tint64">1785000000123456</currentTime>
<plateCount type="uint32">1</plateCount>
<listInfo type="list" count="2">
<item>
<image type="uint32">0</image>
<plateNumber type="string"><![CDATA[]]></plateNumber>
<targetImageData>
<targetType type="targetType"></targetType>
<width type="uint32">0</width>
<height type="uint32">0</height>
<targetBase64Length type="uint32">770384</targetBase64Length>
<targetBase64Data type="string"><![CDATA[... (base64 JPEG overview, ~760 KB) ...]]></targetBase64Data>
</targetImageData>
</item>
<item>
<image type="uint32">1</image>
<plateNumber type="string"><![CDATA[IB36NL]]></plateNumber>
<vehicleDirect type="vehicleDirectType">approach</vehicleDirect>
<vehicleListType type="vehileMatchAlarmList">whiteList</vehicleListType>
<leftTop><x type="uint32">7559</x><y type="uint32">2072</y></leftTop>
<rightTop><x type="uint32">8214</x><y type="uint32">2072</y></rightTop>
<leftBottom><x type="uint32">7559</x><y type="uint32">2635</y></leftBottom>
<rightBottom><x type="uint32">8214</x><y type="uint32">2635</y></rightBottom>
<PlateConfidence type="uint32" count="9900"/>
<plateColor type="uint32" count="3"/>
<carAttr>
<color type="vsdCarAttrColorType">white</color>
<type type="vsdCarAttrTypeType">saloon car</type>
<brand type="vsdCarAttrBrandType">Toyota</brand>
<model type="vsdCarAttrModelType">Toyota_Camry</model>
</carAttr>
<targetImageData>
<targetType type="targetType">car</targetType>
<width type="uint32">176</width>
<height type="uint32">100</height>
<targetBase64Length type="uint32">19520</targetBase64Length>
<targetBase64Data type="string"><![CDATA[... (base64 JPEG plate crop) ...]]></targetBase64Data>
</targetImageData>
</item>
</listInfo>
</config>
This sample is trimmed. The full post is in examples/ipc-v1x/lpr.xml.
The IPC smartType spelling depends on firmware: VEHICE (the firmware's own spelling) on 5.1.1.0 build 52592 and on 5.3.1, and VEHICLE on 5.1.1.0 build 66800. Accept both. The NVR uses vehicle. On firmware 5.1.x, vehicleListType is never sent, even for plates on the camera's list.
See the IPC Event Format reference for the complete v1.x XML structure.
Managing the Plate Database
The LPR camera maintains an on-device plate database. Use the Viewtron Python SDK or the raw API to manage plates:
- Python SDK
- curl
from viewtron import ViewtronCamera
camera = ViewtronCamera("192.168.0.20", "admin", "password")
# Add a plate to the allow list
camera.add_plate("ABC1234")
# Query the database
plates = camera.get_plates()
for plate in plates:
print(plate["plate_number"], plate["owner"])
# Update plate details
camera.modify_plate("ABC1234", owner="Mike", telephone="555-1234")
# Remove a plate
camera.delete_plate("ABC1234")
# Add a plate
curl -u admin:password -X POST http://192.168.0.20/AddLicensePlates \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<config version="2.1.0" xmlns="http://www.ipc.com/ver10">
<licensePlates type="list" maxCount="100" count="1">
<item>
<index>1</index>
<licensePlateNumber><![CDATA[ABC1234]]></licensePlateNumber>
<groupId><![CDATA[1]]></groupId>
</item>
</licensePlates>
</config>'
# Query the database
curl -u admin:password -X POST http://192.168.0.20/GetLicensePlates \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<config version="2.1.0" xmlns="http://www.ipc.com/ver10">
<searchFilter>
<maxResult>50</maxResult>
<resultOffset>1</resultOffset>
<groupId><![CDATA[1]]></groupId>
</searchFilter>
</config>'
See the LPR Config API reference for the complete plate database API including ModifyLicensePlate and DeleteLicensePlate.
Relevant API Endpoints
| Endpoint | Purpose | Reference |
|---|---|---|
| GetSmartVehicleConfig | Read LPR detection settings (sensitivity, region, dedup mode) | LPR Config |
| AddLicensePlates | Add plates to the database | LPR Config |
| GetLicensePlates | Query the plate database with pagination | LPR Config |
| ModifyLicensePlate | Update plate details (owner, phone) | LPR Config |
| DeleteLicensePlate | Remove a plate from the database | LPR Config |
| SetHttpPostConfig | Configure webhook destination | Webhook Config |
| GetAlarmStatus | Poll current alarm state | Alarm Status |
Viewtron LPR cameras include a Wiegand output that sends the plate number directly to gate controllers and access control panels. This works independently of the HTTP API — the camera can simultaneously send Wiegand signals to a gate controller and HTTP POST webhooks to your software.
Integrations
Viewtron LPR cameras also integrate with automation platforms via published packages:
| Platform | Package | What It Does |
|---|---|---|
| Home Assistant | viewtron-home-assistant | Plate reads + images as native HA sensors via MQTT — automate gates, lights, alerts |
| Node-RED | node-red-contrib-viewtron | Plate reads direct to Node-RED flows — no middleware needed |
Related Applications
- Vehicle Detection & Parking Management — detect vehicles without reading plates
- Relay Control & IoT Automation — trigger gate relays based on plate authorization
- Webhook Event Notification — complete webhook setup and format reference
- Human Detection & Intrusion Detection — detect people in the same zones
- Viewtron Python SDK — ViewtronServer, ViewtronEvent, and plate database management
Related Products
- Viewtron LPR Cameras — IP cameras with built-in license plate recognition
- Viewtron LPR Gate Access Camera Systems — complete LPR systems for gated communities and commercial facilities
- Viewtron IP Camera NVRs — NVRs with HTTP POST event forwarding
- Best License Plate Recognition Cameras — buyer's guide comparing LPR camera options
Video Guides
- LPR Camera API Setup and Demo — video walkthrough of configuring LPR webhooks and viewing live plate reads
- ANPR / LPR Camera System Overview — camera installation, plate capture zones, and system design
- LPR Camera Installation Best Practices — mounting angles, distances, and IR illumination
Questions & Development Inquiries
- Email: mike@viewtron.com
- Phone: 561-433-8488
- Forum: NVR Webhook Setup Guide
Mike Haldas is available for questions, consultation, and custom software development for Viewtron API related projects. Email details about your project to mike@viewtron.com.