On-Premises ALPR

OpenALPR On-Premises software runs on your hardware/application without any Internet connection. The software can be used for general surveillance purposes or as an engine to add LPR capabilities to other applications.

Use of OpenALPR On-Premises requires a commercial license. Please contact info@openalpr.com to discuss licensing options for your project.

OpenALPR Agent

System Requirements

The OpenALPR agent scales to make use of as many CPU resources as you can provide. For example, OpenALPR can utilize up to 100 percent of the processing power on both low-power devices (such as a Raspberry Pi) and high-end devices (such as an Intel 32 CPU-core Xeon server). High-end devices are capable of processing significantly more video frames per second.

The minimum system requirements for OpenALPR agents are a function of:

  • The speed/angle of vehicles with respect to the camera (i.e., how long a legible license plate is in-frame)
  • The resolution of the input video
  • The number of camera streams analyzed by the agent
  • Other CPU load
  • The volume of vehicles (i.e., whether vehicles are seen constantly or sporadically)

As a rough rule of thumb, an OpenALPR agent running on a latest-generation Intel i5 desktop-class CPU can process roughly 20 frames of 720p video per second. In other words, an agent can handle three cameras for low-speed vehicles, two cameras for medium-speed vehicles, and one camera for high-speed vehicles. Of course, mileage may vary, and it is always best to benchmark performance on your own hardware.

Memory and disk requirements are relatively constant. Once OpenALPR initializes, the process uses roughly 500MB per analysis thread (CPU core), and that memory usage will not increase. The agent records JPEG images to a disk as plates are recognized. However, Disk IO is usually not a bottleneck.

NVIDIA GPU Acceleration

OpenALPR agent performance can also be drastically accelerated by Nvidia GPU hardware. OpenALPR maintains binaries for CUDA 10.0 using CuDNN 7 on 64-bit Ubuntu Linux 18.04. The OpenALPR software has been compiled for CUDA hardware versions 5.2 5.3 6.0 6.1 6.2 7.0 7.2 7.5. You can verify your CUDA version here: https://developer.nvidia.com/cuda-gpus

Ubuntu 18.04

First setup the Nvidia repos:

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.0.130-1_amd64.deb -O /tmp/cuda-repo-ubuntu1804_10.0.130-1_amd64.deb
sudo dpkg -i /tmp/cuda-repo-ubuntu1804_10.0.130-1_amd64.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub

If you have not already installed Nvidia drivers, you must do this first:

sudo apt-get update
sudo apt-get install -y nvidia-driver-410
sudo reboot

Now you may install the OpenALPR GPU acceleration package:

