# UK Identifier Checker (MPAN, VAT, NINO, NHS, LEI, EIC, IBAN) (`landlordtools/uk-identifier-checker`) Actor

Check the format and check digits of UK and energy-market identifiers in bulk: MPAN, VAT, EORI, National Insurance, NHS, UTR, company numbers, postcodes, IBAN, LEI, EIC and GTIN. Auto-detects the type. No lookups, no data stored.

- **URL**: https://apify.com/landlordtools/uk-identifier-checker.md
- **Developed by:** [LandlordTools](https://apify.com/landlordtools) (community)
- **Categories:** Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 identifier results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## UK Identifier Checker

Check UK and energy-market identifiers in bulk, before they go into a CRM, a billing system or a regulatory report: the format, and the check digit where the identifier has one. Leave `type` out and the Actor works out what each value is. No lookups, no paid APIs, nothing stored.

### What it checks

| `type` | Identifier | Test |
|---|---|---|
| `mpan` | Electricity supply number: the 13-digit core, or the full 21 digits | Check digit: digits times 3, 5, 7, 13 ... 43, sum mod 11 mod 10 [1]. Shows the distributor ID, and for full MPANs the profile class, meter time-switch code and line loss factor class |
| `vat` | UK VAT number (GB or XI, 9 digits, or 12 for a branch; GD and HA numbers) | Modulus 97 check: the original rule, plus the newer ranges for numbers from 100 000 000 (the same rules as python-stdnum [12]). A pass doesn't mean the number is registered: use HMRC's checker [7] |
| `eori` | GB or XI EORI | GB or XI followed by 12 digits [6] |
| `nino` | National Insurance number | HMRC's prefix and suffix rules (no D, F, I, Q, U or V; no O second; never BG, GB, KN, NK, NT, TN, ZZ; suffix A to D) [2] |
| `nhs` | NHS number | Modulus 11, as the NHS Data Dictionary sets out [3] |
| `utr` | Unique Taxpayer Reference | 10 digits [4]. HMRC publishes no check-digit method, so it's a format check only |
| `company-number` | Companies House number | 8 digits, or 2 letters and 6 digits; short numbers padded; the prefix explained (SC Scotland, OC LLP and so on) |
| `postcode` | UK postcode | The GOV.UK published pattern [5]; returns the tidy form (`SW1A 1AA`) and outward and inward codes |
| `iban` | IBAN | ISO 7064 MOD 97-10 [10]. For GB IBANs: length 22, bank code, sort code and account number |
| `lei` | Legal Entity Identifier | ISO 17442: MOD 97-10 [9] |
| `eic` | ENTSO-E Energy Identification Code | The mod-37 check character, and the object type (party, area, measurement point and so on) [8] |
| `gtin` | GTIN-8, 12, 13 or 14 (barcodes) | GS1 check digit [11] |

Every algorithm is also cross-checked against python-stdnum [12], an independent open-source implementation (`tests/crosscheck_stdnum.py`: 5,600 generated cases, no disagreements).

### Input

```json
{
  "items": [
    {
      "type": "mpan",
      "value": "12 0000 0001 238"
    },
    {
      "value": "GB 339 0727 47"
    },
    {
      "value": "10YGB----------A"
    },
    {
      "value": "506700GE1G29325QX363"
    },
    {
      "value": "GB82 WEST 1234 5698 7654 32"
    },
    {
      "value": "sw1a1aa"
    },
    {
      "type": "company-number",
      "value": "SC123456"
    },
    {
      "type": "nhs",
      "value": "999 000 0018"
    },
    {
      "value": "QQ 12 34 56 C"
    },
    {
      "type": "gtin",
      "value": "5012345678901"
    }
  ],
  "redact": true
}
```

- **`items`**: 1 to 10,000 objects, each `{"value": ..., "type": ...}`. `type` defaults to `auto`.
- **`redact`** (default `true`): shows only the last 3 characters of National Insurance, NHS and UTR numbers in the results, so personal identifiers don't sit in your dataset.

### Example output

The first item:

```json
{
  "index": 0,
  "type": "mpan",
  "normalised": "1200000001238",
  "valid": true,
  "formatValid": true,
  "checkDigitValid": true,
  "details": {
    "core": "1200000001238",
    "distributorId": "12"
  },
  "error": null
}
```

`valid` is true when the format is right and the check digit (if the identifier has one) is right. `checkDigitValid` is `null` for identifiers without a check digit. In `auto` mode, `details.alsoMatches` lists any other types the value would also pass as. A 13-digit number, for example, can be both an MPAN core and a GTIN-13, so set `type` when you know it. The OUTPUT record adds a summary and the sources.

### What it doesn't do

It doesn't confirm that an identifier was issued, is active or belongs to a particular person or business. For that, use the issuer's own service: HMRC's VAT checker [7], the GOV.UK EORI checker, Companies House or GLEIF. It doesn't check MPRNs (gas), because no check method is published.

### Integrations

Ready-made files in [`integrations/`](integrations/README.md): a **Microsoft Power Platform custom connector** (Power Automate, Power Apps, Logic Apps, Copilot Studio), **OpenAPI 3** (Azure API Management, Postman, n8n, AI agents), an **Excel / Power BI Power Query** script, a **Google Sheets** function, and curl, Python and JavaScript examples. Apify's own Zapier, Make and n8n apps and its MCP server work too.

### Pricing

Pay per event: $3 per 1,000 results, plus Apify's tiny per-run start fee ($0.00005). See the Pricing tab for the current price.

### Sources

1. [Wikipedia: Meter Point Administration Number (MPAN core check digit)](https://en.wikipedia.org/wiki/Meter_Point_Administration_Number). Accessed 3 October 2026.
2. [HMRC: NIM39110, what a National Insurance number looks like](https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110). Accessed 3 October 2026.
3. [NHS Data Dictionary: NHS Number (Modulus 11 check)](https://v2.datadictionary.nhs.uk/data_dictionary/attributes/n/nhs_number_de.asp@shownav=1.html). Accessed 3 October 2026.
4. [OECD: UK tax identification numbers (UTR and NINO formats)](https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/UK-TIN.pdf). Accessed 3 October 2026.
5. [GOV.UK: Bulk Data Transfer, additional validation (UK postcode regular expression)](https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/488478/Bulk_Data_Transfer_-_additional_validation_valid_from_12_November_2015.pdf). Accessed 3 October 2026.
6. [GOV.UK: Economic Operators Registration and Identification (EORI)](https://www.gov.uk/guidance/economic-operators-registration-and-identification-eori/introduction). Accessed 3 October 2026.
7. [GOV.UK: Check a UK VAT number](https://www.gov.uk/check-uk-vat-number). Accessed 3 October 2026.
8. [ENTSO-E: Energy Identification Codes (EIC) and the EIC Reference Manual](https://www.entsoe.eu/data/energy-identification-codes-eic/). Accessed 3 October 2026.
9. [GLEIF: ISO 17442, the LEI code structure](https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure). Accessed 3 October 2026.
10. [SWIFT: IBAN Registry](https://www.swift.com/standards/data-standards/iban-international-bank-account-number). Accessed 3 October 2026.
11. [Google Merchant Center: Product data specification (GTIN check digit rules)](https://support.google.com/merchants/answer/7052112). Accessed 3 October 2026.
12. [python-stdnum (independent reference implementation used to cross-check these algorithms)](https://pypi.org/project/python-stdnum/). Accessed 3 October 2026.

[1]: https://en.wikipedia.org/wiki/Meter_Point_Administration_Number

[2]: https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110

[3]: https://v2.datadictionary.nhs.uk/data_dictionary/attributes/n/nhs_number_de.asp@shownav=1.html

[4]: https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/UK-TIN.pdf

[5]: https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/488478/Bulk_Data_Transfer_-_additional_validation_valid_from_12_November_2015.pdf

[6]: https://www.gov.uk/guidance/economic-operators-registration-and-identification-eori/introduction

[7]: https://www.gov.uk/check-uk-vat-number

[8]: https://www.entsoe.eu/data/energy-identification-codes-eic/

[9]: https://www.gleif.org/en/about-lei/iso-17442-the-lei-code-structure

[10]: https://www.swift.com/standards/data-standards/iban-international-bank-account-number

[11]: https://support.google.com/merchants/answer/7052112

[12]: https://pypi.org/project/python-stdnum/

# Actor input Schema

## `items` (type: `array`):

1 to 10000 objects: {value, type?}. type is one of mpan, vat, eori, nino, nhs, utr, company-number, postcode, iban, lei, eic, gtin, auto (default auto: the type is detected).

## `redact` (type: `boolean`):

Show only the last 3 characters of National Insurance, NHS and UTR numbers in the results (default true).

## Actor input object example

```json
{
  "items": [
    {
      "type": "mpan",
      "value": "12 0000 0001 238"
    },
    {
      "value": "GB 339 0727 47"
    },
    {
      "value": "10YGB----------A"
    },
    {
      "value": "506700GE1G29325QX363"
    },
    {
      "value": "GB82 WEST 1234 5698 7654 32"
    },
    {
      "value": "sw1a1aa"
    },
    {
      "type": "company-number",
      "value": "SC123456"
    },
    {
      "type": "nhs",
      "value": "999 000 0018"
    },
    {
      "value": "QQ 12 34 56 C"
    },
    {
      "type": "gtin",
      "value": "5012345678901"
    }
  ],
  "redact": true
}
```

# Actor output Schema

## `result` (type: `string`):

No description

## `output` (type: `string`):

No description

# 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 = {
    "items": [
        {
            "type": "mpan",
            "value": "12 0000 0001 238"
        },
        {
            "value": "GB 339 0727 47"
        },
        {
            "value": "10YGB----------A"
        },
        {
            "value": "506700GE1G29325QX363"
        },
        {
            "value": "GB82 WEST 1234 5698 7654 32"
        },
        {
            "value": "sw1a1aa"
        },
        {
            "type": "company-number",
            "value": "SC123456"
        },
        {
            "type": "nhs",
            "value": "999 000 0018"
        },
        {
            "value": "QQ 12 34 56 C"
        },
        {
            "type": "gtin",
            "value": "5012345678901"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("landlordtools/uk-identifier-checker").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 = { "items": [
        {
            "type": "mpan",
            "value": "12 0000 0001 238",
        },
        { "value": "GB 339 0727 47" },
        { "value": "10YGB----------A" },
        { "value": "506700GE1G29325QX363" },
        { "value": "GB82 WEST 1234 5698 7654 32" },
        { "value": "sw1a1aa" },
        {
            "type": "company-number",
            "value": "SC123456",
        },
        {
            "type": "nhs",
            "value": "999 000 0018",
        },
        { "value": "QQ 12 34 56 C" },
        {
            "type": "gtin",
            "value": "5012345678901",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("landlordtools/uk-identifier-checker").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 '{
  "items": [
    {
      "type": "mpan",
      "value": "12 0000 0001 238"
    },
    {
      "value": "GB 339 0727 47"
    },
    {
      "value": "10YGB----------A"
    },
    {
      "value": "506700GE1G29325QX363"
    },
    {
      "value": "GB82 WEST 1234 5698 7654 32"
    },
    {
      "value": "sw1a1aa"
    },
    {
      "type": "company-number",
      "value": "SC123456"
    },
    {
      "type": "nhs",
      "value": "999 000 0018"
    },
    {
      "value": "QQ 12 34 56 C"
    },
    {
      "type": "gtin",
      "value": "5012345678901"
    }
  ]
}' |
apify call landlordtools/uk-identifier-checker --silent --output-dataset

```

## MCP server setup

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

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/G8cDF61se49SCaa6m/builds/nBrpUHLLOOd7UHbhD/openapi.json
