Mudah.my Cars, Property, Jobs & Marketplace Scraper avatar

Mudah.my Cars, Property, Jobs & Marketplace Scraper

Pricing

from $1.00 / 1,000 listing results

Go to Apify Store
Mudah.my Cars, Property, Jobs & Marketplace Scraper

Mudah.my Cars, Property, Jobs & Marketplace Scraper

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.

Pricing

from $1.00 / 1,000 listing results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 days ago

Last modified

Share

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).
  • Daily/recurring change monitoring: turn on Incremental mode to get only NEW, UPDATED, and REAPPEARED listings on every scheduled run, or resume one specific interrupted crawl with resumeFromRunId.

Data you get

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

FieldExample
id100000001
titleSample Listing Title
urlhttps://www.mudah.my/sample-listing-100000001.htm
priceLabelRM 1,234
price1234
currencyMYR
categoryNameCars
listingTypesell
conditionSecond-hand (Used)
regionNameSelangor
subareaSample Subarea
sellerNameSample Seller
sellerVerifiedtrue
images.primaryUrlhttps://img.example.com/images/00/000000000000000000.jpg
images.count5
timestamps.listedAt2026-01-01T00:00:00.000Z
car.make.nameSample Make
car.year2020
car.mileage50000
property.rooms3
reviews[]
changeTypeNEW (incremental mode only, see "Resume & recurring updates" below)
changedFields["price", "priceLabel"] (incremental mode, UPDATED rows only)
firstSeenAt2026-01-01T00:00:00.000Z (incremental mode only)
lastSeenAt2026-01-02T00:00:00.000Z (incremental mode only)

How to use

Search a keyword across all categories:

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

Search cars in one state within a price range:

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

Browse a whole category by state:

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

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

{
"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

ParameterTypeDefaultDescription
modestringsearchsearch (keyword and filters) or url (paste links).
queriesarray["iphone"]Keywords to search. Leave empty to browse a whole category or state.
categorystringallCategory to restrict to (cars, property, mobiles-gadgets, jobs, and more).
statestringallMalaysian state to restrict to.
listingTypestringallall, or for-sale only.
minPriceintegerMinimum price in Ringgit.
maxPriceintegerMaximum price in Ringgit.
startUrlsarrayURL mode: listing, category, or search pages to scrape.
maxItemsinteger20Maximum listings to return across all searches / URLs. Set 0 for unlimited.
maxPagesintegerBound 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.
resumeFromRunIdstringPrevious run ID or dataset ID. Listings already collected there (matched by listing id) are skipped, so the run only saves new ones. For recurring daily/weekly monitoring of the same search, use incrementalMode instead, see "Resume & recurring updates" below.
incrementalModebooleanfalseDaily/recurring monitoring of this same search. First run returns everything as NEW; later runs return only NEW/UPDATED/REAPPEARED by default. See "Resume & recurring updates" below.
stateKeystringOptional name for a monitoring campaign, so its incremental state stays stable or is deliberately shared. Auto-derived from your mode/keyword/category/state/price/URL setup when left empty.
emitUnchangedbooleanfalseIncremental mode only. Also return listings unchanged since the last run, marked UNCHANGED. Adds and bills extra rows you already have.
emitExpiredbooleanfalseIncremental mode only. Also return listings from a previous run no longer found, marked EXPIRED, once a run has fully scanned the tracked search (not capped, not a resume, and not a URL-mode run that only looked up individual listing URLs). Adds and bills extra synthetic rows.
proxyobjectApifyConnection configuration. The default is recommended.
mcpConnectorsarrayOptional MCP connectors to also receive results.

Resume & recurring updates

There are two different things here, pick the one that matches what you're doing:

NeedUse
A crawl stopped and should continueresumeFromRunId / automatic checkpoint recovery
Run the same search every day and receive only changesincrementalMode
Keep separate daily campaigns for similar searchesdistinct stateKey values
Run a normal full snapshotleave both off

Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips listings already collected there, returning only the remaining new ones. A checkpoint is also saved automatically as the run progresses: if the run is interrupted by an Apify platform migration or you click Resurrect on a failed run, it picks back up from where it left off in the same run, without re-saving (or re-charging for) listings it already collected. No input is needed for the checkpoint; it's automatic.

Incremental mode (incrementalMode) is for a schedule (for example, daily): the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything as NEW. Later runs return only NEW, UPDATED, and REAPPEARED listings by default, duplicates and unchanged listings are suppressed (and not charged). Turn on emitUnchanged or emitExpired only when you also want those rows returned (and billed for). State is isolated per mode/keyword/category/state/listing type/price/URL setup automatically; set stateKey to name or deliberately share a monitoring campaign.

Combining both: setting incrementalMode and resumeFromRunId together is only allowed to bootstrap the very first incremental run from an existing crawl (no incremental state saved yet for this search). Once a baseline exists, supplying both fails fast with an explanatory error, remove resumeFromRunId or set a different stateKey.

Scheduled-run example, same search, run daily:

Day 1 (first run ever for this search):

{ "mode": "search", "queries": ["iphone"], "incrementalMode": true }

→ every listing comes back with "changeType": "NEW".

Day 2 (the schedule fires again, identical input):

{ "mode": "search", "queries": ["iphone"], "incrementalMode": true }

→ listings whose price/title/seller/etc. changed come back as "changeType": "UPDATED" with changedFields listing what changed, brand-new listings come back as "changeType": "NEW", listings that vanished and came back come back as "changeType": "REAPPEARED", and listings that are still there unchanged are not returned at all (suppressed, not charged) unless emitUnchanged is on. Turn on emitExpired to also see listings that disappeared since the last run, marked EXPIRED, once a run completes a full scan (not capped by Max items/Max pages, not a resume, and not a URL-mode run that only looked up individual listing URLs, since such a run never walks the tracked search and so cannot prove anything is gone). An EXPIRED row carries the listing exactly as it looked on the last run that still found it, lastSeenAt says when that was.

Output example

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

{
"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.