Node Red Contrib Plate Recognizer

Automatic License Plate Recognition (ALPR) or Automatic Number Plate Recognition (ANPR) on Node-RED.

Automatic License Plate Recognition (ALPR, ANPR) on Node-RED

Get high-accuracy, developer-friendly automatic license plate recognition (ALPR) or automatic number plate recognition (ANPR) on Node-RED!

Our machine-learning software:

Get license plate reader deployed on Node-RED in under 60 minutes:

ALPR, ANPR software on Node-RED is ideal for parking, toll, community security, and other use cases.

Our license plate recognition (LPR) software can also forward results to our full ALPR Dashboard and Parking Management software solution, ParkPow.

Sign up for a Free Trial now (no credit card required) or learn more at


Run the following npm command in your Node-RED user directory (typically ~/.node-red):

npm install node-red-contrib-plate-recognizer

Note that you need to signup for an account on, and paste your private token into this node's config screen. With a free account there is a limit to recognize 2500 images per month, but they also offer various paid license models.

Node usage

This node will detect and recognise license plates in an image, using a deep learning cloud service. The AI cloud service has been trained for license plates for more than 100 countries.

Send an image (as buffer or base64 encoded string) via an input message, to start a recognition:

Basic flow

[{"id":"38586517.a5bf9a","type":"plate-recognizer","z":"d9a54719.b13a88","name":"","inputField":"payload","inputFieldType":"msg","outputField":"payload","outputFieldType":"msg","url":"","ignoreDuring":false,"makeAndModel":false,"statusText":"none","cameraId":"","regionFilter":false,"timestamp":false,"regionList":"","regionListType":"json","x":880,"y":660,"wires":[["30cb89da.c35546"],[]]},{"id":"e4699284.081c7","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":500,"y":660,"wires":[["9e2c9295.7f9a9"]]},{"id":"30cb89da.c35546","type":"debug","z":"d9a54719.b13a88","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1060,"y":660,"wires":[]},{"id":"9e2c9295.7f9a9","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":680,"y":660,"wires":[["38586517.a5bf9a"]]}]

The output message will contain the recognition results (in json format):

Basic output

The "results" will be a json array, containing a separate element for each license plate that has been recognised. When the image contains N cars, then the array will contain N elements.

For each recognised license plate, some basic information will be delivered:

  • box: the bounding box (coordinates) where the vehicle is located inside the image.

  • plate: the license plate itself as plain text.

  • region: the region of the license plate (e.g. "be" for Belgium). This object contains some nested fields:


    • code: the region code (from the region list).
    • score: the confidence level for the region prediction, which is a value between 0 and 1 (with 1 the highest confidence).
  • vehicle: information about the vehicle itself. This object contains some nested fields:


    • type: the type of vehicle (which can be Ambulance, Bus, Car, Limousine, Motorcycle, Taxi, Truck, Van, Unknown).
    • score: the confidence level for the vehicle prediction, which is a value between 0 and 1 (with 1 the highest confidence).
    • box: the bounding box (coordinates) where the vehicle is located inside the image.
  • score: the confidence level for the license plate text prediction, which is a value between 0 and 1 (with 1 the highest confidence).

  • candidates: sometimes the service isn't really sure whether it has recognised the license plate correctly. Therefore a list of possible plate 'candidates' will be supplied. The first candidate is the same plate that has already been offered at the higher level:


    In this case the AI service thinks (with 90,3% certainty) that the plate its "s0k92h", but it might be that the plate is "sok92h" (with 90,1% certainty). In this case the confusion is between the number "0" and the character "o".

  • dscore: the confidence level for the license plate detection, which is a value between 0 and 1 (with 1 the highest confidence).

Node properties

The node can be configured via a series of settings on the config screen:

Input field

The field of the input message which will need to contain the input image. By default msg.payload will be used. The image should be a binary Buffer or a base64 encoded string.

Output field

The field of the output message where the recognition result will be stored (in JSON format). By default msg.payload will be used.

API token

Create an account at and enter your private API token here.


Specify the URL of the recognition service, to allow different kind of setups:

  • Use the official cloud service, which will be the default (and most used) option.
  • Use a local installation (based on the SDK).
  • Use a local Docker container.

Camera ID

Optionally a camera id can be specified, which will be sent to the recognition service.

Status text

Specify how the recognition result needs to be displayed in the node status label:

  • None: Show no recognition results.
  • Plate count: Show the number of plates that have been recognised in the image.
  • Plates: Show a (comma separted) list of the plates that have been recognized in the image.
  • Plates and scores: Same as the previous option, but now the 'score' percentage is also added.

Ignore images arriving during recognition

When selected images will automatically be skipped, when the previous image is still being recognized. When deselected multiple images can be recognized simultaneously.

Send Timestamp

When selected, the current timestamp will be sent in the request to the recognition service.

Predict vehicle make and model (MMC)

When selected not only the plate will be recognized, but there will also be a prediction of the vehicle brand and type.

CAUTION: this is only supported for some paid account types!

Specify one or more regions

When selected, an array of region codes can be specified (see supported regions.

Example flow (different cases)

The following flow explains some different use cases:

  • Image contain a single car.
  • Image containing a single car, but photografed from an angle. It is important to be able to recognize license plates at angles, because a camera won't always be positioned directly in front of the cars.
  • Image containing two cars, which means the array will contain two individual recognitions.
  • Image containing no cars, which means the array will be empty.
  • Image containing a truck with a license plate, but also some texts on the truck itself. There will be multiple recognitions in the array (because the texts will also be detected!).

Note that the node-red-contrib-image-output node needs to be installed also!


[{"id":"fff72ad.6f8c7d8","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":460,"wires":[["ee55dd94.02b2e"]]},{"id":"28523886.f82428","type":"debug","z":"d9a54719.b13a88","name":"Normal recognitions","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"recognition","targetType":"msg","x":1560,"y":580,"wires":[]},{"id":"ee55dd94.02b2e","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":460,"wires":[["231d72b4.5233ae"]]},{"id":"10f189ae.db2d76","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":660,"wires":[["24464bb6.a07b64"]]},{"id":"24464bb6.a07b64","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":660,"wires":[["231d72b4.5233ae"]]},{"id":"5ee1acd5.4e0784","type":"comment","z":"d9a54719.b13a88","name":"No cars","info":"","x":890,"y":620,"wires":[]},{"id":"231d72b4.5233ae","type":"plate-recognizer","z":"d9a54719.b13a88","name":"","inputField":"payload","inputFieldType":"msg","outputField":"recognition","outputFieldType":"msg","url":"","ignoreDuring":false,"makeAndModel":false,"statusText":"scores","cameraId":"","regionFilter":false,"timestamp":false,"regionList":"","regionListType":"json","x":1320,"y":660,"wires":[["28523886.f82428","37b1b695.62fa4a"],["100a66ab.4607f9"]]},{"id":"37b1b695.62fa4a","type":"image","z":"d9a54719.b13a88","name":"Show analyzed image","width":"400","data":"payload","dataType":"msg","thumbnail":false,"active":true,"x":1740,"y":640,"wires":[]},{"id":"869cd924.d991d8","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":960,"wires":[["f6b6ac8f.40806"]]},{"id":"f6b6ac8f.40806","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":960,"wires":[["231d72b4.5233ae"]]},{"id":"6ac3b436.692fac","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":760,"wires":[["d2c4249d.901fd8"]]},{"id":"d2c4249d.901fd8","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":760,"wires":[["231d72b4.5233ae"]]},{"id":"9a21e444.b22fc8","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":560,"wires":[["8e81e18d.39882"]]},{"id":"8e81e18d.39882","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":560,"wires":[["231d72b4.5233ae"]]},{"id":"5899f099.1b645","type":"comment","z":"d9a54719.b13a88","name":"Two cars","info":"","x":900,"y":520,"wires":[]},{"id":"1db8bd98.23d672","type":"comment","z":"d9a54719.b13a88","name":"One car","info":"","x":890,"y":420,"wires":[]},{"id":"100a66ab.4607f9","type":"debug","z":"d9a54719.b13a88","name":"Errors","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"recognition","targetType":"msg","x":1510,"y":680,"wires":[]},{"id":"cdfaa780.c2fa18","type":"comment","z":"d9a54719.b13a88","name":"Truck with labels","info":"","x":920,"y":920,"wires":[]},{"id":"c1d2f038.82ecc","type":"comment","z":"d9a54719.b13a88","name":"Car at angle","info":"","x":910,"y":720,"wires":[]},{"id":"8c4f0d01.426a2","type":"inject","z":"d9a54719.b13a88","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":920,"y":860,"wires":[["7b580c6e.105764"]]},{"id":"7b580c6e.105764","type":"http request","z":"d9a54719.b13a88","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":1100,"y":860,"wires":[["231d72b4.5233ae"]]},{"id":"da494e5a.e21ff","type":"comment","z":"d9a54719.b13a88","name":"Another car at angle","info":"","x":930,"y":820,"wires":[]}]

Recognition status

The output message will contain the recognition status (and statusText):


  • When the service has finished the recognition without problems, the output message will be send on the first output with status 2xx.
  • When the service isn't able to process the recognition, the output message will be send to the second output with status 4xx. The status code will explain what went wrong:
    • 403: Forbidden due to incorrect API token.
    • 413: The payload is too large and exceeds their upload limits.
    • 429: Too many requests have been send in a given amount of time. Upgrade your license for higher number of calls per second.

Plate statistics

Since the number of recognitions per month is limited (e.g. 2500 for a free account), it is very useful to determine from time to time how many recognitions are left. This way you can avoid situations where you are not aware that you have run out of recognitions...

A second node ("Plate statistics") has been provided to get the statistics of your account (with 'URL' and 'API token' settings identical as described above):

Statistics flow

[{"id":"9b354f46.f081d","type":"plate-statistics","z":"d9a54719.b13a88","name":"","outputField":"payload","outputFieldType":"msg","url":"","x":980,"y":480,"wires":[["54063a77.493ae4"]]},{"id":"5653b69.13c4648","type":"inject","z":"d9a54719.b13a88","name":"Get statistics","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":770,"y":480,"wires":[["9b354f46.f081d"]]},{"id":"54063a77.493ae4","type":"debug","z":"d9a54719.b13a88","name":"Plate statistics","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1190,"y":480,"wires":[]}]

The resulting statistics (in json format) contain the maximum number of statistics, and also the used number of statistics of the current month:

Statistics output

Related Searches