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.
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 'https://data.gov.sg/api/action/datastore_search?resource_id=d_8b84c4ee58e3cfc0ece0d773c8ca6abc&limit=1'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);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()){
"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
| Parameter | Type | Required | Description |
|---|---|---|---|
resource_id | query | Required | The dataset resource identifier, a `d_`-prefixed hash from the portal page. d_8b84c4ee58e3cfc0ece0d773c8ca6abc |
limit | query | Optional | Rows to return. Defaults to 100. 1 |
offset | query | Optional | Pagination offset. 1000 |
q | query | Optional | Free-text search across all columns, or a JSON object for per-column search. ANG MO KIO |
filters | query | Optional | JSON object of exact-match column filters. {"town":"BEDOK"} |
sort | query | Optional | Column and direction. Remember most columns are text, so sorting is lexical. resale_price desc |
fields | query | Optional | Comma-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
CSV to JSON Converter
Convert CSV to a JSON array of objects online. Header-row detection, comma/semicolon/tab delimiters and pretty-printed output — 100% in your browser.
JSON to CSV Converter
Convert a JSON array of objects to CSV online. Automatic column headers from the union of all keys, delimiter choice and proper quoting — all in-browser.
SQL Formatter
Format SQL online: uppercase keywords, new lines before SELECT, FROM, WHERE and JOIN, indented AND/OR conditions. One-line minify included. Free and private.
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.