GrabFood Restaurant Scraper icon

GrabFood Restaurant Scraper

Scrape GrabFood restaurants across Southeast Asia, including SG, MY, TH, VN, PH, ID, KH, and MM. Search by keyword or URL and extract 45+ fields:…

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

GrabFood Restaurant Scraper at a glance

GrabFood Restaurant Scraper is a ready-to-run Apify actor from abotapi for collecting ecommerce data. Its documented output includes id, name, chain, cuisine and rating, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Ecommerce, Developer Tools, Automation
Pricing
$1.80 per 1,000 results (Free plan), from $1.00 on paid plans
Output
Documented below · JSON, CSV, Excel
Inputs
24 options

Scrape GrabFood restaurants across Southeast Asia, including SG, MY, TH, VN, PH, ID, KH, and MM. Search by keyword or URL and extract 45+ fields: restaurant name, address, GPS, cuisine, ratings, reviews, promos, delivery time, fees, opening hours, and full menus with item prices and images.

What GrabFood Restaurant Scraper: Menus, Ratings & Delivery Data can do

  • Two ways to find restaurants. Search by keyword inside a region, or paste ready made GrabFood restaurant pages and listing pages directly.
  • Full menu on demand. Turn on menu extraction and get every category and item, with description, price, discounted price, takeaway price, image and modifier group count.
  • 8 regions, one actor. Singapore, Malaysia, Thailand, Vietnam, Philippines, Indonesia, Cambodia and Myanmar, each with prices in its own local currency.
  • Delivery detail that matters for ordering. Delivery time, delivery fee (with any discount applied), delivery options such as delivery, takeaway or dine in, and distance from the search point.
  • Structured promotions. Promo labels come through as readable text, for example "S$5.00 off", not just a yes or no flag.
  • Filters and sorting built in. Keep only restaurants matching a cuisine tag, a minimum rating or a minimum review count, then sort by rating, review count, distance or delivery time.

Choose what to collect

These inputs let you configure GrabFood Restaurant Scraper: Menus, Ratings & Delivery Data. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestring · requiredPick how to find restaurants. Search runs keyword queries in one region. URL mode pastes ready-made GrabFood links (a single restaurant page or a restaurants listing page).

Choices: search, url

regionstringGrabFood country to search. Results and prices are for that country's stores.

Choices: SG, MY, TH, VN, PH, ID, KH, MM

languagestringLanguage of restaurant and menu text and of the grabUrl links, where GrabFood offers it for the selected country: Thailand (en, th), Vietnam (en, vn), Indonesia (en, id). Other countries are English only; an unsupported choice falls back to the country default.

Choices: default, en, th, vn, id

