UK NHS Organisation Lookup (Official ODS Codes) avatar

UK NHS Organisation Lookup (Official ODS Codes)

Pricing

from $5.00 / 1,000 organisation rows

Go to Apify Store
UK NHS Organisation Lookup (Official ODS Codes)

UK NHS Organisation Lookup (Official ODS Codes)

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.

Pricing

from $5.00 / 1,000 organisation rows

Rating

0.0

(0)

Developer

Japan Open Data

Japan Open Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 hours ago

Last modified

Categories

Share

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 listsThis Actor
PriceFree£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 itDownload a CSV by hand, or write your own client for the ORD APIEmailed CSV / Excel under a 12-month licenceJSON, CSV or Excel; API, MCP or a scheduled run
Personal dataODS records named after a person are includedNamed practice managers, direct dials, personal emailsNever — organisations only, no street lines, no mobile numbers
Closed organisationsMixed in with the open onesDepends on the vendor's refresh cycleExcluded by default (Active only)
FreshnessLiveRe-verified every 30 days or on a licence renewalLive — the ORD API is read on every run
Detail per rowPaged web tables, one role code at a timeContact details, no ODS relationships28 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.

InputTypeDefaultWhat it does
postcodesarray 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.
organisationTypestringgpPracticeany, gpPractice, branchSurgery, pharmacy, dentalPractice, optician, nhsTrust, nhsTrustSite, integratedCareBoard, primaryCareNetwork, careHome, socialCareProvider, independentProvider, prescribingCostCentre, localAuthority, hospice.
odsCodesarray 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.
includeInactivebooleanfalsetrue also returns closed organisations (old CCGs, closed practices).
roleIdstring""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
maxResultsinteger50Maximum organisation rows (1–500). Each returned row is charged.

Organisation types and their ODS role codes

organisationTypeRole codeODS role
gpPracticeRO76GP practice (the record's primary role is usually RO177 prescribing cost centre)
branchSurgeryRO96Branch surgery
pharmacyRO182Pharmacy
dentalPracticeRO110General dental practice
opticianRO167Optical site
nhsTrustRO197NHS trust (including foundation trusts)
nhsTrustSiteRO198NHS trust site — hospitals, clinics, community teams
integratedCareBoardRO318Integrated care board (ICB)
primaryCareNetworkRO272Primary care network (PCN)
careHomeRO269Care home
socialCareProviderRO104Social care provider
independentProviderRO172Independent sector healthcare provider
prescribingCostCentreRO177Prescribing cost centre
localAuthorityRO141Local authority
hospiceRO7Hospice

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:

{
"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"]}):

{
"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):

{
"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

FieldDescription
statusok, not_found or error.
odsCodeODS organisation code — the key used by almost every NHS dataset.
organisationNameOrganisation name as recorded in ODS (organisations only, see Privacy).
isActive / organisationStatustrue / false, and the ODS wording (Active or Inactive).
recordTypeorganisation (ODS record class RC1) or site (RC2 — a location belonging to an organisation).
primaryRoleId / primaryRoleNameThe organisation's main ODS role, e.g. RO177 / PRESCRIBING COST CENTRE.
roleIds / roleNamesEvery role the organisation holds, comma-separated. A GP practice typically holds both RO177 and RO76.
postcode / postcodeAreaPostcode of the organisation's address, and its area (TS, LS, SW).
town / county / countryTown, county and country (England, Wales, Scotland, Northern Ireland, Isle Of Man). Street lines are not output (see Privacy).
phoneThe organisation's switchboard number, as recorded in ODS. Mobile numbers are never output.
websiteThe organisation's website, when ODS holds one (mostly trusts and larger bodies).
operationalStartDate / operationalEndDateWhen the organisation started / stopped operating (YYYY-MM-DD).
legalStartDate / legalEndDateLegal start and end dates, when ODS records them separately.
lastChangeDateWhen this record was last changed in ODS.
commissionedByOdsCodeODS code of the body that commissions this organisation (usually its ICB / sub-ICB location).
operatedByOdsCodeODS code of the body that operates it (for example a pharmacy's head office).
partOfOdsCodeODS code this record is a sub-division of.
odsRecordUrlThe organisation's record in the official ORD API.
fetchedAt / attributionRun time (UTC) and the Open Government Licence attribution.
errorOn 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:

EventPriceWhen it is charged
Organisation row (result-row)$0.005 ($5 per 1,000 rows)Each ok row (one organisation)
Actor start$0.001Once per run

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

ExampleRowsCost
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)27about $0.14
Every pharmacy in two postcode areas~40about $0.20
A lead list of 500 GP practices500about $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:

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):

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 seeWhyWhat to do
Rows from postcode districts you did not ask for (LS12 when you asked for LS1)ODS matches a postcode as a prefixFilter the rows on postcode, or pass a four-character outward code (TS18) or a full postcode (TS18 1HU)
Fewer rows than maxResultsThat is all ODS holds for your filter, or the rest were withheld as personal namesWiden the postcode, try organisationType: "any", or set includeInactive: true
A practice or shop you know is missingODS records it under a person's name (DR KHAN & PARTNERS, A.R.BAKER OPTICIANS), or its name is an initialismThis 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 rowsNothing matchedRead 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 postcodeUse the outward part only (LS1) or a full postcode with the space (TS18 1HU) — TS181HU returns nothing
Only some of your odsCodes came backCodes can be unknown, closed, withheld or past maxResultsRead 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 resultsincludeInactive is trueSet it back to false (the default) for open organisations only
Northern Irish GP practices almost all missing98% of them are registered under the partners' namesExpected — see Known limitations. Hospitals, trusts, pharmacies and dental practices in Northern Ireland are unaffected
The run stopped early with "charge limit" in the status messageYour maximum cost per run was reachedRaise 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

More from Japan Open Data

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.