BYTETOOLS

data.gov.sg Datastore API

Free Singapore government data API with no key: query any published dataset row by row through the CKAN datastore, with column types returned alongside the records. Tested example.

No API key requiredCORS enabledHTTPSFree tier

Endpoint tested and returned HTTP 200 on 2026-08-21

What is the data.gov.sg Datastore API?

data.gov.sg exposes every published dataset through a CKAN datastore API that needs no key. Passing a `resource_id` returns actual rows plus a `fields` array giving each column's name and SQL type, so you can query millions of records — such as the full HDB resale price history — without downloading a CSV.

The HDB resale transactions dataset is the one everybody ends up using: every public housing flat sold in Singapore, with town, block, street, storey range, floor area, lease details and price. It is large, it is updated regularly, and the datastore lets you filter and page it server-side instead of pulling the whole file. The `fields` array that comes back with every response is the useful part — it tells you the column is `text` rather than `numeric` before you try to sort on it.

That typing detail matters more here than usual, because most columns are `text` even when they look numeric. `floor_area_sqm` is a string, `storey_range` is a string like `"10 TO 12"`, and only `resale_price` is genuinely `numeric`. Sorting by `floor_area_sqm` therefore sorts lexically — 100 sorts before 44. Cast in your own code, or use the `sql` parameter, which accepts a read-only SELECT against the resource and lets the database do the casting for you.

Quick facts

Base URL
https://data.gov.sg/api/action
Authentication
No API key for reads. The datastore is read-only over HTTP; there is no public write path.
Rate limit
No published limit. Requesting large `limit` values on multi-million-row resources is slow — page instead.
Pricing
Free under the Singapore Open Data Licence, which permits commercial reuse with attribution.
CORS
Enabled — callable directly from browser JavaScript
Official docs
Read the docs

How to use the data.gov.sg Datastore API

Every request below was executed against the live API on 2026-08-21, and the response shown is the real body it returned — not an illustration.

1. Query Singapore HDB resale transactions

GET https://data.gov.sg/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1

curl
curl 'https://data.gov.sg/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1'
JavaScript (fetch)
const res = await fetch("https://data.gov.sg/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);
Python (requests)
import requests

res = requests.get("https://data.gov.sg/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1", timeout=20)
res.raise_for_status()
print(res.json())
Response — HTTP 200 (truncated)
{
  "success": true,
  "result": {
    "resource_id": "d_8b84c4ee58e3cfc0ece0d773c8ca6abc",
    "fields": [
      {
        "type": "text",
        "id": "month"
      },
      {
        "type": "text",
        "id": "town"
      },
      {
        "type": "text",
        "id": "flat_type"
      },
      {
        "type": "text",
        "id": "block"
      },
      {
        "type": "text",
        "id": "street_name"
      },
      {
        "type": "text",
        "id": "storey_range"
      },
      {
        "type": "text",
        "id": "floor_area_sqm"
      },
      {
        "type": "text",
        "id": "flat_model"
      },
      {
        "type": "text",
        "id": "lease_commence_date"
      },
      {
        "type": "text",
        "id": "remaining_lease"
      },
      {
        "type": "numeric",
        "id": "resale_price"
      },
      {
        "type": "int4",
        "id": "_id"
      }
    ],
    "records": [
      {
        "_id": 1,
        "month": "2017-01",
        "town": "ANG MO KIO",
        "flat_type": "2 ROOM",
        "block": "406",
        "street_name": "ANG MO KIO AVE 10",
        "storey_range": "10 TO 12",
        "floor_area_sqm": "44",
        "flat_model": "Improved",
        "lease_commence_date": "1979",
        "remaining_lease": "61 years 04 months",
        "resale_price": "232000"
      }
    ],
    "_links": {
      "start": "/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1",
      "next": "/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&offset=1&limit=1"

Parameters

ParameterTypeRequiredDescription
resource_idqueryRequiredThe dataset resource identifier, a `d_`-prefixed hash from the portal page. d_8b84c4ee58e3cfc0ece0d773c8ca6abc
limitqueryOptionalRows to return. Defaults to 100. 1
offsetqueryOptionalPagination offset. 1000
qqueryOptionalFree-text search across all columns, or a JSON object for per-column search. ANG MO KIO
filtersqueryOptionalJSON object of exact-match column filters. {"town":"BEDOK"}
sortqueryOptionalColumn and direction. Remember most columns are text, so sorting is lexical. resale_price desc
fieldsqueryOptionalComma-separated columns to return, which shrinks responses substantially. month,town,resale_price

Response fields

successboolean
CKAN's success flag. Check it — the datastore returns HTTP 200 on rejected queries.
result.resource_idstring
Echo of the resource queried.
result.fieldsarray
Column definitions with `id` and SQL `type`. Read this before sorting or comparing.
result.fields[].typestring
`text`, `numeric` or `int4`. Most columns are `text` even when they hold numbers.
result.recordsarray
The rows, each including an auto-incrementing `_id`.
result.records[]._idinteger
Datastore row number. Stable within a load, but it changes when the resource is republished.
result.totalinteger
Total rows matching the query, for pagination.

What you can build with the data.gov.sg Datastore API

  • Analyse Singapore HDB resale prices by town, flat type or period
  • Build a property price trend chart without hosting the dataset
  • Filter a large government dataset server-side before charting
  • Run read-only SQL aggregates against a published resource
  • Feed a housing affordability calculator with live transaction data

Common errors and how to fix them

HTTP 200 with success false

The datastore rejected the query.

Fix: Read `error.message`. An unknown `resource_id` or malformed `filters` JSON are the usual causes.

Numeric sort ordering looks wrong

The column is typed `text`.

Fix: Check `fields[].type` first, then cast with the `sql` parameter or sort client-side after conversion.

Very slow response

A large `limit` against a multi-million-row resource.

Fix: Page with `limit` and `offset`, and use `fields` to return only the columns you need.

_id values changed between runs

The resource was reloaded.

Fix: Never persist `_id` as a foreign key; build your own key from the business columns.

data.gov.sg Datastore API — frequently asked questions

Does data.gov.sg require an API key?

No. Datastore reads are open and unauthenticated. Only Singapore government agencies publishing data need credentials, and that is a separate system.

Where do I find a resource_id?

On the dataset's page on data.gov.sg — it is the `d_`-prefixed hash in the URL and in the API examples the portal shows. Each resource within a dataset has its own.

Can I run SQL against a dataset?

Yes. `datastore_search_sql` accepts a read-only SELECT against a single resource, which is the cleanest way to aggregate or cast text columns to numbers before sorting.

Why is floor_area_sqm a string?

The datastore inferred types on load and kept most columns as text. Only `resale_price` came through as numeric, so cast anything else yourself before doing arithmetic or ordering.

Tools that pair with this API

data.gov.sg Datastore is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-21; always check the official documentation before relying on this API in production, as terms and limits can change.