# 99.co Scraper (`happyendpoint/99co-scraper`) Actor

Scrape 99.co Singapore: listings for sale or rent with filters, full listing details, new launch projects, past sale and rental transactions, and agent contacts.

- **URL**: https://apify.com/happyendpoint/99co-scraper.md
- **Developed by:** [Happy Endpoint](https://apify.com/happyendpoint) (community)
- **Categories:** Real estate, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🏠 99.co Scraper - Singapore Property Listings, Transactions, New Launches & Agents

### 🚫 No Proxies Needed

> ⚠️ **Free plan limit: 100 results per run.** Runs started from an Apify **free plan** account return at most 100 results, whatever **Max Items** is set to. Paid Apify plans get unlimited results. [Compare Apify plans](https://apify.com/pricing).

Extract **Singapore real estate data from 99.co**, one of Singapore's leading property portals. Search HDB flats, condos and landed homes **for sale or rent** with price, bedroom, furnishing and tenure filters, get full listing details, browse **new launch projects**, look up any condo or estate, pull **past sale and rental transactions** (resale prices, rents, PSF, profit and holding period) and collect **property agent** contacts. Type plain place names like `Tampines`, `D9` or `Bishan MRT`: the actor finds the right area for you.

***

### What This Actor Does

| Operation | What you get |
|---|---|
| 🏠 **Search listings** | Singapore listings for sale or rent: price, PSF, bedrooms, bathrooms, floor area, address, tenure, built year, furnishing, nearest MRT, agent name and phone, photos, listing URL. Optional full details per listing |
| 📄 **Listing details** | Everything on a listing page: description, postal code, district, amenities, insights, recent transactions of the building, floor plans, videos, photos and agent contact |
| 🏗️ **New projects** | New launch condo and EC projects: district, expected completion (TOP), tenure, total units, price range and latest transaction |
| 🏢 **Project details** | A condo or estate's key facts (developer, tenure, completion, size), facilities, floor plans, photos, units for sale and rent, plus optional nearby amenities with travel times |
| 📈 **Transactions** | Past **sale** or **rental** transactions for a project, area, HDB town, district or MRT station: date, block, unit floor, size, price, PSF, profit, holding period and sale type |
| 🧑‍💼 **Search agents** | Property agents by name: agency, CEA licence numbers, phone, WhatsApp link, listing and transaction counts. Optional full profile with email |
| 🪪 **Agent details** | Full agent profiles: phone, email, job title, bio, areas of expertise and listings by type, category, district and development |
| 🩺 **Health check** | The default operation: confirms the actor is working and saves one status row. Choose another operation to get data |

By default each search loads **one page** of results (up to 50 listings, projects or agents, or 20 transactions per place). Raise **Max Pages** to get more. Duplicates are removed, so you never pay twice for the same listing, project, transaction or agent.

***

### How to Use

#### Search listings for sale or rent

```json
{
    "operation": "search-listings",
    "listingType": "sale",
    "locations": ["Tampines", "D19"],
    "propertyTypes": ["hdb"],
    "minBedrooms": 3,
    "maxPrice": 900000,
    "maxPages": 4,
    "maxItems": 200
}
```

```json
{
    "operation": "search-listings",
    "listingType": "rent",
    "locations": ["Bishan MRT"],
    "furnishing": ["fully"],
    "rentalType": "unit",
    "maxPrice": 5000,
    "includeListingDetails": true,
    "maxItems": 50
}
```

Places can be an area (`Tampines`), a district (`D9`, `District 15`), an MRT station (`Bishan MRT`), an HDB town or a condo name. Leave **Places** empty to search all of Singapore.

#### Listing details

```json
{
    "operation": "listing-details",
    "listingUrls": [
        "https://www.99.co/singapore/sale/property/parc-centennial-condo-PD8ntADQP7UNGz9GcHjKRa",
        "9RdkE9z26j3YdQhooAPdKu"
    ]
}
```

#### New launch projects

```json
{ "operation": "new-projects", "locations": ["D10"], "maxItems": 50 }
```

Leave **Places** empty for every new launch in Singapore. Districts give the most reliable filtering.

#### Project details

```json
{ "operation": "project-details", "projects": ["Parc Centennial", "21 Anderson"], "includeNearbyAmenities": true }
```

#### Past sale or rental transactions

```json
{ "operation": "transactions", "locations": ["Parc Centennial"], "listingType": "sale", "maxPages": 25, "maxItems": 500 }
```

```json
{ "operation": "transactions", "locations": ["Tampines"], "listingType": "rent", "maxPages": 50, "maxItems": 1000 }
```

#### Property agents

```json
{ "operation": "search-agents", "agentKeyword": "tan", "includeAgentDetails": true, "maxPages": 2, "maxItems": 100 }
```

```json
{ "operation": "agent-details", "agentProfiles": ["https://www.99.co/singapore/agents/R024093E-lincoln-choo"] }
```

***

### 📥 Input Reference

| Field | Used by | Description |
| :--- | :--- | :--- |
| `operation` | All | `health-check` (default), `search-listings`, `listing-details`, `new-projects`, `project-details`, `transactions`, `search-agents`, `agent-details` |
| `listingType` | Search listings, Transactions | `sale` (default) or `rent` |
| `locations` | Search listings, New projects, Transactions | Place names or 99.co location IDs |
| `propertySegment` | Search listings | `residential` (default), `commercial`, `industrial`, `land` |
| `propertyTypes` | Search listings | `hdb`, `condo`, `landed` (residential only) |
| `minPrice` / `maxPrice` | Search listings | Price in S$ (monthly rent for rentals) |
| `minBedrooms` / `maxBedrooms` | Search listings | `0` means studio |
| `minBathrooms` | Search listings | Minimum bathrooms |
| `furnishing` | Search listings | `fully`, `partial`, `unfurnished` |
| `tenure` | Search listings | `freehold`, `999`, `99` |
| `rentalType` | Search listings | `any` (default), `unit` (whole unit), `room` |
| `includeListingDetails` | Search listings | Add full listing page data to each result |
| `listingUrls` | Listing details | Listing links or IDs |
| `projects` | Project details | Project names, links or IDs |
| `includeNearbyAmenities` | Project details | Add nearby MRT, schools, shops and more |
| `agentKeyword` | Search agents | Agent name or keyword |
| `includeAgentDetails` | Search agents | Add email, job title and bio |
| `agentProfiles` | Agent details | Agent profile links or slugs |
| `maxItems` | All | Maximum results to save (default 100) |
| `maxPages` | Search listings, New projects, Transactions, Search agents | Result pages to load per place (default 1) |

Invalid input (for example a min price above the max price) stops the run straight away with a message explaining why. A place or ID that can't be found is skipped and reported in the log.

***

### 📤 Output Example (Search listings)

```json
{
  "id": "JTzeUcmjp4qxrqPc3gvFM3",
  "url": "https://www.99.co/singapore/sale/property/520b-tampines-central-8-hdb-JTzeUcmjp4qxrqPc3gvFM3",
  "title": "Premium HDB for Sale in 520B Tampines Central 8",
  "listing_type": "sale",
  "property_type": "hdb",
  "price": 1140000,
  "price_formatted": "S$ 1,140,000",
  "price_per_sqft": 981,
  "bedrooms": 3,
  "bathrooms": 2,
  "floor_area_sqft": 1162,
  "address": "520B Tampines Central 8 522520",
  "neighbourhood": "Tampines East",
  "region": "East Region",
  "tenure": "99 yrs",
  "built_year": 2014,
  "nearest_mrt": "Tampines MRT",
  "nearest_mrt_time": "10 mins",
  "agent_name": "Charmaine Choo",
  "agent_phone": "+6596439124",
  "image_url": "https://pic2.99.co/v3/4BREdCd2wpMkQrKLQJPzfS?...",
  "subCategory": "hdb_5r",
  "estMortgage": "Est. Mortgage S$ 3,623/mo",
  "lat": 1.35726635061626,
  "lng": 103.939665206968,
  "photoCount": 30,
  "photos": ["https://pic2.99.co/v3/..."],
  "nearestMrt": { "name": "Tampines MRT", "walkOrTransit": "walk", "durationFormatted": "10 mins", "distance": 758 },
  "agent": { "id": "8WQysS7yfHLscWLKewWtND", "name": "Charmaine Choo", "phone": "+6596439124", "isRecommended": true },
  "uspTags": ["Spacious Layout", "Balcony Unit", "3 Bedrooms", "Study Room"],
  "search_location": "Tampines",
  "search_location_id": "zotampines"
}
```

#### Output Example (Transactions)

```json
{
  "transaction_type": "sale",
  "date": "02/2026",
  "month": "2026-02",
  "property_name": "Parc Centennial",
  "block": "100",
  "unit": "11-xx",
  "bedrooms": 2,
  "area_sqft": 1162,
  "price": 2218000,
  "price_formatted": "S$ 2.218M",
  "price_per_sqft": 1909,
  "profit": "+S$ 618,000",
  "holding_period_years": 5,
  "sale_type": "Resale",
  "search_location": "Parc Centennial"
}
```

The **Output** tab has table views for Listings, Listing details, New projects, Project details, Transactions, Agents and Agent profiles. Export to **JSON**, **CSV** or **Excel**, or send the data to **Google Sheets**, **webhooks** and other integrations.

***

### 💡 Use Cases

- **Property price research:** compare asking prices and PSF across Singapore areas, districts and MRT stations.
- **Resale and rental benchmarks:** pull past HDB and condo sale and rental transactions to value a unit or check rental yields.
- **New launch tracking:** follow new condo and EC launches with price ranges and completion dates.
- **Investment screening:** filter by tenure, bedrooms and budget, then check each building's transaction history and profit records.
- **Agent lead generation:** build lists of Singapore property agents with agency, licence numbers, phone and email.
- **Market monitoring:** schedule daily runs to track new listings and price changes.

***

### ❓ FAQ

**How am I charged?**
You pay per result saved: one listing, project, transaction or agent is one result. Health check rows and places that can't be found cost nothing.

**How does paging work?**
Each search loads **Max Pages** pages per place (default 1, so a first run stays quick and cheap). One page has up to 50 listings, projects or agents, or 20 transactions. The run stops at **Max Pages**, **Max Items** or when there are no more results, whichever comes first. Duplicates are removed.

**Can I search by MRT station or district?**
Yes. Type `Bishan MRT`, `D9`, `District 15`, an area like `Tampines` or a condo name. The log shows which place each entry was matched to.

**Why do I only get 100 results?**
Runs from Apify free plan accounts are limited to 100 results. Paid Apify plans get unlimited results.

**Which transactions are included?**
The same past sale and rental records shown on 99.co for that place, newest first. Unit numbers are partly hidden (for example `11-xx`), as on the website.

***

### 📞 Contact & Custom Solutions

Need more real estate data or a custom integration? We provide tailored data solutions.

- **Website:** [happyendpoint.com](https://happyendpoint.com)
- **Twitter:** [@happyendpointhq](https://x.com/happyendpointhq)
- **Email:** <hello@happyendpoint.com>

### 🔗 Useful Links

- **Our Official Website:** [Happy Endpoint](https://happyendpoint.com)
- **99.co Data API (use this data in your own app):** [happyendpoint.com/library/99co-api](https://happyendpoint.com/library/99co-api)
- **99.co:** [www.99.co](https://www.99.co)

### Our Other Scrapers

- [Priceline Hotels Scraper](https://apify.com/happyendpoint/priceline-hotels-scraper)
- [Tesco Scraper](https://apify.com/happyendpoint/tesco-scraper)
- [Sephora Scraper](https://apify.com/happyendpoint/sephora-scrapper)
- [Ikea Scraper](https://apify.com/happyendpoint/ikea-scraper)
- [Ikea Product Scraper By Category](https://apify.com/happyendpoint/ikea-products-bycategory)
- [Idealista Scraper](https://apify.com/happyendpoint/idealista-scraper)
- [Idealista Scraper by URL](https://apify.com/happyendpoint/idealista-scraper-by-url)
- [Kohl's Scraper](https://apify.com/happyendpoint/kohls-scraper)

### Other Products

- [UAE Bayut Data API](https://bayutapi.dev)
- [Propertyfinder UAE Data API](https://uaepropertyapi.com)

> This actor is an independent service and is not affiliated with, endorsed, or sponsored by 99.co.

# Actor input Schema

## `operation` (type: `string`):

**Health check** (default) only confirms the actor is working and saves one status row. To get data, pick another operation and fill in its section below.

## `listingType` (type: `string`):

**\[Search listings, Transactions]** Homes for sale or for rent. For **Transactions** this picks past sale prices or past rental prices.

## `locations` (type: `array`):

**\[Search listings, New projects, Transactions]** One or more places in Singapore: an area (`Tampines`), a district (`D9` or `District 15`), an MRT station (`Bishan MRT`), an HDB town or a condo name (`Parc Centennial`). Leave empty to search all of Singapore (not possible for **Transactions**, which needs a place). Each place is searched in turn.

## `propertySegment` (type: `string`):

**\[Search listings]**

## `propertyTypes` (type: `array`):

**\[Search listings]** Residential only. Leave empty for all types.

## `minPrice` (type: `integer`):

**\[Search listings]** For rent this is the monthly rent.

## `maxPrice` (type: `integer`):

**\[Search listings]** For rent this is the monthly rent.

## `minBedrooms` (type: `integer`):

**\[Search listings]** `0` means studio.

## `maxBedrooms` (type: `integer`):

**\[Search listings]**

## `minBathrooms` (type: `integer`):

**\[Search listings]**

## `furnishing` (type: `array`):

**\[Search listings]** Leave empty for any furnishing.

## `tenure` (type: `array`):

**\[Search listings]** Leave empty for any tenure.

## `rentalType` (type: `string`):

**\[Search listings]** For rent searches only.

## `includeListingDetails` (type: `boolean`):

**\[Search listings]** Also load each listing's page: description, postal code, district, amenities, insights, past transactions of the building, floor plans, videos and full agent info. Slower (one extra request per listing).

## `listingUrls` (type: `array`):

**\[Listing details]** 99.co listing links, or the `id` values from **Search listings**.

## `projects` (type: `array`):

**\[Project details]** Condo or estate names (`Parc Centennial`), project links from 99.co, or the project `id` values from **New projects** or **Listing details** (`project_id`).

## `includeNearbyAmenities` (type: `boolean`):

**\[Project details]** Also add nearby MRT stations, schools, supermarkets, parks, clinics and more, with walking, driving and public transport times.

## `agentKeyword` (type: `string`):

**\[Search agents]** Agent name or keyword, for example `tan`. Leave empty to go through the whole agent directory.

## `includeAgentDetails` (type: `boolean`):

**\[Search agents]** Also load each agent's profile: email, job title, bio, areas of expertise and a breakdown of their listings. Slower (one extra request per agent).

## `agentProfiles` (type: `array`):

**\[Agent details]** 99.co agent profile links, or the `slug` values from **Search agents** (for example `R024093E-lincoln-choo`).

## `maxItems` (type: `integer`):

**\[All operations]** Maximum number of results to save in total (listings, projects, transactions or agents). The run stops at Max Items or Max Pages, whichever comes first. Apify free plan accounts get at most 100 results per run.

## `maxPages` (type: `integer`):

**\[Search listings, New projects, Transactions, Search agents]** How many result pages to load for each place (or for the agent search). One page has up to 50 listings, projects or agents, or 20 transactions. The default of 1 keeps a first run quick; raise it to get more, for example 4 pages for about 200 listings.

## Actor input object example

```json
{
  "operation": "health-check",
  "listingType": "sale",
  "locations": [
    "Tampines"
  ],
  "propertySegment": "residential",
  "rentalType": "any",
  "includeListingDetails": false,
  "listingUrls": [
    "https://www.99.co/singapore/sale/property/parc-centennial-condo-PD8ntADQP7UNGz9GcHjKRa"
  ],
  "projects": [
    "Parc Centennial"
  ],
  "includeNearbyAmenities": false,
  "agentKeyword": "tan",
  "includeAgentDetails": false,
  "agentProfiles": [
    "https://www.99.co/singapore/agents/R024093E-lincoln-choo"
  ],
  "maxItems": 100,
  "maxPages": 1
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "Tampines"
    ],
    "listingUrls": [
        "https://www.99.co/singapore/sale/property/parc-centennial-condo-PD8ntADQP7UNGz9GcHjKRa"
    ],
    "projects": [
        "Parc Centennial"
    ],
    "agentKeyword": "tan",
    "agentProfiles": [
        "https://www.99.co/singapore/agents/R024093E-lincoln-choo"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("happyendpoint/99co-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["Tampines"],
    "listingUrls": ["https://www.99.co/singapore/sale/property/parc-centennial-condo-PD8ntADQP7UNGz9GcHjKRa"],
    "projects": ["Parc Centennial"],
    "agentKeyword": "tan",
    "agentProfiles": ["https://www.99.co/singapore/agents/R024093E-lincoln-choo"],
}

# Run the Actor and wait for it to finish
run = client.actor("happyendpoint/99co-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "Tampines"
  ],
  "listingUrls": [
    "https://www.99.co/singapore/sale/property/parc-centennial-condo-PD8ntADQP7UNGz9GcHjKRa"
  ],
  "projects": [
    "Parc Centennial"
  ],
  "agentKeyword": "tan",
  "agentProfiles": [
    "https://www.99.co/singapore/agents/R024093E-lincoln-choo"
  ]
}' |
apify call happyendpoint/99co-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,happyendpoint/99co-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Mrz8e10voWvIQy7WA/builds/7s4lKwSuIgGx9NTVQ/openapi.json
