FairPrice API & Scraper
FairPrice is Singapore's largest supermarket chain and fairprice.com.sg its online shop.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
`search` returns the products for a search term with the price a shopper pays, the regular price when a price cut is running, the cut in S$ and percent with its end date, multi-buy deals such as "Any 2 for $6.80" as their own object (quantity, bundle price, price each, which products can be mixed), spend-and-save and free-gift promotions, the BCRS container deposit, pack size, a price per kg, litre or piece, stock level and online stock count, brand, barcodes, origin, dietary labels, Nutri-Grade, rating and review count. Filters are brand, one dietary label, country of origin, one promotion programme and FairPrice's own price bands, with sorting by price or brand. `promotions` lists everything on promotion, `category` lists a category and `categories` returns the shop's category tree. `product` returns one product with its key information, ingredients, storage, preparation, product details and nutrition table. Pass a Singapore postal code to see the range and stock of the store that delivers there; `store` tells you which store that is.
What a FairPrice field actually contains
Fields that read differently from how they look. Every row was measured against live fairprice.com.sg responses on 2026-10-15.
| Field | What it holds |
|---|---|
| price | What a shopper pays for one unit now, in SGD, the price the product page prints first (Farm Fresh Milk 2 L: 6.00). |
| regular_price, discount_amount, discount_percent | The price before a running price cut and the cut itself (Farm Fresh Milk: 6.70, 0.70, 10.4 %). All three are empty when no cut runs; price_cut_valid_to says when the cut ends. |
| multibuy | A bundle deal kept apart from price: "Any 2 for $6.80" gives quantity 2, total_price 6.80, price_each 3.40. mix_and_match is true when the deal covers several products, listed in any_of_product_ids. |
| promotions | Other deals on the product: spend and save (spend $20, get $2 off), spend and get a gift, buy and get a gift, with the minimum spend and dates. |
| unit_price, unit_price_unit | Price per kg, litre or piece, worked out from price and pack_size and rounded up to the cent the way FairPrice rounds its own per-piece prices (diapers, 26.06 for 50: 0.53 per piece, same as the site on 10 of 10). Empty when the pack size is not a plain measure. source_unit_price_text is FairPrice's own text where it prints one. |
| deposit | The BCRS beverage container deposit added at checkout, for example +$0.10 per bottle. It is not part of price. |
| stock_level, online_stock | in_stock, low or out_of_stock and the online stock count of the store the row is for. |
| sponsored | True for the paid placements FairPrice puts at the top of the first search page. The same product also appears at its own position further down. |
| store | Which store's range, stock and discounts the row comes from. 'milk' had 1,445 products at the default store, 1,316 at Hyper Changi and 719 at Bedok Mall; regular prices were the same on every shared product, discounts differed on a few. |
Loyalty prices that need a FairPrice or Link account are not part of the public shop listings, so they are not returned; price is what any shopper pays online.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/fairprice/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "milk"
}
}{
"ok": true,
"meta": {
"api": "fairprice",
"endpoint": "search",
"mode": "live",
"latency_ms": 1258.6,
"record_count": 20,
"bytes": 166590,
"cache_hit": false,
"upstream_requests": 1,
"total": 1448,
"charged_credits": 2,
"version": "0.1.0",
"request_id": "9df0e1d92fde4582",
"queue_ms": 1.9,
"fetched_at": "2026-10-15T17:02:52.957Z"
},
"data": {
"store": {
"store_id": 165,
"store_name": "Fairprice PFC",
"resolved_from": "site default"
},
"query": "milk",
"category": null,
"filters": {},
"sort": "relevance",
"total": 1448,
"page": 1,
"page_size": 20,
"last_page": 50,
"has_more": true,
"returned": 20,
"facets": {
"Country/Place Of Origin": [
{
"value": "Malaysia",
"name": "Malaysia",
"count": 272
},
{
"value": "Singapore",
"name": "Singapore",
"count": 243
},
{
"value": "Thailand",
"name": "Thailand",
"count": 160
}
],
"Dietary Attributes": [
{
"value": "Halal",
"name": "Halal",
"count": 548
},
{
"value": "Healthier Choice",
"name": "Healthier Choice",
"count": 181
},
{
"value": "Organic",
"name": "Organic",
"count": 46
}
],
"brand": [
{
"value": "marigold",
"name": "Marigold",
"count": 37
},
{
"value": "nestle-nan",
"name": "Nestle Nan",
"count": 33
},
{
"value": "marusan",
"name": "Marusan",
"count": 31
}
],
"price": [
{
"value": "[0 TO 3]",
"name": "<$3",
"count": 141
},
{
"value": "[3 TO 5]",
"name": "$3 - $5",
"count": 208
},
{
"value": "[5 TO 10]",
"name": "$5 - $10",
"count": 367
}
],
"tag": [
{
"value": "everyday-low-price",
"name": "Everyday Low Price",
"count": 28
},
{
"value": "mix-and-match-1",
"name": "Mix and match",
"count": 154
},
{
"value": "curated-lowest-price-in-30-days",
"name": "Price Slash Zone",
"count": 116
}
]
},
"results": [
{
"rank": 1,
"product_id": "1114804",
"sku": "131467",
"slug": "marigold-hl-milk-plain-946ml-131467",
"name": "Marigold HL Milk - Plain",
"brand": "Marigold",
"brand_slug": "marigold",
"barcodes": [
"8888026560010"
],
"price": 3.56,
"regular_price": null,
"discount_amount": null,
"discount_percent": null,
"currency": "SGD",
"on_offer": true,
"price_cut_valid_to": null,
"multibuy": {
"text": "Any 2 for $6.55",
"quantity": 2,
"total_price": 6.55,
"price_each": 3.27,
"mix_and_match": true,
"any_of_product_ids": [
"[trimmed-depth]",
"[trimmed-depth]",
"[trimmed-depth]"
],
"valid_from": "2026-10-01 04:01:00",
"valid_to": "2026-11-01 04:00:00"
},
"promotions": [],
"pack_size": "946ml",
"unit_price": 3.77,
"unit_price_unit": "l",
"source_unit_price_text": null,
"sold_by_weight": false,
"deposit": null,
"in_stock": true,
"stock_level": "in_stock",
"online_stock": 178,
"sponsored": true,
"rating": 4.448888888888889,
"review_count": 450,
"category": {
"id": 1803,
"name": "Fresh Milk",
"slug": "fresh-milk"
},
"category_path": [
"Dairy, Chilled & Eggs",
"Fresh Milk",
"Fresh Milk"
],
"origin": "Singapore",
"dietary": [
"Healthier Choice"
],
"nutrigrade": "B",
"supplier": "MALAYSIA DAIRY INDUSTRIES PTE",
"marketplace_seller": null,
"store": {
"store_id": 165,
"store_name": "Fairprice PFC"
},
"image": "https://media.nedigital.sg/fairprice/fpol/media/images/product/XL/131467_XL1_20260619.jpg",
"url": "https://www.fairprice.com.sg/product/marigold-hl-milk-plain-946ml-131467"
},
{
"rank": 2,
"product_id": "1623656",
"sku": "13287436",
"slug": "farm-fresh-milk-pure-2l-13287436",
"name": "[BCRS] Farm Fresh Milk - Pure",
"brand": "Farm Fresh",
"brand_slug": "farm-fresh",
"barcodes": [
"8885022600061"
],
"price": 6,
"regular_price": 6.7,
"discount_amount": 0.7,
"discount_percent": 10.4,
"currency": "SGD",
"on_offer": true,
"price_cut_valid_to": "2026-11-01 04:00:00",
"multibuy": null,
"promotions": [],
"pack_size": "2L",
"unit_price": 3,
"unit_price_unit": "l",
"source_unit_price_text": null,
"sold_by_weight": false,
"deposit": {
"amount": 0.1,
"text": "+$0.10 deposit"
},
"in_stock": true,
"stock_level": "in_stock",
"online_stock": 92,
"sponsored": false,
"rating": 4.586206896551724,
"review_count": 29,
"category": {
"id": 1803,
"name": "Fresh Milk",
"slug": "fresh-milk"
},
"category_path": [
"Dairy, Chilled & Eggs",
"Fresh Milk",
"Fresh Milk"
],
"origin": "Malaysia",
"dietary": [
"Halal",
"Vegetarian"
],
"nutrigrade": "C",
"supplier": "FRESH N NATURAL FOODS PTE LTD",
"marketplace_seller": null,
"store": {
"store_id": 165,
"store_name": "Fairprice PFC"
},
"image": "https://media.nedigital.sg/fairprice/fpol/media/images/product/XL/13287436_XL1_20260604.jpg",
"url": "https://www.fairprice.com.sg/product/farm-fresh-milk-pure-2l-13287436"
},
{
"rank": 3,
"product_id": "1622351",
"sku": "13281144",
"slug": "bcrs-marigold-hl-bottle-milk-plain-1-89l-13281144",
"name": "[BCRS] Marigold HL Bottle Milk - Plain",
"brand": "Marigold",
"brand_slug": "marigold",
"barcodes": [
"8888026240011"
],
"price": 6.55,
"regular_price": 6.97,
"discount_amount": 0.42,
"discount_percent": 6,
"currency": "SGD",
"on_offer": true,
"price_cut_valid_to": "2026-11-01 04:00:00",
"multibuy": null,
"promotions": [],
"pack_size": "1.89L",
"unit_price": 3.47,
"unit_price_unit": "l",
"source_unit_price_text": null,
"sold_by_weight": false,
"deposit": {
"amount": 0.1,
"text": "+$0.10 deposit"
},
"in_stock": true,
"stock_level": "in_stock",
"online_stock": 15,
"sponsored": true,
"rating": null,
"review_count": 0,
"category": {
"id": 1803,
"name": "Fresh Milk",
"slug": "fresh-milk"
},
"category_path": [
"Dairy, Chilled & Eggs",
"Fresh Milk",
"Fresh Milk"
],
"origin": "Singapore",
"dietary": [
"Halal",
"Healthier Choice"
],
"nutrigrade": "B",
"supplier": "MALAYSIA DAIRY INDUSTRIES PTE",
"marketplace_seller": null,
"store": {
"store_id": 165,
"store_name": "Fairprice PFC"
},
"image": "https://media.nedigital.sg/fairprice/fpol/media/images/product/XL/13281144_XL1_20260727T175327.jpg",
"url": "https://www.fairprice.com.sg/product/bcrs-marigold-hl-bottle-milk-plain-1-89l-13281144"
}
]
}
}What the FairPrice API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search NTUC FairPrice's online shop (Singapore): price paid and regular price, discount S$ and %, multi-buy deal, spend-and-save and gift promotions, container deposit, pack size and price per kg/l/pc, stock level, brand, barcodes, origin, dietary labels, rating. `query` required; filters brand, diet, origin, promo_type, min_price/max_price (FairPrice's price bands); sort; page; optional postal_code or store_id for that store's range and stock. | Pricing teams call search to search NTUC FairPrice's online shop (Singapore). | query, brand, diet, origin, promo_type, ... |
| category | List one FairPrice category (slug from `categories`, e.g. fresh-milk) with the same row fields, filters and sorts as `search`. | Marketplace operators call category to list one FairPrice category (slug from `categories`, e.g. | category, brand, diet, origin, promo_type, ... |
| promotions | Everything FairPrice has on promotion right now (the site's promotions page, 28,563 products on 2026-10-15): price paid, regular price, discount, multi-buy and gift deals. Narrow with brand, diet, origin, promo_type, price bands. For promotions matching words, use `search` with `promo_type`. | Catalog enrichment teams call promotions to get everything FairPrice has on promotion right now (the site's promotions page, 28,563 products…. | brand, diet, origin, promo_type, min_price, ... |
| product | One FairPrice product by the `product_id` a search row returns (or its slug / URL): prices, discount with its end date, multi-buy and other promotions, deposit, stock at the store, barcodes, category path, images, and the label: key information, ingredients, storage, preparation, Nutri-Grade, nutrition table, product details. | Retail analysts call product to get one FairPrice product by the `product_id` a search row. | product_id, postal_code, store_id |
| categories | FairPrice's category tree from the shop menu (1,004 nodes on 2026-10-15): slug, id, name, URL, children. Slugs feed `category`. | Pricing teams call categories to get fairPrice's category tree from the shop menu (1,004 nodes on 2026-10-15). | category, postal_code, store_id |
| store | Which FairPrice store delivers to a Singapore postal code (the store whose range and stock the listings show when you pass the same `postal_code`, or its `store_id`). | Marketplace operators call store to get which FairPrice store delivers to a Singapore postal code (the store whose range and stock th…. | postal_code |
Call search from your stack
curl -X POST https://api.reefapi.com/fairprice/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"milk"}'import requests
r = requests.post(
"https://api.reefapi.com/fairprice/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "milk"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/fairprice/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "milk"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.fairprice.search with {"query":"milk"}.Who uses this API and why
- Track FairPrice prices, price cuts and multi-buy deals with their end dates.
- Compare Singapore grocery prices per kg, litre or piece across brands and house labels.
- Build a Singapore grocery catalogue with barcodes, brands, origin, dietary labels, ingredients and nutrition.
- Monitor what is on promotion by programme, brand or price band.
- Check which products and how much stock the store serving a Singapore postal code has.
Questions developers ask before integrating
Do I need a FairPrice account?
No. Everything is read logged out: the prices, deals, stock levels and product labels any visitor sees.
What is the difference between price, regular_price and multibuy?
price is what one unit costs now. regular_price is the price before a running cut and is empty when no cut runs. multibuy is a bundle deal such as Any 2 for $6.80: it only applies when you buy the stated quantity, so it is never folded into price.
Is the container deposit included in the price?
No. Drinks under Singapore's beverage container return scheme show a separate deposit, for example +$0.10, which the API returns in deposit.
Can I filter by any price range?
FairPrice filters by its own bands only: under $3, $3 to $5, $5 to $10, $10 to $25 and over $25. min_price and max_price therefore take 0, 3, 5, 10 or 25, and the band is applied to the regular price. 'milk' went from 1,445 products to 141 under $3 and 573 between $3 and $10.
Which filters work?
brand, one dietary label, country of origin, one promotion programme and the price bands, plus sorting by price or brand. Each was checked against the unfiltered count in the same minute: 'milk' 1,445 unfiltered, 37 Marigold, 46 organic, 74 from Japan, 154 in the mix-and-match programme.
Do prices depend on the postal code?
The range, the stock and some discounts do, because each address is served by one store. Regular prices were the same in every store we compared. Pass postal_code (or store_id) to read the store that delivers there.
How many products per page, and how deep?
20 per page, FairPrice's own page size, up to page 50, so one listing shows at most 1,000 products. Narrow with filters or a category to reach the rest.
How fresh is the data?
Every call reads fairprice.com.sg live; nothing is cached. Price cuts and multi-buy deals come with their end dates.
What is the FairPrice API?
FairPrice API is a ReefAPI endpoint group for singapore supermarket prices from fairprice.com.sg: price paid and regular price, discounts, multi-buy deals, price per kg or litre, stock and product labels. It returns live JSON through POST requests under /fairprice/v1.
Is the FairPrice API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. FairPrice calls use the same shared credit balance as every other ReefAPI engine.
Do I need a FairPrice login or account?
No login to FairPrice is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the FairPrice data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the FairPrice API use?
FairPrice actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call FairPrice from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call fairprice actions with the same key, credit pool and JSON envelope used by normal REST requests.