bash <(curl https://deb.openalpr.com/install)

Select OpenALPR software and the install_nvidia option

Ubuntu 16.04

To enable GPU acceleration, first install Nvidia packages:

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.61-1_amd64.deb -O /tmp/cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
sudo dpkg -i /tmp/cuda-repo-ubuntu1604_8.0.61-1_amd64.deb

Next install the OpenALPR Nvidia acceleration. Choose “install_nvidia” from the menu:

bash <(curl https://deb.openalpr.com/install)

The following properties will be set automatically in /etc/openalpr/openalpr.conf:

hardware_acceleration = 1
gpu_id = 0
gpu_batch_size = 10

The batch size controls how many images are simultaneously processed by the GPU. The default value is usually the best balance of performance and GPU memory usage.

OpenALPR also maintains special builds for Jetson TX-1/TX-2 hardware on Jetpack v3.1. To install, follow the standard Linux install instructions. The defaults are configured such that the GPU will automatically be installed, enabled, and configured with a default batch size of 5.



  • Download the OpenALPR Windows Installer
  • Install the program onto your PC
  • When installation is complete, start the Configure OpenALPR program.
  • Depending on how you wish to use the OpenALPR agent, you may choose one of four options for data destination:
Windows Agent Configuration
  1. OpenALPR Cloud — Data is sent to https://cloud.openalpr.com (requires an active OpenALPR Cloud Account).
  2. OpenALPR On-Premises Web Server — You have installed the OpenALPR web server on a Linux machine and wish to point the agent data to that server.
  3. Generic HTTP Url — You wish to integrate OpenALPR with your own application. You can point the data to your own HTTP endpoint.
  4. Local Queue — You want the OpenALPR data to be stored on a local beanstalkd queue. Your application will programmatically drain the queue to process results.

If you intend to use the agent for surveillance purposes, you will most likely select the “OpenALPR On-Premises Web Server.” Options 3 and 4 are useful if you are an application developer and are integrating OpenALPR data into your own application.


  1. Download the Ubuntu 18.04 64-bit install DVD image and burn it to a DVD.
  2. Follow this installation guide to install Ubuntu 18.04 64-bit.
  3. Run the following command from the terminal:
bash <(curl -s https://deb.openalpr.com/install)
  1. To connect the agent to the OpenALPR Cloud, choose “install_agent”.
  2. If you are using a GUI, you can configure the agent using the alprdconfig utility by running the following command:
sudo alprdconfig
  1. If your server does not have a GUI and you wish to connect your software to an OpenALPR On-Premises web server, run the following commands. - Type “n” to choose “no” to registering with the OpenALPR Cloud. - Type the command alprlink-register -w http://[ip_address_of_web_server] . - Type in the e-mail address and password that you used to install the web server.


  1. Run the command docker pull openalpr/commercial-agent to pull the latest OpenALPR docker commercial agent.
  2. Run the following command to register the agent with the service:
docker run -P -v openalpr-vol1-config:/etc/openalpr/ -v openalpr-vol1-images:/var/lib/openalpr/ -it openalpr/commercial-agent alprlink-register
  1. Start the docker container with the following command:
docker run --restart always -d --cap-add SYS_NICE -P -v openalpr-vol1-config:/etc/openalpr/ -v openalpr-vol1-images:/var/lib/openalpr/ -it openalpr/commercial-agent


Agent Properties

You can configure each OpenALPR agent manually (by editing the agent configuration files) or through the OpenALPR web server. This section discusses manual configuration. Configuring the agent through the OpenALPR web server is described in the web server section of the documentation.

The primary configuration file for the OpenALPR agent is located in the /etc/openalpr/alprd.conf file. For your reference, you can find a default configuration file containing every default setting for the agent in /usr/share/openalpr/config/alprd.defaults.conf. Any value you change in alprd.conf will take precedence over the default configuration.

The following configuration options can be modified if you edit the alprd.conf file. After adding or changing values in the configuration file, you must restart the OpenALPR agent process.

Image Storage Configuration

The commercial daemon maintains a maximum disk quota and automatically cleans up after itself. Images stored to the disk are removed on a FIFO-basis. These parameters control the location, image quality, and maximum size of local image storage.

store_plates = 1
store_plates_jpeg_quality = 85
store_plates_location = /var/lib/openalpr/plateimages/
store_plates_maxsize_mb = 8000
Upload Configuration

You may enable or disable uploading. When the agent is running, all plate results will first be placed onto a local beanstalkd queue. If the upload_data parameter is set to “1” for enabled, the agent will pull results from the queue and send them to the configured “upload_address” endpoint as an HTTP POST. The upload_threads parameter will specifies the number of simultaneous data uploads. Generally, the number of threads only needs to be increased if the web server is slow to respond or network latency is exceptionally high.

upload_data = 1
upload_address = https://cloud.openalpr.com/push/
upload_threads = 2
Company ID (required)

The company_id value is sent in the JSON payload for all results. If you connect to an OpenALPR web server, this value is configured for you automatically. However, if you configure the agent manually, the value is not used, but it is still required. Any alphanumeric string will suffice.

company_id = abc-123
Motion Detection

Motion detection improves efficiency and draws more plate reads from available processors. The ALPR processing only analyzes frames with movement, ignoring areas of the image that have not changed. This parameter controls whether motion detection is enabled (1) or disabled (0).

motion_detection = 1
Parallel Processing

The ALPR processing occurs in parallel; each thread consumes an entire CPU core. Allocating more CPUs for ALPR processing will linearly increase the number of plate reads per second. If you wish to maximize the ALPR processing on your hardware, this number should map the number of CPU cores available on the system.

analysis_threads = 2
Back-Buffer Processing

With motion detection enabled, you are able to buffer moving images and analyze them as CPU becomes available. For example, if a car moves past the camera over 10 frames but the CPU can only analyze 3 of those frames in that period, the buffer allows you to analyze all 10 frames. When activity ceases, the ALPR process drains the buffer, looking for license plates during the period of movement. Increasing the buffer_size increases the duration of this period but will also consume more memory. The camera_buffer_size unit is the number of image frames.

camera_buffer_size = 60
Plate Grouping

The agent groups similar plate numbers together and sends a JSON post containing the UUIDs of every plate image in the group. These configuration files control the behavior of the plate grouping algorithm:

  • plate_groups_span_cameras – A single agent may have multiple cameras. Depending on how the cameras are positioned, they may view the same vehicles or different ones. If plate_groups_span_cameras is set to “enabled,” the grouping algorithm combines plate events that are seen by different cameras. Otherwise, they are never combined.
  • plate_groups_min_plates_to_group – A plate group must have at least this number of individual plate reads to form a group.
  • plate_groups_min_confidence – The plate read must have at least this confidence to be considered for grouping.
  • plate_groups_max_plates_to_group – At some point, if a plate is seen more than this number of times, it is wrapped into a group and sent even if the plate is still in the frame.
  • plate_groups_time_delta_ms – The plate group waits this long for another plate to be identified with a similar license plate. If a matching plate is seen, this timer is reset.
  • plate_groups_max_delay_to_send – Wait at least this long before sending a plate group event. This function is primarily intended to ensure that any back-log of processing is complete before the group event is finished. Depending on the value for camera_buffer_size, you may want to increase or decrease this value.
plate_groups_enabled = 1
plate_groups_span_cameras = 0
plate_groups_time_delta_ms = 4500
plate_groups_min_plates_to_group = 2
plate_groups_min_confidence = 80.0
plate_groups_max_plates_to_group = 500
plate_groups_max_delay_to_send = 7500
Image Retrieval

The agent may also host a local web server for retreiving images via HTTP GET requests. This web server is turned off, but you may enable it by changing the web_server_enabled parameter to 1.

web_server_enabled = 0
web_server_port = 8355
Vehicle Make/Model Classification

OpenALPR automatically classifies vehicle make/model, color, and body type for each license plate group it detects. If you are not using or do not need this feature, you can disable it to save CPU processing time.

classify_vehicles = 1

Camera Streams

The agent must be configured to connect to one or more camera streams to process license plates. OpenALPR expects to receive a URL specifying the HTTP or RTSP stream location on the IP camera. You should be able to find this URL by consulting your camera’s user manual, or with the help of an ONVIF-capable discovery tool. Once you have found the URL, you can test the stream with a video player such as VLC

To add a camera stream:

  1. Create a new unique file in /etc/openalpr/stream.d/ with the extension “.conf”. For example, create a file named “my_new_camera.conf”.
  2. Add a line to the file with the following format: - stream = [Camera HTTP/RTSP stream URL]
  3. Restart the OpenALPR agent.

Once restarted, you should see the agent successfully connecting to the camera in the log file (/var/log/alpr.log)

Each camera configuration file may optionally be configured with the following settings:

  • prewarp - A series of numbers that adjusts the rotation/angle of the camera image before processing. The exact value can be obtained through the OpenALPR configuration utility
  • detection_mask_image - The path to a black and white image file that creates a mask over the video stream before processing. Black areas are ignored, white areas are scanned for plates.
Custom GStreamer Pipeline

In some cases, you may require more control over the process that grabs video from your device and makes it available to OpenALPR. The OpenALPR agent and AlprStream SDK both allow you to configure a custom GStreamer Pipeline which can handle pulling video from your camera. GStreamer is open source and supports user plug-ins which allow you to write your own C code in case you need to utilize 3rd party device drivers to pull the data.

To get started, you should first familiarize yourself with GStreamer pipelines. The following are a few examples of pulling video from various sources. gst-launch-1.0 is a command line program that will execute the pipeline and display the output.


gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,framerate=30/1,width=1280,height=720 ! decodebin ! videoconvert ! video/x-raw,format=BGR ! videoconvert ! autovideosink

Video File

gst-launch-1.0 filesrc location=/tmp/video.mp4 ! decodebin ! videoconvert ! video/x-raw,format=BGR ! videoconvert ! autovideosink

RTSP/H264 Camera

gst-launch-1.0 rtspsrc location=rtsp:// user-id=testuser user-pw=test drop-on-latency=1 latency=1000 ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 min-threshold-time=10 ! rtph264depay ! h264parse ! decodebin ! videoconvert ! video/x-raw,format=BGR ! videoconvert ! autovideosink

Once you have experimented with GStreamer to display video, you can now integrate it with OpenALPR. Our software will see the video exactly as the gst-launch-1.0 command displays it. If using the agent, you can add your custom gstreamer format as follows:

  1. Edit /etc/openalpr/stream.d/[cameraname].conf
  2. Add gstreamer_format = [your custom gstreamer pipeline]
  3. Remove the “autovideosink” and replace it with “appsink name=sink max-buffers=5”
  4. Make sure you do not include the “gst-launch-1.0” command at the beginning.

If you are using the AlprStream SDK, you will apply the pipeline to the API function “connect_video_stream_url” by passing it a string for “gstreamer_pipeline_format”

Restarting the Agent

The OpenALPR agent must be restarted for any configuration changes to take effect.

To restart the OpenALPR agent:
  • On Windows, use the OpenALPR configuration utility or manually restart the “OpenALPR Agent” Windows service.
  • On Linux, run: sudo systemctl restart openalpr-daemon.
  • On Docker, restart the container.

Web Server


The OpenALPR web server is a web-based interface that collects, manages, and presents license plate data that has been produced by one or more OpenALPR agents. The server software installs on Ubuntu Linux.

The web server does not process license plate videos; that function is performed by the OpenALPR agent. The web server receives license plate data and stores the data in a local database. When sizing a server for the OpenALPR web server, make sure to select a sufficiently fast hard drive. For web servers supporting up to 200 OpenALPR agents, a single SSD hard drive should be sufficient. For larger installations, the server will likely need multiple hard drives configured as a RAID.

Minimum system requirements:

  • 4GB RAM
  • 250GB SSD hard drive
  • Dual-core or greater CPU
  • Ubuntu Linux 18.04 64-bit


The OpenALPR agent reads a video stream from your IP camera, processes the stream, and uploads plate metadata to the OpenALPR web server. The agent also stores all of the plate images in a rolling buffer on the hard drive.

There is a constant stream of data flowing between the camera and the agent, as well as between the agent and the web server. The data sent to the cloud is relatively low-bandwidth because it contains text metadata describing the license plates. The OpenALPR web server does not store your plate images; these are downloaded directly from the agent when you select a plate to view from the web server.


Download the Ubuntu 18.04 64-bit install DVD image and burn it to a DVD:

Follow this installation guide to install Ubuntu 18.04 64-bit:

Run the following command from the terminal:

bash <(curl -s https://deb.openalpr.com/install)
OpenALPR VM installation step 4

Choose “install_webserver”:


Agent Configuration

The OpenALPR web server may have any number of agents connected to it who send license plate data. Configuration for these agents is managed centrally on the OpenALPR web server. To configure an agent:

  • Log in to the OpenALPR web server.
  • Select Configuration -> Agents from the menu on the left-hand side of the page.
  • You should see your new agent on this screen. Select Configure to set up the camera.
  • Select Add Stream to connect your agent to the camera stream.
OpenALPR VM installation step 4
  • Select the model of IP camera you wish to connect to. Fill in the IP address. If the camera requires credentials, check the box and enter your camera’s username and password.
  • Click Test. After a few seconds, you will see a window indicating whether or not the connection was successful. If it was successful, click Save Camera. If not, try another option (such as H264 Alt1 or MJPEG) and click Test again until you succeed.
OpenALPR VM installation step 4
  • Configure the Agent Parameters.
    • Choose a sensible name for your Site ID, such as the location of the agent system (e.g., headquarters, dallas-branch, or warehouse3). Each agent should be given a unique site ID.
    • Choose the country in which the camera is located. US will recognize North American-style plates (12 inches x 6 inches). EU will recognize European-style plates. Other countries whose plates have different dimensions will also be supported.
    • The number of Processing Cores will control how much CPU will be allocated to the LPR process. The more processing cores you provide (up to the number of CPU cores on the system), the more frames per second (fps) you will be able to process. Higher fps will generally increase accuracy and allow plates on faster-moving vehicles to be detected.
    • Disk Quota will control how much space is reserved for storing vehicle and license plate images. It will operate as a rolling buffer, so when it runs out of space, the oldest images will be removed.
    • For Europe, Pattern is the country in which the camera is located. For the USA, OpenALPR uses a high-accuracy state detection algorithm to detect the state of origin, so it is better to leave the pattern set to “None” for recognition in the USA.
  • Click Update.
OpenALPR VM installation step 4
  • Finally, if you scroll to the bottom of the page, you can watch the agent status. You should now see Video FPS and other information indicating that the video is being pulled from the camera and license plates are being recognized. Now that the agent is configured, it will continue collecting data from the configured video streams. If the agent is rebooted, the OpenALPR agent will automatically start. If the camera goes down or the network becomes temporarily inoperative, the agent will retry until connectivity is restored. All results will be queued, so no data will be lost in an outage.
OpenALPR VM installation step 4

Advanced Agent Configuration

You can also configure the OpenALPR agent manually by modifying the file in /etc/openalpr/alprd.conf. This advanced option may be useful in the management of dozens or hundreds of agents. The default values with descriptions can be found here: /usr/share/openalpr/config/alprd.defaults.conf. You may add any value into the alprd.conf file; to apply changes, restart the agent.

Additional documentation on these configuration options is located in the Configuration.

To restart services, run the following command:

sudo systemctl restart openalpr-daemon

To watch the OpenALPR logs, run the following command:

tail -f /var/log/alpr.log

Web Services

The Web Services API can be used to programmatically query your on-premises server for data. The API is documented here

Application Integration

You can integrate OpenALPR with your application in two ways:

  • Use the OpenALPR SDK to compile OpenALPR code libraries into your application and process individual image frames or video streams.
  • Run the OpenALPR Agent to directly pull video feeds and send the plate results and images to your application.

Integrating With the Agent

The OpenALPR agent runs as either a Windows service (on Windows) or a daemon (on Linux). The process runs constantly in the background, watching the configured video streams for license plates. When a license plate is found, it immediately places JSON data onto a local beanstalkd queue for uploading or processing.

Decide whether your application should receive data from OpenALPR (sent via HTTP POST) or pull data from a queue on demand. Both approaches are equally valid; your choice simply depends on the most appropriate integration method based on your application architecture.

Receiving HTTP POSTs

The OpenALPR agent can be configured to send HTTP POSTs to your HTTP server. To enable this option, set the following parameters in /etc/openalpr/alprd.conf:

upload_data = 1
upload_address = [your HTTP server endpoint]
websockets_enabled = 0
web_server_enabled = 1

In addition, you must add a valid on-premises license to /etc/openalpr/license.conf

Once updated, restart the OpenALPR agent service to allow the settings to take effect. As plates are recognized, the JSON data described in this section will be sent to your HTTP server as an HTTP POST.

Pulling From the Queue

OpenALPR maintains a local Beanstalkd queue. All JSON results are placed onto this queue. Your application can grab and process the latest plate results from this queue .

Beanstalkd maintains client libraries in many popular programming languages. For a complete list, visit: https://github.com/kr/beanstalkd/wiki/Client-Libraries

To configure OpenALPR to make the results available via the local queue, set the following parameters in /etc/openalpr/alprd.conf:

upload_data = 0
websockets_enabled = 0
web_server_enabled = 1

In addition, you must add a valid on-premises license to /etc/openalpr/license.conf

Once updated, restart the OpenALPR agent service to allow the settings to take effect.

Below is a sample Python script that pulls results from the local Beanstalkd queue:


import beanstalkc
import json
from pprint import pprint

beanstalk = beanstalkc.Connection(host='localhost', port=11300)


# For diagnostics, print out a list of all the tubes available in Beanstalk.
print beanstalk.tubes()

# For diagnostics, print the number of items on the current alprd queue.
except beanstalkc.CommandFailed:
    print "Tube doesn't exist"

# Watch the "alprd" tube; this is where the plate data is.

# Loop forever
while True:

    # Wait for a second to get a job. If there is a job, process it and delete it from the queue.
    # If not, return to sleep.
    job = beanstalk.reserve(timeout=1.0)

    if job is None:
        print "No plates available right now, waiting..."

        print "Found a plate!"
        plates_info = json.loads(job.body)

        # Print all the info about this plate to the console.

        # Do something with this data (e.g., match a list, open a gate, etc.).
        if 'data_type' not in plates_info:
            print "This shouldn't be here... all OpenALPR data should have a data_type"
        elif plates_info['data_type'] == 'alpr_results':
            print "This is a plate result"
        elif plates_info['data_type'] == 'alpr_group':
            print "This is a group result"
        elif plates_info['data_type'] == 'heartbeat':
            print "This is a heartbeat"

        # Delete the job from the queue when it is processed.

JSON Plate Results

OpenALPR generates an “alpr_results” JSON value for every frame of video in which a license plate is recognized. This value will be sent multiple times for a single vehicle. For example, as a vehicle drives past the camera over the course of three seconds, OpenALPR may recognize the same license plate fifty times. All fifty recognition results will be recorded as alpr_results JSON values.

The number of recognition results largely depends on the processing speed and number of cameras being processed. A faster processor will produce more of these per vehicle because it is able to process video frames at a faster rate.

Individual plate results are best suited for applications that need to operate on plate data in real time.

JSON Plate results are sent in the following format:

  "version": 2,
  "data_type": "alpr_results",
  "epoch_time": 1490574589596,
  "img_width": 1280,
  "img_height": 720,
  "processing_time_ms": 259.132385,
  "error": false,
  "regions_of_interest": [
      "x": 60,
      "y": 600,
      "width": 620,
      "height": 120
      "x": 0,
      "y": 0,
      "width": 1280,
      "height": 570
  "results": [
      "plate": "AE1T3E",
      "confidence": 93.904076,
      "matches_template": 1,
      "plate_index": 0,
      "region": "mo",
      "region_confidence": 34,
      "processing_time_ms": 17.029213,
      "requested_topn": 10,
      "coordinates": [
          "x": 110,
          "y": 300
          "x": 227,
          "y": 295
          "x": 227,
          "y": 348
          "x": 113,
          "y": 352
      "vehicle_region": {
        "x": 0,
        "y": 34,
        "width": 433,
        "height": 433
      "candidates": [
          "plate": "AE1T3E",
          "confidence": 93.904076,
          "matches_template": 1
          "plate": "AET3E",
          "confidence": 83.211739,
          "matches_template": 0
          "plate": "A1T3E",
          "confidence": 79.840271,
          "matches_template": 0
          "plate": "AE1T3F",
          "confidence": 79.130386,
          "matches_template": 1
          "plate": "AEIT3E",
          "confidence": 78.878433,
          "matches_template": 0
          "plate": "4E1T3E",
          "confidence": 78.217575,
          "matches_template": 0
          "plate": "AT3E",
          "confidence": 69.147926,
          "matches_template": 0
          "plate": "AET3F",
          "confidence": 68.438042,
          "matches_template": 0
          "plate": "4ET3E",
          "confidence": 67.52523,
          "matches_template": 0
          "plate": "A1T3F",
          "confidence": 65.066574,
          "matches_template": 0
  "uuid": "unspecified-cam16488027-1490574589596",
  "camera_id": 16488027,
  "agent_version": "2.3.111",
  "agent_type": "alprd",
  "site_id": "unspecified",
  "company_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

JSON Group Results

OpenALPR generates an “alpr_group” JSON value for a collection of similar license plates, generally delegating a single plate group per vehicle. When the plate is not seen for a number of seconds, the plate_group result is sent with a reference (by UUID) to all the individual plate results that make up the group. The group also includes a best estimate for the license plate number based on a weighted score from all the frames included in the group.

Additionally, each plate group includes a detection value for the make/model, color, and vehicle body type.

Group results are most suitable for surveillance-type purposes. When these values are used, results may be delayed up to ten seconds after the vehicle has passed, so it is important that the application is not sensitive to this delay. If more real-time results are needed, it is recommended that you ignore the plate_group value and use only the individual plate results.

ALPR group results are sent in the following JSON format:

   "data_type" : "alpr_group",
   "version" : 2,
   "company_id" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
   "camera_id" : 2090267338,
   "best_plate_number" : "6PK132",
   "best_confidence" : 90.2536163330078,
   "best_region" : "us-mo",
   "best_region_confidence" : 83,
   "best_image_width" : 1280,
   "best_image_height" : 720,
   "best_uuid" : "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY-2090267338-1538924513527",
   "matches_template" : false,
   "epoch_start" : 1538924513527,
   "epoch_end" : 1538924513627,
   "frame_start" : 68,
   "frame_end" : 71,
   "is_parked" : false
   "agent_type" : "alprd",
   "user_data" : "hello world",
   "uuids" : [
   "travel_direction" : 285.945404052734,
   "agent_version" : "2.6.101",
   "country" : "us",
   "plate_indexes" : [
   "candidates" : [
         "matches_template" : 0,
         "confidence" : 90.2536163330078,
         "plate" : "6PK132"
         "matches_template" : 0,
         "confidence" : 70.315123252332,
         "plate" : "6PKI32"
   "best_plate" : {
      "plate_index" : 0,
      "confidence" : 90.2536163330078,
      "region_confidence" : 70,
      "plate_crop_jpeg" : "...base64_jpeg_bytes...",
      "processing_time_ms" : 21.2537994384766,
      "candidates" : [
            "plate" : "6PK132",
            "matches_template" : 0,
            "confidence" : 90.2536163330078
            "confidence" : 75.9956741333008,
            "matches_template" : 0,
            "plate" : "6PKI32"
            "plate" : "6PK32",
            "confidence" : 75.5074081420898,
            "matches_template" : 0
            "matches_template" : 0,
            "confidence" : 75.3532333374023,
            "plate" : "6PKA32"
            "plate" : "6PK12",
            "matches_template" : 0,
            "confidence" : 74.8602905273438
            "matches_template" : 0,
            "confidence" : 74.8599395751953,
            "plate" : "PK132"
            "confidence" : 74.7018280029297,
            "matches_template" : 0,
            "plate" : "GPK132"
            "confidence" : 74.6972503662109,
            "matches_template" : 0,
            "plate" : "6PK122"
            "plate" : "6PKI2",
            "matches_template" : 0,
            "confidence" : 60.6023483276367
      "region" : "us-mo",
      "matches_template" : 0,
      "requested_topn" : 20,
      "plate" : "6PK132",
      "vehicle_region" : {
         "y" : 71,
         "width" : 229,
         "height" : 229,
         "x" : 0
      "coordinates" : [
            "y" : 219,
            "x" : 62
            "x" : 115,
            "y" : 217
            "y" : 245,
            "x" : 114
            "x" : 61,
            "y" : 247

JSON Heartbeat

Every minute, the OpenALPR agent adds one heartbeat message to the queue. The heartbeat provides general health and status information. The format is as follows:

   "data_type" : "heartbeat",
   "company_id" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
   "agent_hostname" : "mymachine",
   "license_systemid" : "10799630758371023307",
   "license_key" : "...license_key...",
   "license_valid" : true,
   "memory_swapused_bytes" : 8265138176,
   "memory_last_update" : 1538925240573,
   "memory_total_bytes" : 67475775488,
   "memory_swaptotal_bytes" : 12813594624,
   "memory_consumed_bytes" : 67061047296,
   "cpu_last_update" : 1538925240573,
   "cpu_cores" : 8,
   "cpu_usage_percent" : 54.1457290649414,
   "disk_quota_earliest_result" : 1538924513527,
   "disk_quota_total_bytes" : 2147483648,
   "disk_quota_consumed_bytes" : 524288000,
   "processing_threads_configured" : 1,
   "processing_threads_active" : 1,
   "timestamp" : 1538925244693,
   "daemon_uptime_seconds" : 35,
   "system_uptime_seconds" : 585390,
   "recording_enabled" : false,
   "agent_type" : "alprd",
   "agent_version" : "2.6.101",
   "beanstalk_queue_size" : 0,
   "openalpr_version" : "2.6.101",
   "os" : "linux",
   "video_streams" : [
         "fps" : 30,
         "camera_id" : 2090267338,
         "camera_name" : "h265",
         "last_update" : 1538925244689,
         "is_streaming" : true,
         "url" : "rtsp://"

Local Image Retrieval

The OpenALPR agent exposes a simple web service for retrieving license plate images. Each image is referenced by a UUID that is sent along with the JSON metadata.

By default, this web server is disabled on the agent, but you can turn it on by adding “web_server_enabled = 1” to the alprd.conf file.

Assuming that the daemon port is set to the default (8355), the full image is referenced with the following URL:

  • http://[Agent_IP]:8355/img/[plate_event_uuid].jpg

In some cases, you may prefer to retrieve a cropped image of just the license plate. This requires significantly less bandwidth than downloading the entire source image. The X and Y coordinates can be computed from the JSON metadata x/y coordinates of the license plate. The x1/y1 coordinates reference the top left of the license plate crop region, and the x2/y2 coordinates reference the bottom right. For example, assuming the crop is located at (477,258), (632,297):

  • http://[Agent_IP]:8355/crop/[plate_event_uuid]?x1=477&y1=258&x2=632&y2=297

In addition, the web server exposes a web service API for searching license plates and groups. Detailed documentation is available in the web server section

Forensic Plate Finder

The Forensic Plate Finder processes video or image files (e.g., MPG, AVI, or MP4) to find all of the license plates. The output is a CSV file that lists the license plate information


To use this utility, you must have a commercial license key. Request a free 14-day evaluation key. The license key must be saved in /etc/openalpr/license.conf.


Download and run the OpenALPR Forensic Plate Finder Installer.

After the software is installed, the Forensic Plate Finder will be located in the install directory and as a Windows shortcut on the start menu.


Install the OpenALPR agent following the install procedure in the OpenALPR agent section.

Run the following command to install the OpenALPR video utility:

` sudo apt update && sudo apt install openalpr-video `

After the install is complete, you can execute the alprvideogui and alprvideocli utility directly on the command line.

GUI Usage

Launch the Forensic Plate Finder by clicking the “OpenALPR Forensic Plate Finder” shortcut created by the installer.

OpenALPR Forensic Plate Finder

Once launched, choose Edit->Preferences to select the country, number of processing threads, and the output directory.

Click “Open video…” to select files for processing. The utility can accept:

  • One or more video files
  • One or more JPG image files

Once you’ve selected one or more files to process, click the “Start” button to begin processing. Each file will be processed in order. A spreadsheet for each video file will be placed in the output folder that you specified in the preferences.

Command-Line Usage

Launch the alpr_video program with a path to a video file. In addition include an output directory; this is where the CSV and SQLite files are saved. The threads option provides more threads to process the video simmultaneously. This should not exceed the number of CPU cores on the machine.


   ./alpr_video  --output_dir <output_dir> [-c <country_code>] [--config
                 <config_file>] [-n <topN>] [--threads <num_threads>] [-p
                 <pattern code>] [--save_frames] [--debug] [--motion] [--]
                 [--version] [-h] <video_file_path>


   --output_dir <output_dir>
     (required)  Path to the output directory

   -c <country_code>,  --country <country_code>
     Country code to identify (either us for USA or eu for Europe).

   --config <config_file>
     Path to the openalpr.conf file

   -n <topN>,  --topn <topN>
     Max number of possible plate numbers to return.  Default=10

   --threads <num_threads>
     Number of simmultaneous processing threads. Default=1

   -p <pattern code>,  --pattern <pattern code>
     Attempt to match the plate number against a plate pattern (e.g., md
     for Maryland, ca for California)

     Save the image frames for recognized license plates.  Default=off

     Print diagnostic information to the console.  Default=off

     Use motion detection on video file or stream.  Default=on

   --,  --ignore_rest
     Ignores the rest of the labeled arguments following this flag.

     Displays version information and exits.

   -h,  --help
     Displays usage information and exits.

     (required)  Video file containing license plates

   OpenAlpr Forensic Plate Finder


The results are made available in CSV files as well as a SQLite database for querying. The image frames in which license plates were found are also optionally saved to a folder on the disk.

The CSV data is exported in two files. One file shows the individual plate reads, while the other shows the plate groups. For example:

Plate Results:

Plate Results
id group_id country plate_number confidence frame_num video_time_s matches_pattern tracking_hash x1 y1 x2 y2 x3 y3 x4 y4 img_name region region_confidence
1 2 gb CV60UWK 78.4882 70 2.84 1   36 235 176 280 169 314 29 267   gb 0
2 2 gb CV60UWK 75.4025 73 2.96 1   134 180 269 220 260 251 127 209   gb 0
3 2 gb CV60UWK 83.4606 74 3 1   167 159 310 199 300 238 159 196   gb 0
4 2 gb CV60UWK 82.3763 75 3.04 1   198 141 332 180 322 215 189 177   gb 0

Plate groups:

Plate Groups
id country plate_number matches_pattern plate_count frame_start frame_end video_time_start_s video_time_end_s best_plate_id confidence region region_confidence
2 gb CV60UK 0 6 70 77 2.84 3.12 6 82.6058 gb 0
1 gb GP0VZC 0 9 199 211 8 8.48 18 84.4312 gb 0
4 gb GR15RYT 1 2 981 994 39.28 39.8 39 82.4912 gb 0