# Mudah.my Cars, Property, Jobs & Marketplace Scraper (`abotapi/mudah-my-scraper`) Actor

Scrape Mudah.my listings across every category: cars, motorcycles, property, mobiles, electronics, home, hobbies, jobs and services. Search by keyword, filter by category, state and price, or paste URLs. Rich records with seller, store verification, images and category-specific specs.

- **URL**: https://apify.com/abotapi/mudah-my-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Jobs, Real estate
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listing results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Mudah.my Scraper

Collect structured listings from Mudah.my, Malaysia's largest online classifieds marketplace, across every category: cars, motorcycles, property, mobiles and electronics, home and furniture, hobbies and collectibles, jobs, and services. Search by keyword, narrow by category, state and price, or paste listing and category links. Each result is a clean, normalized record with seller and store details, images, timestamps, and category-specific specifications (car make/model/mileage, property rooms/size/title type, and more).

### Why this scraper

- All categories in one Actor: cars, motorcycles, property, apartments and condos, computers, mobiles and gadgets, home and furniture, hobbies and collectibles, business equipment, jobs, and services.
- Two ways to start: keyword and filter search, or paste Mudah.my listing and category URLs.
- Filter by category, Malaysian state, listing type, and price range.
- Forward pagination that walks as many result pages as you allow.
- Rich per-listing output: seller name and account type, store id and verification status, seller badges (for example, Verified Dealer), primary image, image and media counts, and full timestamps.
- Category-aware specifications extracted automatically: vehicle make, model, manufacturing year, mileage, transmission, fuel type, monthly payment and loan estimates for cars; property type, rooms, bathrooms, size, title type, and building for property.
- Optional export of results into your own apps through MCP connectors (Notion, Linear, Airtable, Apify).

### Data you get

> Sample shape, values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| id | 100000001 |
| title | Sample Listing Title |
| url | https://www.mudah.my/sample-listing-100000001.htm |
| priceLabel | RM 1,234 |
| price | 1234 |
| currency | MYR |
| categoryName | Cars |
| listingType | sell |
| condition | Second-hand (Used) |
| regionName | Selangor |
| subarea | Sample Subarea |
| sellerName | Sample Seller |
| sellerVerified | true |
| images.primaryUrl | https://img.example.com/images/00/000000000000000000.jpg |
| images.count | 5 |
| timestamps.listedAt | 2026-01-01T00:00:00.000Z |
| car.make.name | Sample Make |
| car.year | 2020 |
| car.mileage | 50000 |
| property.rooms | 3 |
| reviews | \[] |

### How to use

Search a keyword across all categories:

```json
{
  "mode": "search",
  "queries": ["iphone"],
  "maxItems": 20
}
```

Search cars in one state within a price range:

```json
{
  "mode": "search",
  "queries": ["honda civic"],
  "category": "cars",
  "state": "selangor",
  "listingType": "for-sale",
  "minPrice": 50000,
  "maxPrice": 150000,
  "maxItems": 50
}
```

Browse a whole category by state:

```json
{
  "mode": "search",
  "category": "property",
  "state": "kuala-lumpur",
  "maxItems": 100
}
```

Scrape pasted URLs (listing pages, category pages, or keyword-search pages):

```json
{
  "mode": "url",
  "startUrls": [
    "https://www.mudah.my/malaysia/cars-for-sale?q=honda+civic",
    "https://www.mudah.my/sample-listing-100000001.htm"
  ],
  "maxItems": 30
}
```

### Input parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| mode | string | search | search (keyword and filters) or url (paste links). |
| queries | array | \["iphone"] | Keywords to search. Leave empty to browse a whole category or state. |
| category | string | all | Category to restrict to (cars, property, mobiles-gadgets, jobs, and more). |
| state | string | all | Malaysian state to restrict to. |
| listingType | string | all | all, or for-sale only. |
| minPrice | integer | | Minimum price in Ringgit. |
| maxPrice | integer | | Maximum price in Ringgit. |
| startUrls | array | | URL mode: listing, category, or search pages to scrape. |
| maxItems | integer | 20 | Maximum listings to return across all searches / URLs. Set 0 for unlimited. |
| maxPages | integer | | Bound on result pages walked per search/URL. Leave empty to walk every result page; the run then stops at Max items or when a search's results are exhausted. |
| resumeFromRunId | string | | Previous run ID or dataset ID. Listings already collected there (matched by listing id) are skipped, so the run only saves new ones. Leave empty for a normal fresh run. |
| proxy | object | Apify | Connection configuration. The default is recommended. |
| mcpConnectors | array | | Optional MCP connectors to also receive results. |

### Output example

> Sample shape, values are illustrative placeholders, not from a live listing.

