Health — entry 020 of 23

Open Data NHS Scotland

Verified Jul 2026

Public Health Scotland's open-data portal is a keyless CKAN instance covering GP practices, prescribing, hospital admissions, and population health statistics for Scotland, queryable via the standard CKAN Action API (datastore_search, datastore_search_sql) with no registration. A live GET against the site's api/3/action endpoints succeeds without a key. A live Origin-header probe (both a plain GET and an OPTIONS preflight) against the same host returns no Access-Control-Allow-Origin header, so the stored 'unknown' cors resolved to 'no'.

Public Health Scotland's open-data portal is a keyless CKAN instance covering GP practices, prescribing, hospital admissions, and population health statistics for Scotland, queryable via the standard CKAN Action API (package_show, datastore_search, datastore_search_sql) with no registration. A live GET against datastore_search this run succeeded without a key and returned a real GP-practice record; both a plain GET and an OPTIONS preflight with an Origin header returned no access-control-allow-origin header at all, confirming the stored cors: no.

healthgovernmentscotlandopen-datastatistics
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSDisabledBrowser calls need a server-side proxy.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score88out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs14/20Documentation URL provided
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 88 on greatapis.com
<a href="https://greatapis.com/api/open-data-nhs-scotland/"><img src="https://greatapis.com/badge/open-data-nhs-scotland.svg" alt="Scored 88 on greatapis.com"></a>

Auth quickstart

  1. No API key required. Every action is a GET (or POST) against /api/3/action/<action_name> with query params — confirmed live this run against package_show and datastore_search.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

Query one record from a GP-practice datastore resource

GEThttps://www.opendata.nhs.scot/api/3/action/datastore_search?resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8&limit=1

200 application/json;charset=utf-8

{"help": "https://www.opendata.nhs.scot/api/3/action/help_show?name=datastore_search", "success": true, "result": {"include_total": true, "resource_id": "0032ce94-f7f6-44dd-879c-7d3074d8e2e8", "fields": [{"type": "int", "id": "_id"}, {"type": "numeric", "id": "PracticeCode"}, {"type": "text", "id": "GPPracticeName"}, {"type": "numeric", "id": "PracticeListSize"}, {"type": "text", "id": "AddressLine1"}, {"type": "text", "id": "AddressLine2"}, {"type": "text", "id": "AddressLine3"}, {"type": "text", "id": "AddressLine4"}, {"type": "text", "id": "Postcode"}, {"type": "text", "id": "TelephoneNumber"}, {"type": "text", "id": "PracticeType"}, {"type": "text", "id": "HB"}, {"type": "text", "id": "HSCP"}, {"type": "text", "id": "DataZone"}, {"type": "text", "id": "GPCluster"}], "records_format": "objects", "records": [{"_id":1,"PracticeCode":10002,"GPPracticeName":"Muirhead Medical Centre","PracticeListSize":8559,"AddressLine1":"Muirhead Medical Centre","AddressLine2":"Liff Road","AddressLine3":"Muirhead","AddressLine4":"","Postcode":"DD2 5NH","TelephoneNumber":"01382 580 264","PracticeType":"GMS","HB":"S08000030","HSCP":"S37000007","DataZone":"S01007129","GPCluster":"Dundee 4"}], "limit": 1, "_links": {"start": "/api/3/action/datastore_search?limit=1&resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8", "next": "/api/3/action/datastore_search?offset=1&limit=1&resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8"}, "total": 879}}

Developer reference

Base URLhttps://www.opendata.nhs.scot/api/3/action/
SDKs

Gotchas & limits

  • resource_id values are tied to a specific quarterly CSV upload, not a stable long-lived identifier for "the current GP practice list": the id pinned above (0032ce94-f7f6-44dd-879c-7d3074d8e2e8) is this run's July 2026 release — a live package_show?id=gp-practice-contact-details-and-list-sizes this run listed a fresh resource_id for every quarter back to 2018, so re-discover the current one via package_show before hardcoding it.
  • An invalid resource_id is a real HTTP 404 with a CKAN error envelope, not a 200: a live datastore_search?resource_id=00000000-0000-0000-0000-000000000000 this run returned {"success": false, "error": {"message": "Not found: Resource \"00000000-0000-0000-0000-000000000000\" was not found.", "__type": "Not Found Error"}} at status 404 — check both the HTTP status and success before reading result.
  • The SQL variant datastore_search_sql is enabled and equally keyless: a live SELECT * FROM "<resource_id>" LIMIT 1 against the same resource this run returned 200 with a success: true envelope and the matching row — useful for filters CKAN's own datastore_search query params can't express, but it accepts arbitrary read-only SQL, so treat it as a public read replica rather than a locked-down endpoint.
  • No CORS support at all, even for preflight: a live OPTIONS request with Origin and Access-Control-Request-Method headers this run returned HTTP 200 with Allow: HEAD, GET, POST, OPTIONS but no access-control-allow-origin or any other CORS response header — browser-side calls need a server-side proxy.