# UK NHS Organisation Lookup (Official ODS Codes) (`japan-open-data/uk-nhs-organisation-lookup`) Actor

Look up the official NHS Organisation Data Service (ODS) register by postcode, type or ODS code: GP practices, pharmacies, dentists, opticians, NHS trusts, ICBs, PCNs, care homes. Open organisations only, updated every working day, no API key, no personal data. JSON via API or MCP. $5/1,000 rows.

- **URL**: https://apify.com/japan-open-data/uk-nhs-organisation-lookup.md
- **Developed by:** [Japan Open Data](https://apify.com/japan-open-data) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 organisation rows

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 NHS Organisation Lookup (Official ODS Codes)

**Look up the United Kingdom's official NHS organisation register — the Organisation Data Service (ODS) run by NHS England — by postcode, organisation type or ODS code.** GP practices, pharmacies, dental practices, opticians, hospitals, NHS trusts, integrated care boards (ICBs), primary care networks (PCNs), care homes and independent providers, one flat JSON row each: ODS code, name, open/closed, role codes, postcode, town, county, switchboard number, website, start and end dates, and the ODS codes of the bodies that commission and operate it. No API key, no login.

- **Organisations only — no personal data.** ODS names many of its entries after the people who run them ("DR KHAN & PARTNERS", "MRS VELDA REILLY", "SIMPSON SALLY (PHYSIOTHERAPIST)"). Every name goes through a second gate and those records are never returned. Street address lines are never output either — only the town, county, postcode and country. The Actor never touches the separate ODS files about individual GPs, nurses and pharmacists.
- **Active only by default.** ODS is full of closed organisations, such as the 106 clinical commissioning groups replaced by integrated care boards in 2022. This Actor returns only organisations that are currently open, unless you ask for the closed ones with `includeInactive`.
- **Official data, updated daily, read live on every run.** NHS England edits ODS every working day: the register's own change feed listed 114 records changed in the 24 hours before 23 September 2026. The ODS datasets are published under the Open Government Licence v3.0.
- **Whole UK.** England, Scotland, Wales, Northern Ireland, the Isle of Man and the Channel Islands are all in ODS. Scottish and Northern Irish GP practices have their own role codes (`RO227`, `RO315`).
- **Postcodes match as a prefix.** This is how the NHS register itself searches: `LS1` returns organisations in LS1 **and** in LS10–LS19, so a short postcode covers a wide area. Every row carries its own `postcode`, the run's status message lists the districts covered, and you can filter afterwards or search with a full postcode (`TS18 1HU`) for one address.

### Why use this instead of the NHS's own tools?

| | NHS ODS Search & Export (official web tool) | Commercial NHS / GP contact lists | **This Actor** |
|---|---|---|---|
| Price | Free | £325–£425 per 1,000 named contacts; a GP-practice database is £1,250 a year for ~6,400 practices | **$5 per 1,000 rows**, pay only for the rows you get |
| How you get it | Download a CSV by hand, or write your own client for the ORD API | Emailed CSV / Excel under a 12-month licence | JSON, CSV or Excel; API, MCP or a scheduled run |
| Personal data | ODS records named after a person are included | Named practice managers, direct dials, personal emails | **Never** — organisations only, no street lines, no mobile numbers |
| Closed organisations | Mixed in with the open ones | Depends on the vendor's refresh cycle | **Excluded by default** (`Active` only) |
| Freshness | Live | Re-verified every 30 days or on a licence renewal | Live — the ORD API is read on every run |
| Detail per row | Paged web tables, one role code at a time | Contact details, no ODS relationships | 28 flat fields including role codes, commissioner and operator ODS codes, dates |

If you only need one organisation, the official tool is free and fine. This Actor is for the cases where you need a **list** — every pharmacy in an area, every NHS trust, 200 ODS codes resolved into names — as flat rows, on a schedule, or from an AI agent.

### What can you do with the NHS organisation register?

1. **Sell to the NHS.** Medical devices, pharmaceuticals, diagnostics, IT, staffing, cleaning, waste, catering, furniture: build a list of every GP practice, pharmacy, dental practice or NHS trust in a postcode area, with its ODS code, switchboard number and website, and refresh it on a schedule.
2. **Join your data to NHS codes.** Prescribing data (OpenPrescribing / NHSBSA), CQC ratings, GP Patient Survey and almost every NHS dataset is keyed by ODS code. Use this Actor to turn codes into names, addresses and organisation types — or names and postcodes into codes.
3. **Track reorganisations.** Practices merge, close and change ICB; `organisationStatus`, `operationalEndDate` and `commissionedByOdsCode` show what happened and who commissions a provider now.
4. **Healthcare market research and M\&A.** Count GP practices, pharmacies or care homes per area, or per integrated care board, and watch the counts change between runs.
5. **AI agents.** "What is the ODS code for Guy's and St Thomas'?", "List the pharmacies in LS1" — one small flat JSON row per organisation, with `status` on every row.

### How to use

1. Click **Start** with the default input: GP practices in Leeds, searched as postcode `LS1` (27 practices on 23 September 2026 — one in LS1 itself and the rest in LS10–LS19, because ODS matches a postcode as a prefix).
2. Change **Postcodes** to the areas you care about — `LS1` or `M1` to sweep a city (they also match `LS10`–`LS19`, `M10`–`M19`), `TS18` or `SW1A` for one outward district, or `TS18 1HU` for one address. Up to 20 per run, and the budget is split evenly between them.
3. Pick an **Organisation type** (pharmacy, dental practice, optician, NHS trust, ICB, PCN, care home…), or choose *Any organisation* to get every kind — including NHS suppliers and administrative records.
4. Or look organisations up directly by **ODS codes**, for example `["RJ1", "A81001", "FA002"]`.
5. Download the results as JSON, CSV or Excel, or call the Actor via API / MCP (see below).

Leaving **Postcodes** empty and choosing an organisation type lists that type across the whole UK (up to `maxResults`).

#### Run it on a schedule

ODS changes every working day, so a saved run keeps a lead list or a code mapping current:

1. Start the Actor once with the input you want and check the rows.
2. On the run page choose **Actions → Schedule Actor** (or **Schedules → Create new** in the left menu) and pick, for example, every Monday at 07:00.
3. Add an integration if you want the rows pushed out — Google Sheets, Slack, a webhook, or pull them with `GET /v2/acts/.../runs/last/dataset/items` after each run.
4. Set a **maximum cost per run** on the schedule so a bad input can never cost more than you expect.

Compare two runs on `odsCode` to spot practices that closed, merged or moved to a different integrated care board since last week.

### Input

No input is required; every field has a default, and running with no input at all returns rows.

| Input | Type | Default | What it does |
|---|---|---|---|
| `postcodes` | array of strings | `["LS1"]` | Outward part (`LS1`, `TS18`, `SW1A`) or a full postcode (`TS18 1HU`). **Matched as a prefix**, so `LS1` also returns LS10–LS19. Up to 20 per run; `maxResults` is split evenly between them. Empty = search by type only. |
| `organisationType` | string | `gpPractice` | `any`, `gpPractice`, `branchSurgery`, `pharmacy`, `dentalPractice`, `optician`, `nhsTrust`, `nhsTrustSite`, `integratedCareBoard`, `primaryCareNetwork`, `careHome`, `socialCareProvider`, `independentProvider`, `prescribingCostCentre`, `localAuthority`, `hospice`. |
| `odsCodes` | array of strings | `[]` | Exact ODS codes, e.g. `["RJ1", "A81001"]`. Takes priority over postcodes and type. Up to 200 per run — but never more than `maxResults`, so raise that too. Codes that return nothing are listed in one free row. |
| `includeInactive` | boolean | `false` | `true` also returns closed organisations (old CCGs, closed practices). |
| `roleId` | string | `""` | Advanced: any of the ~205 ODS role codes (`RO227` Scottish GP practice, `RO142` local health board, `RO175` prison…). Overrides `organisationType`. Full list: https://directory.spineservices.nhs.uk/ORD/2-0-0/roles |
| `maxResults` | integer | `50` | Maximum organisation rows (1–500). Each returned row is charged. |

#### Organisation types and their ODS role codes

| `organisationType` | Role code | ODS role |
|---|---|---|
| `gpPractice` | `RO76` | GP practice (the record's primary role is usually `RO177` prescribing cost centre) |
| `branchSurgery` | `RO96` | Branch surgery |
| `pharmacy` | `RO182` | Pharmacy |
| `dentalPractice` | `RO110` | General dental practice |
| `optician` | `RO167` | Optical site |
| `nhsTrust` | `RO197` | NHS trust (including foundation trusts) |
| `nhsTrustSite` | `RO198` | NHS trust site — hospitals, clinics, community teams |
| `integratedCareBoard` | `RO318` | Integrated care board (ICB) |
| `primaryCareNetwork` | `RO272` | Primary care network (PCN) |
| `careHome` | `RO269` | Care home |
| `socialCareProvider` | `RO104` | Social care provider |
| `independentProvider` | `RO172` | Independent sector healthcare provider |
| `prescribingCostCentre` | `RO177` | Prescribing cost centre |
| `localAuthority` | `RO141` | Local authority |
| `hospice` | `RO7` | Hospice |

ODS codes themselves follow a pattern: English GP practices are a letter plus five characters (`A81001`), NHS trusts are three characters (`RJ1`), pharmacies start with `F`, dental practices with `V`, PCNs with `U`, and a site adds three digits to its parent's code (`A82016004`).

#### Input example

Every pharmacy in the Leeds LS1 and LS2 postcode areas:

```json
{
  "postcodes": ["LS1", "LS2"],
  "organisationType": "pharmacy",
  "maxResults": 100
}
```

### Output

One row per organisation (`status: "ok"`), sorted by postcode. If nothing matches, one free row with `status: "not_found"` and an `error` sentence saying what to change; invalid input gives one free `status: "error"` row. When you search by `odsCodes` and some of the codes return nothing — no such organisation, closed, withheld as a personal name, or past `maxResults` — one extra free `not_found` row lists exactly which codes they were.

Real row from a run on 23 September 2026 (`{"odsCodes": ["A81001"]}`):

```json
{
  "status": "ok",
  "odsCode": "A81001",
  "organisationName": "THE DENSHAM SURGERY",
  "isActive": true,
  "organisationStatus": "Active",
  "recordType": "organisation",
  "primaryRoleId": "RO177",
  "primaryRoleName": "PRESCRIBING COST CENTRE",
  "roleIds": "RO177, RO76",
  "roleNames": "PRESCRIBING COST CENTRE, GP PRACTICE",
  "postcode": "TS18 1HU",
  "postcodeArea": "TS",
  "town": "Stockton-On-Tees",
  "county": null,
  "country": "England",
  "phone": "01642 672351",
  "website": null,
  "operationalStartDate": "1974-04-01",
  "operationalEndDate": null,
  "legalStartDate": null,
  "legalEndDate": null,
  "lastChangeDate": "2023-08-22",
  "commissionedByOdsCode": "16C",
  "operatedByOdsCode": null,
  "partOfOdsCode": null,
  "odsRecordUrl": "https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/A81001",
  "fetchedAt": "2026-09-23T08:41:07Z",
  "attribution": "NHS England Organisation Data Service (ODS), retrieved from the ORD API. Contains public sector information licensed under the Open Government Licence v3.0. Not affiliated with, or endorsed by, NHS England or NHS Digital. Organisations only; records whose name identifies a private individual are excluded by this Actor."
}
```

When nothing matches (free row):

```json
{
  "status": "not_found",
  "fetchedAt": "2026-09-23T08:44:10Z",
  "error": "No organisation in the NHS ODS register has the code(s) \"ZZZZZZ\". Check the code, or search by \"postcodes\" instead."
}
```

#### Output fields

| Field | Description |
|---|---|
| `status` | `ok`, `not_found` or `error`. |
| `odsCode` | ODS organisation code — the key used by almost every NHS dataset. |
| `organisationName` | Organisation name as recorded in ODS (organisations only, see Privacy). |
| `isActive` / `organisationStatus` | `true` / `false`, and the ODS wording (`Active` or `Inactive`). |
| `recordType` | `organisation` (ODS record class RC1) or `site` (RC2 — a location belonging to an organisation). |
| `primaryRoleId` / `primaryRoleName` | The organisation's main ODS role, e.g. `RO177` / `PRESCRIBING COST CENTRE`. |
| `roleIds` / `roleNames` | Every role the organisation holds, comma-separated. A GP practice typically holds both `RO177` and `RO76`. |
| `postcode` / `postcodeArea` | Postcode of the organisation's address, and its area (`TS`, `LS`, `SW`). |
| `town` / `county` / `country` | Town, county and country (`England`, `Wales`, `Scotland`, `Northern Ireland`, `Isle Of Man`). Street lines are not output (see Privacy). |
| `phone` | The organisation's switchboard number, as recorded in ODS. Mobile numbers are never output. |
| `website` | The organisation's website, when ODS holds one (mostly trusts and larger bodies). |
| `operationalStartDate` / `operationalEndDate` | When the organisation started / stopped operating (`YYYY-MM-DD`). |
| `legalStartDate` / `legalEndDate` | Legal start and end dates, when ODS records them separately. |
| `lastChangeDate` | When this record was last changed in ODS. |
| `commissionedByOdsCode` | ODS code of the body that commissions this organisation (usually its ICB / sub-ICB location). |
| `operatedByOdsCode` | ODS code of the body that operates it (for example a pharmacy's head office). |
| `partOfOdsCode` | ODS code this record is a sub-division of. |
| `odsRecordUrl` | The organisation's record in the official ORD API. |
| `fetchedAt` / `attribution` | Run time (UTC) and the Open Government Licence attribution. |
| `error` | On `not_found` / `error` rows: one English sentence explaining what to change. |

### How much does it cost?

This Actor uses **Pay per event** pricing — you pay for organisation rows, not for compute time:

| Event | Price | When it is charged |
|---|---|---|
| Organisation row (`result-row`) | **$0.005** ($5 per 1,000 rows) | Each `ok` row (one organisation) |
| Actor start | **$0.001** | Once per run |

`not_found` and `error` rows are **free**; the $0.001 start fee is charged once per run, even when nothing is found.

| Example | Rows | Cost |
|---|---|---|
| **One organisation by ODS code** (`{"odsCodes": ["RJ1"]}`) | 1 | **$0.006** |
| A run that finds nothing (free rows, start fee only) | 0 | **$0.001** |
| Default run (GP practices searched as postcode `LS1` — 27 rows) | 27 | about $0.14 |
| Every pharmacy in two postcode areas | ~40 | about $0.20 |
| A lead list of 500 GP practices | 500 | about $2.50 |

- **Cheapest way to start:** one ODS code, `{"odsCodes": ["RJ1"]}` — one row, well under a cent.
- For comparison, commercial UK healthcare contact lists sell at **£325–£425 per 1,000 records** and a licensed GP-practice database costs about **£1,250 a year** for roughly 6,400 practices.
- Set a **maximum cost per run** when you start the Actor to cap spending; if the limit is reached, the Actor stops cleanly and says so in the status message.

### Use via API / MCP (AI agents)

**Apify API (HTTP).** Run the Actor and get the rows in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/japan-open-data~uk-nhs-organisation-lookup/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"postcodes": ["LS1", "LS2"], "organisationType": "pharmacy", "maxResults": 20}'
```

**Python (apify-client):**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("japan-open-data/uk-nhs-organisation-lookup").call(run_input={
    "postcodes": ["TS18"], "organisationType": "gpPractice", "maxResults": 50,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["status"], row.get("odsCode"), row.get("organisationName"), row.get("postcode"))
```

**MCP (Claude, ChatGPT, Cursor and other AI agents).** Add this Actor as a tool through the Apify MCP server (https://mcp.apify.com), for example with `?tools=japan-open-data/uk-nhs-organisation-lookup`. No input is required.

Recommended agent settings:

- "What is the ODS code for X?" → `{"postcodes": ["<postcode>"], "maxResults": 10}` and match on `organisationName`.
- "Tell me about ODS code X" → `{"odsCodes": ["<code>"]}` — one row, one request.
- "GP practices / pharmacies near postcode Y" → `{"postcodes": ["<outward part>"], "organisationType": "gpPractice", "maxResults": 20}`.
- Keep `maxResults` small (5–50) for questions; raise it only for list exports.
- Always read `status` first; on `not_found` the `error` sentence tells you what to change. An organisation that ODS names after a person is always missing on purpose (see FAQ).
- A postcode is a **prefix**: `LS1` also returns LS10–LS19. If the user asked about one district, filter the rows on `postcode` yourself, or pass a four-character outward code (`TS18`) or a full postcode.
- When you pass `odsCodes`, set `maxResults` to at least the number of codes, and read the free `not_found` row that names any codes that returned nothing.

**Summary for AI agents:** Input: `postcodes` (array, default `["LS1"]`, matched as a prefix so `LS1` also covers LS10–LS19), `organisationType` (enum, default `gpPractice`; use `any` for every kind), `odsCodes` (array), `includeInactive` (boolean, default `false`), `roleId` (string), `maxResults` (integer, default 50, also the cap on how many `odsCodes` are looked up). Output: flat rows, one per UK NHS organisation in the official ODS register, with `status`, `odsCode`, `organisationName`, `isActive`, role codes and names, `postcode`, `town`, `county`, `country`, `phone`, `website`, dates and the commissioner's ODS code. Active organisations only unless `includeInactive` is true. No personal names, no street addresses. $0.005 per `ok` row + $0.001 per run; `not_found` / `error` rows are free.

### Privacy: why some organisations are missing

ODS is a register of organisations, but it records many of them under the name of the person who runs them. Two independent reviews of active ODS records on 23 September 2026 — 62,420 records and then 66,425 — found four shapes:

- a title in front of a surname — `DR KHAN & PARTNERS`, `MRS VELDA REILLY`, `MR M SALEEM`;
- a bare personal name — `PHILIP DAY`, `COLES LESLEY`, `D L YADAVE`, `ALEC MING`;
- initials and a surname, with or without a company suffix — `A.R.BAKER OPTICIANS`, `B.J.TOYE OPTOMETRISTS`, `J BROWN LTD`;
- a personal name followed by a profession — `SIMPSON SALLY (PHYSIOTHERAPIST)`, `PRING D W (OBSTETRICS & GYNAECOLOGY)`.

This Actor never returns those rows. **12% of active ODS records are withheld this way** (8,076 of 66,425 in the second review): 4% of English GP practices and pharmacies, 21% of optical sites, 17% of social care providers, 41% of non-NHS organisations, and **98% of Northern Irish GP practices** (almost all of which ODS names `DR <SURNAME> & PARTNERS`) — but none at all of the NHS trusts, integrated care boards or primary care networks in the sample. A few genuine organisations are withheld with them: a plain personal trading name (`MARIA MALLABAND CARE HOMES`), or a company whose name is an initialism (`DATABRICKS U.K. LIMITED`, `M&S OPTICIANS`). That trade is deliberate — the Open Government Licence that covers ODS explicitly does not cover personal data, so anything that reads like a person is withheld.

In addition: the free-text street address lines are dropped (only town, county, postcode and country are returned), mobile numbers are never output, and the separate ODS files about individual GPs, nurses and pharmacists are never read.

### FAQ

#### Why can't I find a GP practice I know?

Either it is registered under a doctor's name and is withheld on purpose (see Privacy), or you are searching with a postcode that is not the practice's registered one. Try a shorter postcode (`LS1` instead of `LS1 4AP`), or search with `organisationType: "gpPractice"` and no postcode filter and look for the name.

#### How fresh is the data?

The Actor reads the ORD API live on every run, and NHS England updates ODS every working day. The register's own change feed listed 114 records changed in the 24 hours to 23 September 2026. Newly opened organisations usually appear within a few working days of being registered.

#### Does it cover Scotland, Wales and Northern Ireland?

Yes — ODS covers the whole UK, plus the Isle of Man and the Channel Islands. Scottish GP practices use role `RO227`, Northern Irish GP practices `RO315`, and Welsh local health boards `RO142`. Use the advanced `roleId` input for those.

One warning: Scotland and Northern Ireland register most GP practices under the partners' names (`DR MCCUTCHEON & PARTNERS`), so the privacy gate withholds 12% of Scottish and **98% of Northern Irish** GP practice records. Hospitals, health boards, trusts, pharmacies and dental practices in those countries are unaffected. If you need every Northern Irish practice, this is not the right tool.

#### Why did I get organisations in LS12 when I searched LS1?

Because the NHS register matches a postcode as a prefix, and this Actor passes your postcode through unchanged. `LS1` matches LS1, LS10, LS11 … LS19; `M1` matches M1 and M10–M19. Four-character outward codes such as `TS18` or `SW1A` have no longer neighbours, so they match one district only. The status message of every run lists the districts the rows actually came from, and each row carries its own `postcode` so you can filter.

#### What is the difference between `RO76` and `RO177`?

`RO177` (prescribing cost centre) is the primary role on an English GP practice record and the code prescribing data is keyed on. `RO76` (GP practice) is the non-primary role that marks it as a GP practice. Choosing `gpPractice` uses `RO76`, which is the more reliable filter; both codes appear in `roleIds`.

#### Can I get patient numbers, CQC ratings or opening hours?

No — ODS holds none of those. It is the organisation code register. Join the `odsCode` to NHS Digital's practice-level datasets, OpenPrescribing or the CQC API for those.

#### Is this an official NHS service?

No. This Actor is not affiliated with, or endorsed by, NHS England or NHS Digital. It reads their public ORD API and re-publishes the data under the Open Government Licence.

### Troubleshooting

| What you see | Why | What to do |
|---|---|---|
| Rows from postcode districts you did not ask for (LS12 when you asked for LS1) | ODS matches a postcode as a **prefix** | Filter the rows on `postcode`, or pass a four-character outward code (`TS18`) or a full postcode (`TS18 1HU`) |
| Fewer rows than `maxResults` | That is all ODS holds for your filter, or the rest were withheld as personal names | Widen the postcode, try `organisationType: "any"`, or set `includeInactive: true` |
| A practice or shop you know is missing | ODS records it under a person's name (`DR KHAN & PARTNERS`, `A.R.BAKER OPTICIANS`), or its name is an initialism | This is deliberate — see Known limitations. Search by `odsCodes` and read the free `not_found` row, which says why |
| One free `not_found` row instead of rows | Nothing matched | Read the `error` sentence on that row; it names the exact input to change. You are not charged for it |
| `status: "error"`, "Supplied PostCode format is invalid" | ODS rejected the postcode | Use the outward part only (`LS1`) or a full postcode **with the space** (`TS18 1HU`) — `TS181HU` returns nothing |
| Only some of your `odsCodes` came back | Codes can be unknown, closed, withheld or past `maxResults` | Read the extra free `not_found` row: it lists exactly which codes returned nothing. Raise `maxResults` to at least the number of codes |
| Closed organisations in the results | `includeInactive` is `true` | Set it back to `false` (the default) for open organisations only |
| Northern Irish GP practices almost all missing | 98% of them are registered under the partners' names | Expected — see Known limitations. Hospitals, trusts, pharmacies and dental practices in Northern Ireland are unaffected |
| The run stopped early with "charge limit" in the status message | Your maximum cost per run was reached | Raise the limit, or lower `maxResults` |

### Known limitations

- **About 12% of active ODS records are withheld** because their name identifies a person (8,076 of 66,425 records checked on 23 September 2026). By type: NHS trusts, integrated care boards and primary care networks **0%**; English GP practices, pharmacies and dental practices **4–5%**; NHS trust sites and Scottish GP practices **12%**; social care providers **17%**; **optical sites 21%**; **non-NHS organisations 41%**; **Northern Irish GP practices 98%**. If you need a complete list of one of the last three, this is not the right tool.
- **A few genuine organisations are withheld with them** — roughly 40 in 66,425 — because their registered name is an initialism that cannot be told apart from a person's initials (`DATABRICKS U.K. LIMITED`, `M&S OPTICIANS`, `I.D.H. LTD`). Look those up by `odsCodes` and you get a free `not_found` row explaining why.
- **Postcodes match as a prefix.** `LS1` returns LS1 and LS10–LS19. Four-character outward codes (`TS18`, `SW1A`) match a single district. Two-character inputs (`LS`) are rejected by ODS.
- **No street addresses, no mobile numbers, no personal names** — by design. Only town, county, postcode, country and the organisation's switchboard number.
- **ODS is a code register, not a directory of services.** No patient list sizes, CQC ratings, opening hours, staff, services or geographic coordinates. Join `odsCode` to NHSBSA, OpenPrescribing or the CQC API for those.
- **`maxResults` caps the run at 500 rows**, and it is also the cap on how many `odsCodes` are resolved. The Actor does not yet report how many records matched in total beyond what it returned.
- **Related organisations are returned as codes, not names** (`commissionedByOdsCode`, `operatedByOdsCode`, `partOfOdsCode`). Feed those codes back in through `odsCodes` to get the names.
- **Website and county are often empty** — ODS holds a website mostly for trusts and larger bodies.
- **No incremental / changes-only mode yet.** Every run reads the register live. To find changes, compare two runs on `odsCode`.

### Data source and licence

- **Source:** NHS England Organisation Data Service (ODS), read through the ORD API — `https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations`. API documentation: https://directory.spineservices.nhs.uk/apidocs/ . Listed in the UK government API catalogue: https://www.api.gov.uk/nd/organisation-data-service-ord-api/
- **Licence:** the ODS datasets are published on data.gov.uk under the **Open Government Licence v3.0** (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/), which allows commercial re-use and adaptation.
- **Attribution:** *Contains public sector information licensed under the Open Government Licence v3.0.* This attribution is also on every row, in the `attribution` field, together with the `fetchedAt` timestamp.
- **Not affiliated** with NHS England, NHS Digital or the Department of Health and Social Care.
- Licence and API behaviour checked on **23 September 2026**.

### More from Japan Open Data

- [UK Visa Sponsor Register Tracker (Daily Changes)](https://apify.com/japan-open-data/uk-visa-sponsor-register) — new, removed and downgraded UK visa sponsor licences from the official Home Office register, or check whether a company can sponsor workers.
- [US Flood Zone Lookup by Address (FEMA NFHL)](https://apify.com/japan-open-data/us-flood-zone-lookup) — official FEMA flood zone (A, AE, VE, X…), base flood elevation and FIRM panel for any U.S. address or coordinates.
- [UK Flood Risk Lookup by Postcode (England)](https://apify.com/japan-open-data/uk-flood-zone-lookup) — Environment Agency flood zone, recorded flood extents and flood defences for any postcode or coordinates in England.
- [England Listed Building & Conservation Area Check](https://apify.com/japan-open-data/england-heritage-constraint-lookup) — official listed buildings, scheduled monuments, conservation areas and Article 4 directions for any postcode or coordinates in England, one row per location.
- [France Property Risk Lookup by Address (Georisques)](https://apify.com/japan-open-data/france-property-risk-lookup) — official Géorisques risks for any French address or coordinates: flood, clay shrink-swell, seismic zone, radon, past natural-disaster declarations and nearby industrial sites.
- [UK Waste Carrier Licence Check (Environment Agency)](https://apify.com/japan-open-data/uk-waste-carrier-register) — check whether an English business is a registered waste carrier, broker or dealer.
- [UK HGV Operator Licence Lookup (Official DVSA)](https://apify.com/japan-open-data/uk-hgv-operator-licence) — Great Britain's official HGV and bus / coach operator licences by company, postcode and fleet size.
- [US Hail History by Location (NOAA NEXRAD Radar)](https://apify.com/japan-open-data/us-hail-history) — every hail day near any U.S. latitude/longitude with max estimated hail size.
- [US Storm Reports API: Hail, Wind & Tornado (NWS)](https://apify.com/japan-open-data/us-storm-reports-live) — U.S. hail, wind, tornado and flood reports from official NWS Local Storm Reports.
- [Mexico Gas Prices API by Station (Official CNE)](https://apify.com/japan-open-data/mexico-fuel-station-prices) — today's gas and diesel prices at every Mexican gas station, from the official CNE feed.
- [Argentina Fuel Prices API by Station (Official)](https://apify.com/japan-open-data/argentina-fuel-station-prices) — last reported gasoline (nafta), diesel and CNG prices at every Argentine gas station.
- [TSA Checkpoint Travel Numbers (Daily, Weekly & YoY)](https://apify.com/japan-open-data/tsa-checkpoint-throughput) — daily U.S. TSA airport checkpoint traveler counts.
- [Japan Postal Code & Address in English](https://apify.com/japan-open-data/japan-postal-code-english) — Japanese postal codes and addresses in English/romaji, kanji and kana.

### Feedback

Found a wrong row, a missing organisation type, or want a field ODS holds that this Actor does not return? Open an issue on the **Issues** tab of this Actor and it will be read. Requests already on the list: name search (`nameContains`), a total-matches count, and a changes-only mode built on the ODS change feed.

# Actor input Schema

## `postcodes` (type: `array`):

UK postcodes to search. The NHS register matches a postcode as a PREFIX, so "LS1" returns organisations in LS1 and in LS10-LS19, and "M1" also covers M10-M19; four-character codes such as "TS18" or "SW1A" match one district only, and a full postcode ("TS18 1HU") matches one address. Up to 20 per run, and "maxResults" is split evenly between them. Leave empty to search the whole UK by organisation type instead.

## `organisationType` (type: `string`):

Which kind of NHS organisation to return. "Any organisation" returns every kind, including NHS suppliers and administrative records. Each choice maps to an official ODS role code, shown in brackets.

## `odsCodes` (type: `array`):

Look up specific organisations by their ODS code, for example \["RJ1", "A81001", "FA002"]. Takes priority over the postcodes and the organisation type. Up to 200 per run, but never more than "maxResults", so raise that as well. Any code that returns no row is listed in one extra free row.

## `includeInactive` (type: `boolean`):

Off by default, so only organisations that are currently open are returned. Turn it on to include closed ones, such as the CCGs replaced by integrated care boards in 2022.

## `roleId` (type: `string`):

Any of the ~205 official ODS role codes, for example "RO227" (Scottish GP practice), "RO142" (local health board) or "RO175" (prison). Overrides "Organisation type". The full list is at https://directory.spineservices.nhs.uk/ORD/2-0-0/roles . Leave empty to ignore.

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

Maximum number of organisation rows to return (1 to 500). Each returned row is charged.

## Actor input object example

```json
{
  "postcodes": [
    "LS1"
  ],
  "organisationType": "gpPractice",
  "odsCodes": [],
  "includeInactive": false,
  "roleId": "",
  "maxResults": 50
}
```

# Actor output Schema

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

ODS code, organisation name, open or closed, role codes and names, postcode, town, county, country, switchboard number, website, start and end dates, commissioner and operator ODS codes, per organisation. Table view: overview.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("japan-open-data/uk-nhs-organisation-lookup").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("japan-open-data/uk-nhs-organisation-lookup").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 '{}' |
apify call japan-open-data/uk-nhs-organisation-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,japan-open-data/uk-nhs-organisation-lookup"
        }
    }
}
```

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/3wSblmOWc5OYKHBea/builds/d2GqMFBxhVYrariV9/openapi.json