```json
{
  "id": "100000001",
  "adId": "100000002",
  "url": "https://www.mudah.my/sample-listing-100000001.htm",
  "title": "Sample Listing Title",
  "price": 1234,
  "priceLabel": "RM 1,234",
  "currency": "MYR",
  "category": { "id": "1020", "name": "Cars", "level1Id": null, "level1Name": null },
  "listingType": "sell",
  "condition": { "id": "1", "name": "Second-hand (Used)" },
  "location": { "regionId": "8", "region": "Selangor", "subareaId": "301", "subarea": "Sample Subarea", "raw": null },
  "seller": { "userId": "10000000", "name": "Sample Seller", "accountType": 1, "companyAd": false, "storeId": "100000", "storeVerified": true, "badges": [] },
  "sellerVerified": true,
  "images": { "primaryUrl": "https://img.example.com/images/00/000000000000000000.jpg", "count": 5, "mediaCount": 5 },
  "timestamps": { "listedAt": "2026-01-01T00:00:00.000Z", "modifiedAt": "2026-01-01T00:00:00.000Z", "origDate": "2026-01-01T00:00:00.000Z", "expiresAt": "2026-02-01T00:00:00.000Z", "listTs": 1700000000 },
  "car": { "make": { "id": "10", "name": "Sample Make" }, "model": { "id": "20", "name": "Sample Model" }, "year": 2020, "mileage": 50000, "transmission": "Automatic", "fuelType": "Petrol" },
  "reviews": [],
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

### Send results into your apps (MCP connectors)

You can optionally pipe each run's results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector under Apify, Settings, API and Integrations, then select it in the `mcpConnectors` input. For Notion, also set `notionParentPageUrl` and each item is created as a page under it; other connectors receive a best-effort write. The connector receives a condensed, human-readable summary per item (a title plus the key fields), while the complete record always stays in the Apify dataset. Leave `mcpConnectors` empty to skip; it never changes the dataset output.

### Notes on coverage

- Seller ratings and reviews: Mudah.my does not operate a seller star-rating or written-review system, so the `reviews` field is always an empty array. Seller trust is instead surfaced through the `sellerVerified` flag, the store verification status, and seller badges such as Verified Dealer.
- Contact details, full photo galleries, and long descriptions are shown only on individual protected listing pages and are not included; each record carries the primary image plus the full structured card data (price, specifications, seller, store, category, location, and timestamps).
- Property for-rent listings are browsed through their own category and URL rather than the for-sale listing type.

### Requirements

Runs on any Apify account with the default connection settings. No extra configuration is required for typical use.

# Actor input Schema

## `mode` (type: `string`):

How to start: run a keyword/category search, or scrape specific pasted URLs.

## `queries` (type: `array`):

One or more keywords to search across Mudah.my (e.g. iphone, honda civic, condo). Leave empty to browse a whole category or state.

## `category` (type: `string`):

Restrict results to a category. Choose All to search across every category.

## `state` (type: `string`):

Restrict results to a Malaysian state. Choose All for the whole country.

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

All listings, or only items offered for sale. (Property for-rent is browsed via its own category and URL.)

## `startUrls` (type: `array`):

Mudah.my URLs to scrape. Supports individual listing pages (…-<id>.htm), category pages, and keyword-search pages. Multiple URLs supported.

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

Only listings priced at or above this amount in Malaysian Ringgit.

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

Only listings priced at or below this amount in Malaysian Ringgit.

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

Maximum number of listings to return across all searches / URLs. Set 0 for unlimited (the run then stops when results are exhausted).

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

Optional bound on result pages walked per search/URL. Leave empty to walk every result page; the run then stops at Max items or when a search's results are exhausted.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already collected there (matched by listing id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run.

## `proxy` (type: `object`):

Connection configuration. The default Apify connection is recommended.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a page-per-item export; other connectors get a best-effort write. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "iphone"
  ],
  "category": "all",
  "state": "all",
  "listingType": "all",
  "startUrls": [
    "https://www.mudah.my/malaysia/cars-for-sale?q=honda+civic"
  ],
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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 = {
    "mode": "search",
    "queries": [
        "iphone"
    ],
    "startUrls": [
        "https://www.mudah.my/malaysia/cars-for-sale?q=honda+civic"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/mudah-my-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 = {
    "mode": "search",
    "queries": ["iphone"],
    "startUrls": ["https://www.mudah.my/malaysia/cars-for-sale?q=honda+civic"],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/mudah-my-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "mode": "search",
  "queries": [
    "iphone"
  ],
  "startUrls": [
    "https://www.mudah.my/malaysia/cars-for-sale?q=honda+civic"
  ],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/mudah-my-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=abotapi/mudah-my-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bWhNkj72bMaD5h9Bv/builds/U6BlxWJZsLSVGej0S/openapi.json
