PlateAPIPlateAPI
DemoPricingDocsBlogLoginGet API Key
Demo→Pricing→Docs→Blog→Login→Get API Key→

Blog · 4 October 2026 · 6 min read

How to Look Up Australian Number Plates in Python

This guide covers looking up Australian registration plates from Python with plateapi, PlateAPI's official SDK. It handles the HTTP calls, retries and error codes for you, so a lookup is one line. Every example below was run against the live API on 4 October 2026. The lookup examples use the free sandbox plate TEST123, so you can run them without spending a lookup; the vehicle database examples need a Starter plan or above.

Install

shell
pip install plateapi

It needs Python 3.8 or later and depends only on requests. The SDK's code is on GitHub and the package on PyPI. You also need an API key: create a free account (20 lookups a month, no card) and copy the key from your dashboard. Keep it in an environment variable rather than in your code.

Your first lookup

python
import os
from plateapi import PlateAPI

client = PlateAPI(os.environ["PLATEAPI_KEY"])
result = client.lookup("TEST123", "NSW")   # the free sandbox plate

if result.success:
    v = result.vehicle
    print(v.year_range, v.make, v.model, v.body, v.engine)
    print(v.vehicle_id, result.match, result.request_id)
else:
    print(result.code, result.error)
output
2015-2020 TOYOTA HILUX UTE 2.8L
1380801 exact req_33d68941f9dfb9dcec7d8cab

The state is one of ACT, NSW, NT, QLD, SA, TAS, VIC or WA. The SDK upper-cases and trims the plate and state, and raises ValueError for an unknown state before sending anything. Swap TEST123 for a real plate when you are ready; each real plate counts as one lookup.

A plate that does not resolve is a normal result, not an exception: result.success is False and result.code is "not_found". It still counts toward your quota, so check the plate format before you send it.

vehicle_id and match

Every vehicle in a result carries vehicle_id, PlateAPI's stable ID for that exact variant. Store it instead of the make and model text: it is the same ID the vehicle database uses, it never changes, and it is the key to link your own records, such as products or service history, to vehicles. result.match says how to read the answer:

  • "exact": one variant, in result.vehicle.
  • "multiple": several trims of one make and model on sale at the same time. result.vehicle is the first, the rest are in result.alternatives.
  • "ambiguous": different models or generations. result.vehicle.vehicle_id is None (an ID is never guessed) and result.alternatives lists every candidate with its ID.
python
if result.match == "exact":
    save(result.vehicle.vehicle_id)
else:
    for alt in result.alternatives:
        print(alt.vehicle_id, alt.year_range, alt.description)
    save_all(result.candidate_ids)   # every non-null ID, primary first

For a customer-facing form, showing the candidates and letting the customer pick theirs is usually best. The SKU linking guide shows how stores use these IDs to list the parts that fit.

The full vehicle record

On Starter plans and above, vehicle_by_id() returns the full record for an ID, including the series, full engine description, drive and gearbox. It does not use lookup quota.

python
record = client.vehicle_by_id(1380801)
print(record.make, record.model, record.year_range)
print(record.series, "|", record.engine)
print(record.body, record.doors, record.drive, record.transmission, record.years)
output
TOYOTA HILUX SR 2015-2020
GUN126R -GUN126 | 2.8L,  DIE 1GDFTV I4 16v DOHC I/C Turbo CRD {130kW}
UTE 4 4WD AT/MT [2015, 2016, 2017, 2018, 2019, 2020]

Note the model: the lookup said HILUX, the record says HILUX SR. The wording can differ, the ID does not, which is why you integrate on the ID.

Make, model and year menus, cars and motorcycles

On Starter plans and above, vehicles() walks the vehicle database one level at a time (no lookup quota used): no arguments returns the makes, make returns its models, model its years, and so on down to vehicle records. Pass vehicle_type="motorcycle" for the separate motorcycle cascade.

python
makes = client.vehicles()
print(makes.type, makes.total, makes.data[:3])

years = client.vehicles(make="TOYOTA", model="HILUX")
print(years.type, years.data[:5])

bikes = client.vehicles(make="YAMAHA", vehicle_type="motorcycle")
print(bikes.type, bikes.total, bikes.data[:5])
output
make 227 ['ABARTH', 'ACE EV', 'ACURA']
year [2025, 2024, 2023, 2022, 2021]
model 628 ['1700', 'AEROX', 'AG100', 'AG125', 'AG175']

Pass each value back exactly as it was returned; the SDK URL-encodes it. To collect every ID for a model range in one go, walk_vehicles() does the whole walk and yields each vehicle once. The motorcycle guide has a full bike example.

Errors and retries

Errors are exceptions with the API's own message, HTTP status and code. The SDK already retries connection errors, rate limits and temporary server errors with backoff, so what reaches your code is worth handling:

python
from plateapi import (
    PlateAPIError, QuotaExceededError, RateLimitError, ServerError,
)

try:
    result = client.lookup(plate, state)
except QuotaExceededError:
    ...   # monthly lookup quota used up
except RateLimitError as e:
    ...   # per-minute limit: retry after e.retry_after seconds
except ServerError as e:
    ...   # temporary failure, not billed: retry later (e.code, e.request_id)
except PlateAPIError as e:
    ...   # anything else: invalid key, IP not allowed, network failure

A lookup that cannot be completed returns 503 with code lookup_failed and is never billed. Quote request_id if you contact support about a specific request.

Testing with TEST123

The sandbox plate returns a fixed vehicle instantly with any state. It is free, it does not touch your quota or rate limit, and it is a real record (vehicle_id 1380801), so it works in CI:

python -- test_vehicle_lookup.py
import os

import pytest
from plateapi import PlateAPI


@pytest.fixture(scope="session")
def client():
    with PlateAPI(os.environ["PLATEAPI_KEY"]) as c:
        yield c


def test_sandbox_plate_is_a_hilux(client):
    result = client.lookup("TEST123", "VIC")
    assert result.success and result.sandbox
    assert result.match == "exact"
    assert result.vehicle.make == "TOYOTA"
    assert result.vehicle.vehicle_id == 1380801
output
$ pytest -q test_vehicle_lookup.py
.                                                                        [100%]
1 passed in 0.18s

Next steps

  • The SDK README lists every field, the usage and logs calls, and the retry settings.
  • The lookup reference and vehicle database reference document the API underneath.
  • Prefer plain HTTP? The developer guide has cURL, requests and JavaScript examples.

PlateAPI turns Australian number plates into structured vehicle data -- one REST endpoint, all eight states, free tier included.

Try the live demo · API reference · Pricing

More from the blog

  • Australian Rego Check API for Developers
  • How to Link Auto Parts SKUs to Vehicles with Vehicle IDs
  • Motorcycle Make, Model and Year Database API for Australia
PlateAPIPlateAPI

Australian vehicle registration plate lookup API. Operated by WolfStack Solutions, ABN 26 877 229 839, Melbourne, Australia.

[email protected]
(03) 9122 8765

ProductLive DemoPricingAPI ReferencePlate Lookup APIVehicle Database APIGitHubGet an API Key
CompanyBlogContactAPI StatusTerms of ServicePrivacy PolicySecurity
© 2026 WolfStack Solutions. All rights reserved.