deliveryLatitudenumberOptional delivery point. Supply both latitude and longitude. Used in search, recommended listings and restaurant detail requests. Leave both blank to use the country default point. Does not confirm checkout eligibility.
deliveryLongitudenumberOptional delivery point. Supply both latitude and longitude. Used in search, recommended listings and restaurant detail requests. Leave both blank to use the country default point. Does not confirm checkout eligibility.
searchQueriesarrayKeywords to search within the selected region (e.g. "ramen", "pizza", "bubble tea"). Leave empty to search the default keyword (ramen); to browse a region's recommended feed use URL mode with a listing URL that has no search term. Only applies in Search mode.
startUrlsarrayReady-made GrabFood URLs. Supported: a restaurant page (https://food.grab.com///restaurant//, the language segment is optional), a restaurants listing page (https://food.grab.com///restaurants?search=, or without a keyword for the recommended feed) and a country home page (treated as the recommended feed). A page= parameter is not honoured and a sortBy= parameter is ignored (use the Sort by input); chain pages and city cuisine/dish collections are skipped with a warning. Only applies in URL mode.
Show 17 more inputs
More input fields
InputWhat it controls
cuisineFilterarrayKeep only restaurants whose cuisine tags contain any of these terms (e.g. burger, sushi, halal, western, vegetarian). Case-insensitive substring match. Leave empty to include all.
minRatingintegerMinimum star rating (0-5). Restaurants below this are skipped. Leave empty for no minimum.
minReviewsintegerMinimum number of ratings a restaurant must have to be included. Leave empty or 0 for no minimum.
sortBystringOrder of restaurants in the output. Default keeps GrabFood's own ranking; the other options re-order the collected results client-side.

Choices: default, rating, reviews, distance, delivery-time

fetchMenubooleanWhen ON, each restaurant is enriched with its full menu (categories, items, prices, images) and full address. Turn off for faster listing-only runs.
includeRatingsbooleanWhen ON, the rating score and review count are populated on every record. Turn off if you don't need any rating data.
maxItemsintegerHard cap on total restaurants for the whole run. This is the main limit. Leave empty or 0 for unlimited (the run then stops at Max pages).
maxPagesintegerNo page limit by default, the run stops at Max restaurants. Set a number only to also cap how many listing pages are walked per search. Whatever you set, a single run never walks beyond what the 1,000-restaurant hard stop needs.
resumeFromRunIdstringPaste a previous run ID or dataset ID to continue a large pull of restaurants without returning or charging for restaurants already collected there. Use this after an interrupted run, or when continuing a large crawl in another run. For recurring daily monitoring of the same search, use Incremental mode below instead.
incrementalModebooleanTurn this on for daily or recurring monitoring. The first run returns all matching restaurants as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED restaurants. A restaurant is UPDATED when any output field changes (rating, votes, promo labels, open status, delivery time and fee, menu categories/items with prices and availability, opening hours, announcements, photos) except scrapedAt and any fields you list in Ignore fields below; changedFields names what moved. EXPIRED is only emitted after a complete scan. Turn on "Emit unchanged" or "Emit expired" only when you also want those restaurants returned (and billed). State is kept separately for each mode/region/search/URL and detail/filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.
stateKeystringOptional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the mode/region/search/URL and detail/filter settings, different searches then never mix state with each other.
emitUnchangedbooleanOff by default. Turn on to also return restaurants that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want the full snapshot every run.
emitExpiredbooleanOff by default. Turn on to also return restaurants that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max restaurants capped it or when Resume was used. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.
ignoreFieldsForChangesarrayOptional. Field names that must NOT make a restaurant count as UPDATED, e.g. announcements, photoHref, openHours. Use a dotted path for nested fields (menu.items.price drops price from every menu item; arrays are transparent) or .name to ignore a name at any depth (.photoHref). Ignored fields still appear in the output; they are only left out of the comparison and changedFields. Already excluded automatically: scrapedAt.
mcpConnectorsarrayOptionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON, the complete record stays in the dataset. 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).
notionParentPageUrlstringURL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.
maxNotifyListingsintegerCap on items written to each connector per run. Does not affect the dataset.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

