# DVSA MOT History Check (`wildorigins/uk-mot-history`) Actor

🏷️ From $6.00 / 1K | Full MOT history for any UK vehicle by registration, from the official DVSA API. Test results, mileage at every test, advisories, failures and mileage anomaly detection. No API key needed.

- **URL**: https://apify.com/wildorigins/uk-mot-history.md
- **Developed by:** [Wild Origins](https://apify.com/wildorigins) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 mot records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## DVSA MOT History Check

Look up the full MOT history of any UK vehicle by registration number, using the official DVSA MOT History API. No API key needed.

### 🔍 What does UK DVSA MOT History do?

You give it one or more UK registration plates. It returns test dates, pass and fail results, recorded mileage at every test, advisories and failure reasons, as structured data ready for export.

It also does the reading for you. Mileage across every recorded test is checked for a reading that goes backwards, dangerous defects are flagged, and every plate the vehicle has been tested under is listed, so a plate change shows up rather than hiding.

### 📊 What data can I extract from the MOT register?

One dataset item per registration looked up, with the full test history nested inside it.

| Field | Description |
|---|---|
| `registration` | The plate, normalised |
| `make`, `model` | Vehicle make and model |
| `firstUsedDate`, `registrationDate`, `manufactureDate` | ISO dates |
| `fuelType`, `primaryColour`, `engineSize` | Vehicle details |
| `motTestCount` | Number of MOT tests on record |
| `latestTestResult` | `PASSED` or `FAILED` at the most recent test |
| `latestExpiryDate` | When the current MOT runs out |
| `latestMileage` | Odometer reading at the most recent test |
| `highestMileage` | Highest reading ever recorded, useful for spotting clocking |
| `hasDangerousDefects` | True if any test recorded a dangerous defect |
| `hasOutstandingRecall` | DVSA outstanding safety recall status |
| `mileageAnomaly` | True if a later test recorded lower mileage than an earlier one, the classic clocking signal |
| `registrationsSeen` | Every plate this vehicle has been tested under, useful for spotting a plate change |
| `motTests[]` | Every test, newest first |
| `sourceUrl` | The vehicle on the DVSA checker |
| `scrapedAt` | When the row was collected, ISO 8601 |

Each entry in `motTests` contains `completedDate`, `testResult`, `passed`, `expiryDate`, `odometerValue`, `odometerUnit`, `odometerResultType`, `motTestNumber`, `registrationAtTimeOfTest`, `dataSource`, `defectCount`, `dangerousDefectCount`, `advisories`, `failureReasons`, and the raw `defects` array.

### 💡 Why look up MOT history?

**Used car buyers.** Check mileage consistency across every recorded test before viewing a car.

**Dealers and traders.** Bulk check a batch of plates before auction or listing.

**Fleet operators.** Track MOT expiry dates across a fleet and catch dangerous defects early.

**Garages.** Pull prior advisories before a service so nothing gets missed.

### 🚀 How do I use UK DVSA MOT History?

1. Click **Try for free**.
2. Enter one or more registration plates in `registration`, separated by commas.
3. Raise `maxResults` if you are checking a batch.
4. Click **Start** and wait for the run to finish.
5. Download the results as JSON, CSV or Excel, or pull them from the API.

### ⬇️ Input

```json
{
  "registration": "AB12CDE",
  "maxResults": 1
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `registration` | string | `AB12CDE` | One or more UK plates, comma separated, for example `AB12CDE, ZZ99ABC`. Spaces and case are ignored |
| `maxResults` | integer | `1` | Cap on how many registrations to process in one run, maximum 1000 |
| `clientId` | string | | Optional, use your own DVSA account |
| `clientSecret` | string | | Optional, use your own DVSA account |
| `apiKey` | string | | Optional, use your own DVSA account |
| `tokenUrl` | string | | Optional, use your own DVSA account |

### ⬆️ Output

#### Table view

Results arrive as a Vehicles table you can sort and filter in the Console, with make, model, fuel type, the latest result, expiry date, latest mileage, test count and the dangerous defect flag lined up per registration.

A plate with no MOT record is logged and skipped rather than failing the run. A run summary with any failures is written to `RUN_SUMMARY` in the key value store.

#### JSON

A typical row:

```json
{
  "registration": "AB12CDE",
  "make": "VAUXHALL",
  "model": "ASTRA",
  "fuelType": "Petrol",
  "latestTestResult": "PASSED",
  "latestExpiryDate": "2027-06-11T00:00:00.000Z",
  "latestMileage": 43244,
  "motTestCount": 9,
  "hasDangerousDefects": false,
  "firstUsedDate": "2017-06-19T00:00:00.000Z"
}
```

Download it from the run as JSON, CSV or Excel, or read it straight from the API.

### No API key needed

This Actor includes DVSA MOT History API access, so you can run it straight away. Nothing to register for and nothing to configure.

If you would rather run against your own DVSA account, fill in the four optional credential fields under "Advanced" and they take priority. Register free at [documentation.history.mot.api.gov.uk](https://documentation.history.mot.api.gov.uk/).

### Data licence

MOT data comes from DVSA and is published under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Commercial use is permitted with attribution:

*Contains public sector information licensed under the Open Government Licence v3.0.*

Respect the DVSA rate limits and terms of use.

### ⏱️ How long does a run take?

Measured on real runs, so you know what normal looks like and can tell it apart from a run that has stalled.

| Registrations looked up | Typical run time |
|---|---|
| 1 | 3 to 5 seconds |
| 5 | about 6 seconds |

A lookup is one call to the DVSA MOT History API and it answers in well under a second, so almost all of a single registration run is the container starting rather than the work. That is why five registrations cost about six seconds rather than five times three: the fixed cost is paid once and each further plate adds a fraction of a second.

The one thing that can lengthen a run is DVSA rate limiting on a long list, which the Actor backs off from rather than pushing through. A registration that the register holds no record of is reported as a miss with the reason attached and does not stop the rest of the list.

A run is never silently stuck. Every registration is logged as it is looked up and written to the dataset as it returns rather than held back to the end, so a run that hits its time limit still leaves every vehicle history it had already collected. A run where no plate could be looked up at all finishes with an empty dataset and the reason in its status message, and the RUN\_SUMMARY record lists every plate that missed.

**Set the run timeout to suit the size of the ask.** This Actor's default is 3600 seconds, which is comfortably more than the largest run in the table above (one registration takes well under a minute). You are charged per delivered result rather than per minute, so a generous timeout costs you nothing and a tight one risks losing the run's work. Lower it only if you want a hard ceiling on how long a scheduled run may sit.

### 💰 How much does it cost?

Right now this Actor rents at $10 a month, which covers as many lookups as you need.

**From 21 August 2026 it moves to pay per result at $0.02 per registration.** One charge covers the vehicle record and its complete test history, however many tests are on file. Set `maxResults` to cap what a run can cost.

Plates with no MOT record are skipped and cost nothing under the new pricing.

### 🔌 Integrations

Send results straight to Google Sheets, Slack, Airtable, Zapier, Make or your own webhook using [Apify integrations](https://docs.apify.com/platform/integrations). You can also trigger a run whenever something happens in another tool.

### 🔗 Using UK DVSA MOT History with the Apify API

```bash
curl -X POST "https://api.apify.com/v2/acts/spookyweb~uk-mot-history/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"registration": "AB12CDE", "maxResults": 1}'
```

Or with the Apify client:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('spookyweb/uk-mot-history').call({
  registration: 'AB12CDE',
  maxResults: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Full detail is in the [Apify API reference](https://docs.apify.com/api/v2), and every run is also callable from the [Python](https://docs.apify.com/api/client/python) and [JavaScript](https://docs.apify.com/api/client/js) clients.

### ❓ FAQ

#### Do I need my own DVSA API key?

No. Access is built in, so you can run it straight away. There are four optional credential fields under "Advanced", `clientId`, `clientSecret`, `apiKey` and `tokenUrl`, if you would rather the requests ran against your own free DVSA account. Fill them in and they take priority.

#### What does mileage anomaly detection do?

It compares the odometer reading at every recorded test in order. If a later test reports fewer miles than an earlier one, `mileageAnomaly` is true. That is the classic clocking signal. `highestMileage` gives you the largest reading ever recorded, which is the figure to compare an advert against.

#### Can I check several registrations at once?

Yes. Put them all in `registration` separated by commas, and raise `maxResults`, which caps how many are processed in one run and goes up to 1000. Spaces and letter case in a plate are ignored.

#### How far back does the history go?

As far back as DVSA holds tests for that vehicle, newest first in `motTests`. `motTestCount` tells you how many are on record. A vehicle too new to have had its first MOT returns a vehicle record with no tests, which is an answer rather than an error.

#### What counts as a dangerous defect?

A defect the tester recorded at the dangerous level, meaning the vehicle should not be driven until it is repaired. `hasDangerousDefects` flags whether any test ever recorded one, and `dangerousDefectCount` on each test says how many, with the detail in `defects` and `failureReasons`.

#### What happens if a plate has no record?

It is logged and skipped, and the run carries on with the rest. A summary of anything that failed is written to `RUN_SUMMARY` in the key value store, so you can see exactly which plates did not resolve.

### ⚖️ Is it legal to use DVSA MOT data?

This uses the DVSA's official MOT History API, the government service provided for looking up a vehicle's test history. It returns data about a vehicle rather than about a person, and the registration is a vehicle identifier.

The data is published under the Open Government Licence v3.0 and commercial use is permitted with the attribution above. Respect the DVSA rate limits and terms of use. If you go on to link a registration to a named individual, that combination is personal data and handling it is on you under GDPR. Apify's [ethical scraping guide](https://blog.apify.com/is-web-scraping-legal/) covers the wider picture.

### 👍 Your feedback

Found a bug, or want a field that is not here yet? Open an issue on the Actor's Issues tab. Requests that make the data more useful get built, and problems get fixed quickly.

### 🔎 You might also like

| Actor | What it does |
|---|---|
| [UK Insolvency Register Search](https://apify.com/spookyweb/uk-insolvency-register-search) | Bankruptcies, IVAs, DROs and restrictions orders from the official register |
| [UK Food Hygiene Ratings](https://apify.com/spookyweb/uk-food-hygiene-ratings) | Food hygiene ratings for every UK food business, straight from the FSA |
| [Website Contact Scraper](https://apify.com/spookyweb/website-contact-scraper) | Emails, phones, socials and addresses from company websites, one record per domain |

# Actor input Schema

## `registration` (type: `string`):

UK registration number(s) to check. Separate multiple plates with commas, e.g. AB12CDE, ZZ99ABC. Spaces and case are ignored.

## `maxResults` (type: `integer`):

Maximum number of registrations to process in a single run.

## `clientId` (type: `string`):

Optional. Leave blank to use this Actor built in DVSA access. Only fill these in if you want to run against your own DVSA account.

## `clientSecret` (type: `string`):

Optional. Leave blank to use this Actor built in DVSA access. Only fill these in if you want to run against your own DVSA account.

## `apiKey` (type: `string`):

Optional. Leave blank to use this Actor built in DVSA access. Only fill these in if you want to run against your own DVSA account.

## `tokenUrl` (type: `string`):

Optional. Leave blank to use this Actor built in DVSA access. Only fill these in if you want to run against your own DVSA account.

## Actor input object example

```json
{
  "registration": "AB12CDE",
  "maxResults": 1
}
```

# Actor output Schema

## `results` (type: `string`):

One row per item: vehicles with their full MOT history.

## `runSummary` (type: `string`):

Counts and stop reason for the run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "registration": "AB12CDE"
};

// Run the Actor and wait for it to finish
const run = await client.actor("wildorigins/uk-mot-history").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "registration": "AB12CDE" }

# Run the Actor and wait for it to finish
run = client.actor("wildorigins/uk-mot-history").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "registration": "AB12CDE"
}' |
apify call wildorigins/uk-mot-history --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wildorigins/uk-mot-history"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/S2Hb8hcpvjq36JNbU/builds/KIwqWlQY1ugTbO0Jd/openapi.json