idID
nameName
chainNameChain
cuisineCuisine
ratingRating
voteCountReviews
priceTagPrice tier
addressAddress
fullAddressFull address
cityCity
countryCodeCountry
latitudeLat
Show 44 more fields
longitudeLng
isOpenOpen
estimatedDeliveryTimeETA (min)
estimatedDeliveryTimeRangeETA range
distanceInKmDistance km
hasPromoPromo
promoLabelsPromo labels
deliveryOptionsDelivery options
menuCategoryCountMenu cats
menuItemCountMenu items
branchNameBranch
deliveryFeeDelivery fee
currencyCurrency
openHoursOpening hours
photoHrefPhoto (image)
menuMenu (categories and items)
orderValueLimitOrder value limit
announcementsAnnouncements
sourceQuerySource query
sourceUrlSource URL (link)
grabUrlGrabFood URL (link)
regionRegion
scrapedAtScraped
changeTypeChange type (incremental mode)
changedFieldsChanged fields (incremental mode)
firstSeenAtFirst seen (incremental mode)
lastSeenAtLast seen (incremental mode)
deliveryContextDelivery point and status
menuObservedAtMenu observed at
descriptionItem description
availableAvailable (boolean)
pricePrice (minor units) (number)
discountedPriceDiscounted price (minor units) (number)
takeawayPriceTakeaway price (minor units) (number)
imageUrlImage (link)
modifierGroupCountOption groups (number)
isOnSpecialOn special (boolean)
savingsAmountSavings (minor units) (number)
discountPercentDiscount % (number)
currencyCodecurrencyCode
currencyExponentCurrency decimal places
priceInCurrencyUnitsPrice (currency units)
priceDisplaypriceDisplay
discountedPriceDisplaydiscountedPriceDisplay

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "id": "SGDD00000",
  "name": "Sample Burger Place",
  "chainName": "Sample Burger",
  "branchName": "Downtown",
  "description": "Sample restaurant blurb",
  "cuisine": [
    "Burger",
    "Fast Food",
    "Halal"
  ],
  "address": "Sample Burger Place - Downtown",
  "fullAddress": "1 Sample Street, #01-01",
  "street": "Sample Street",
  "suburb": "Downtown",
  "postcode": "000000",
  "city": "Singapore",
  "countryCode": "SG",
  "rating": 4.3,
  "voteCount": 1200,
  "priceTag": 2,
  "isOpen": true,
  "estimatedDeliveryTime": 35,
  "estimatedDeliveryTimeRange": "From 35 mins",
  "distanceInKm": 1.34,
  "hasPromo": true,
  "promoLabels": [
    "S$5.00 off"
  ],
  "deliveryOptions": "DELIVERY_TAKEAWAY_DINEIN",
  "deliveryFee": {
    "currencyCode": "SGD",
    "currencySymbol": "S$",
    "price": 200,
    "priceDisplay": "S$2.00",
    "discountedPrice": 0,
    "hasDiscountedPrice": true
  },
  "currency": {
    "code": "SGD",
    "symbol": "S$",
    "exponent": 2
  },
  "openHours": {
    "mon": "10:00-22:00",
    "tue": "10:00-22:00",
    "displayedHours": "Daily 10:00-22:00"
  },
  "photoHref": "https://food.grab.com/sample/photo.jpg",
  "grabUrl": "https://food.grab.com/sg/en/restaurant/sample-burger-place/SGDD00000",
  "menuCategoryCount": 12,
  "menuItemCount": 86,
  "menu": [
    {
      "name": "Burgers",
      "available": true,
      "itemCount": 1,
      "items": [
        {
          "id": "ITEM0001",
          "name": "Classic Cheeseburger",
          "description": "Beef patty, cheddar, lettuce, house sauce",
          "available": true,
          "price": 890,
          "discountedPrice": 690,
          "takeawayPrice": 850,
          "imageUrl": "https://food.grab.com/sample/burger.jpg",
          "modifierGroupCount": 2,
          "isOnSpecial": true,
          "savingsAmount": 200,
          "discountPercent": 22
        }
      ]
    }
  ],
  "orderValueLimit": 1500,
  "announcements": [
    "Public holiday hours apply"
  ],
  "region": "SG",
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}

Ways to use this data

  • Delivery aggregation and comparison apps: pull live menus, prices and delivery fees to compare against other platforms.
  • Market and competitor research: track promotions, price tiers and ratings across cuisines, chains and cities.
  • Menu and pricing analytics: build a historical menu and price dataset for a chain across countries.
  • Local lead generation: find restaurants by cuisine, rating or review count to build outreach or partnership lists.
  • Daily monitoring: watch a search or a list of restaurants for new promotions, rating changes or menu updates.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does GrabFood Restaurant Scraper return?

The documented output for GrabFood Restaurant Scraper includes id, name, chain, cuisine, rating, reviews, price tier and address. Availability of each field depends on the source page and the selected mode.

How much does GrabFood Restaurant Scraper cost?

It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Is an evaluation run free?

Starting a run incurs the Actor Start charge even if no restaurants are returned. Restaurant result and Menu enrichment charges apply to delivered results as described above; credits are not a zero-charge guarantee. Check the Pricing tab and the run's memory setting before starting. A separately shared static evaluation sample requires no actor run, subscription or purchase, and grants no additional content-use rights.

Does the menu include availability or sold-out status?

With Fetch full menu on, menu[].items[].available and the category's available field are included when GrabFood supplies a boolean value. true means available and false means unavailable in that response; unavailable does not necessarily mean sold out. A null or omitted flag means unknown, and an item missing from the menu is not proof that it is sold out. Availability reflects the selected location and time, rather than a guaranteed inventory count.

How do I target one Indonesian outlet?

Search in region ID uses a central Jakarta delivery location unless both delivery coordinates are supplied. A keyword containing another city or branch name can still return nearby alternatives. Use URL mode with that outlet's restaurant URL to target a specific branch.

Can I get only new or changed restaurants on a schedule?

Yes. Schedule the actor from the Schedules tab with the same search or URLs and turn on Incremental mode. Each run then returns only NEW, UPDATED and REAPPEARED restaurants; unchanged ones are skipped and not billed unless Emit unchanged is on.

Ready to collect with GrabFood Restaurant Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.