Grab Scraper - GrabFood Menus & GrabMart Data
Pricing
from $2.20 / 1,000 results
Grab Scraper - GrabFood Menus & GrabMart Data
Extract GrabFood restaurants, menus, and GrabMart products across eight Southeast Asian markets. Get merchant IDs, public URLs, ratings, and prices when available. Pay per delivered row plus a start fee.
Pricing
from $2.20 / 1,000 results
Rating
0.0
(0)
Developer
kane liu
Maintained by CommunityActor stats
1
Bookmarked
77
Total users
39
Monthly active users
4.9 hours
Issues response
a day ago
Last modified
Categories
Security
Limited permissionsShare
Grab Scraper
Extract GrabFood restaurants, menus, and GrabMart listings across eight Southeast Asian markets as rows you can export.
- Find merchants by keyword, cuisine, chain, delivery location, or public directory.
- Collect menu items and product details with prices when available.
- Keep merchant IDs and URLs for matching across runs.
- Export rows or use them with AI agents and the Apify API.
- Pay $3.00 per 1,000 rows on the Free plan, plus a small start fee.
What does Grab Scraper do?
Grab Scraper collects public data from food.grab.com and mart.grab.com. Supported market inputs are Singapore (sg), Malaysia (my), Philippines (ph), Thailand (th), Vietnam (vn), Indonesia (id), Cambodia (kh), and Myanmar (mm). Availability varies by location and mode.
- Discovery:
search,cuisine,recommended,chain, anddiscoverCategoriesfind restaurants, branches, or categories. - Details:
restaurantreturns merchants and optional menu rows;mart_itemreturns one product's details. - GrabMart:
martfinds merchants;mart_itemsandmart_merchantslist public directory entries. - Directories and URLs:
directorylists GrabFood merchants;startUrlsaccepts several supported links. - Optional rows:
includeMenuItems,expandBranches,emitCuisines, andemitPromoLabelsare off by default. Each extra row is billed at the same price and counts toward the input's limit.
What data can you extract from Grab?
Each row represents one entity. Fields vary by mode and source availability. rowType identifies the entity; itemType remains for compatibility.
Merchants: restaurant
Includes GrabFood restaurants, branches, GrabMart merchants, and directory entries.
| Field | Description | Example |
|---|---|---|
merchantId | Grab merchant identifier | 2-C2EYTY3AJ6NZKA |
name | Merchant name | Example Kitchen |
url | Public merchant link | https://food.grab.com/ph/en/restaurant/example/2-C2EYTY3AJ6NZKA |
businessType | Food or grocery merchant | FOOD |
countryCode | Market code in output | PH |
rating | Published rating | 4.6 |
deliveryFee | Published delivery fee | 29 |
eta | Delivery estimate, when supplied | 30 |
cuisine | Cuisine tags | Chicken,Pizza |
address | Public merchant address, when available | {"full": null} |
directoryOnly | Directory entry without confirmed details | true |
nameSource | Origin of a directory name | url_slug |
detailStatus | Directory detail result | route_shell |
Menu products: menuItem
| Field | Description | Example |
|---|---|---|
itemId | Menu product identifier, when supplied | ITEM001 |
name | Product name | Chicken rice |
section | Menu section | Rice meals |
price | Published list price | 120 |
currency | Currency code | PHP |
restaurantName | Parent restaurant | Example Kitchen |
restaurantCity | Restaurant's address city, not delivery city | Makati |
GrabMart directory products: martItem
| Field | Description | Example |
|---|---|---|
itemId | Product identifier | SGITE2023041907043919153 |
slug | Product URL text | pokka-green-tea |
url | Public product link | https://mart.grab.com/sg/en/item/pokka-green-tea/SGITE2023041907043919153 |
lastmod | Sitemap publication date, not price-change time | 2026-10-01 |
GrabMart product details: mart_item_detail
| Field | Description | Example |
|---|---|---|
name | Product name | Green tea |
description | Published product description | Bottled green tea |
priceV2 | Structured list price | {"amountInMinor": 250} |
discountedPriceV2 | Structured discounted price | {"amountInMinor": 220} |
available | Availability supplied by Grab | true |
barcode | Product barcode, when supplied | null |
Categories: category
| Field | Description | Example |
|---|---|---|
id | Category identifier | pizza |
name | Category name | Pizza |
url | Category or restaurant-list link | https://food.grab.com/ph/en/cuisines/pizza |
Promotions: promo
| Field | Description | Example |
|---|---|---|
merchantId | Associated merchant | 2-C2EYTY3AJ6NZKA |
name | Published promotion text | Delivery offer |
Labels: label
| Field | Description | Example |
|---|---|---|
merchantId | Associated merchant | 2-C2EYTY3AJ6NZKA |
name | Published label text | Popular |
Contact fields such as phones, emails, and web can be empty. leadAbsences explains missing information; 未验证 means unverified, not confirmed absent. The city field describes the requested delivery location, not necessarily the merchant's address.
How to scrape Grab
- Open Grab Scraper in Apify Console.
- Choose
countryCodeand fill a target such askeyword. - Set
maxResultsto 3 for a small first run. - Click Start and wait for completion.
- Open the dataset and download rows, or read them through the API.
Empty input starts a billed example search for pizza in ph, capped at 3 rows. With mode: "auto", one target selects its matching mode. When several targets are filled, priority is startUrls, restaurantUrl, merchantId, itemId, chainName, cuisineSlug, then keyword.
Search
Use keyword for restaurant discovery. Explicit search without a keyword searches for pizza.
Restaurant
Use restaurantUrl or merchantId. Enable includeMenuItems for separate menu rows; the merchant row also counts.
GrabMart feed
Choose mart and optionally a grocery keyword. It returns merchants, not a complete product catalog.
GrabMart product directory
Choose mart_items for product IDs and URLs. Directory rows do not promise prices or availability.
GrabMart product detail
Choose mart_item with a complete product link in restaurantUrl, or itemId plus itemSlug. Preserve merchant information from the full link when present.
GrabMart merchant directory
Choose mart_merchants for published shop entries. Listing a shop does not prove current deliverability.
Chain
Fill chainName for branch listings and public addresses when supplied.
Cuisine
Fill cuisineSlug; optionally add cuisineId. Explicit cuisine can also use keyword as its slug.
Recommended
Choose recommended for merchants around your delivery location. No keyword is required.
Start URLs
Fill startUrls with supported restaurant, cuisine, or GrabMart links. Restaurant links can include menu rows.
Discover categories
Choose discoverCategories for category shortcuts in the selected market. No target is required.
GrabFood directory
Choose directory and optionally sitemapCity. Names derived from URLs are marked nameSource: "url_slug". modifiedSince filters sitemap dates inclusively. enrichDetails checks up to maxEnrich pages; pages without merchant details remain directoryOnly: true.
What to fill in
| Field | What to enter | Default |
|---|---|---|
mode | Collection mode, or automatic selection | auto |
countryCode | One supported market code | ph |
keyword | One search phrase | Empty; example pizza |
startUrls | List of supported Grab links | Empty |
restaurantUrl | Restaurant link; product link for mart_item | Empty |
merchantId | Merchant identifier | Empty |
merchantSlug | Merchant text from its URL | Empty |
itemId | GrabMart product identifier | Empty |
itemSlug | Product text from its URL | Empty |
chainName | Chain name or slug | Empty |
cuisineSlug | Cuisine slug | Empty |
cuisineId | Optional cuisine identifier | Empty |
maxResults | Rows per input, from 1 to 500 | 70; form example 3 |
city | Delivery city slug | Market's main city |
latlng | Delivery pin; overrides city | Empty |
businessType | ALL, FOOD, or MART for search/recommended | ALL |
lang | Language path supported by the market | en |
includeMenuItems | Separate menu rows on restaurant pages | false |
maxMenuItemsPerRestaurant | Menu rows per restaurant | 25 |
expandBranches | Additional branch merchant rows | false |
emitCuisines | Additional cuisine category rows | false |
emitPromoLabels | Additional promotion and label rows | false |
pageSize | Merchants per page, from 1 to 32 | 32 |
cursor | Previous RUN_SUMMARY.nextCursor object | Empty |
sitemapCity | Published sitemap city slug | Empty |
sitemapShard | Zero-based sitemap file index | 0 |
sitemapOffset | Zero-based entry offset | 0 |
sitemapMaxShards | Maximum sitemap files, from 1 to 5 | 1 |
modifiedSince | Inclusive sitemap date, YYYY-MM-DD | Empty |
enrichDetails | Check directory merchant details | false |
maxEnrich | Directory detail pages to check | 5 |
useSeedPool | Use previously discovered URLs for detail modes | false |
seedCount | Previously discovered URLs to select | 3 |
seedFamily | mart_items, mart_merchants, or food_merchants | Mode-dependent |
seedPoolMaxAge | Maximum age of saved URLs in seconds | 86400 |
persistSeen | Skip previously delivered rows for the same query | false |
proxyCountry | Optional country hint for chain requests | Market country |
Search example
{"keyword": "pizza", "countryCode": "ph", "maxResults": 3}
Restaurant example
{"mode": "restaurant", "countryCode": "ph", "merchantId": "2-C2EYTY3AJ6NZKA", "includeMenuItems": true, "maxResults": 3}
GrabMart feed example
{"mode": "mart", "countryCode": "my", "city": "penang", "keyword": "grocery", "maxResults": 3}
GrabMart product directory example
{"mode": "mart_items", "countryCode": "sg", "sitemapCity": "singapore", "maxResults": 3}
GrabMart product detail example
{"mode": "mart_item", "countryCode": "sg", "itemId": "SGITE2023041907043919153", "itemSlug": "pokka-green-tea", "maxResults": 1}
GrabMart merchant directory example
{"mode": "mart_merchants", "countryCode": "sg", "sitemapCity": "singapore", "maxResults": 3}
Chain example
{"chainName": "mcdonalds", "countryCode": "id", "maxResults": 3}
Cuisine example
{"cuisineSlug": "pizza", "countryCode": "ph", "city": "cebu", "maxResults": 3}
Recommended example
{"mode": "recommended", "countryCode": "ph", "maxResults": 3}
Start URLs example
{"startUrls": ["https://food.grab.com/ph/en/cuisines/pizza"], "maxResults": 3}
Discover categories example
{"mode": "discoverCategories", "countryCode": "mm", "maxResults": 3}
GrabFood directory example
{"mode": "directory", "countryCode": "sg", "sitemapCity": "singapore", "maxResults": 3}
maxItems and limit are aliases for maxResults; q, query, and searchTerm are aliases for keyword. Close misspellings such as keywrd are corrected; other unknown fields are ignored with a note. Invalid optional filters can also be ignored.
Every run writes its interpretation to INPUT_REPORT in the default key-value store. Invalid coordinates fail before rows are charged: INVALID_INPUT: latlng — write latitude,longitude, for example 14.5547,121.0244. A start fee can still apply. Examples show input format, not guaranteed current inventory.
Output example
Illustrative merchant row; values depend on the selected location and source.
{"rowType": "restaurant","itemType": "merchant","businessType": "FOOD","merchantId": "2-C2EYTY3AJ6NZKA","name": "Example Kitchen","title": "Example Kitchen","countryCode": "PH","url": "https://food.grab.com/ph/en/restaurant/example/2-C2EYTY3AJ6NZKA","rating": 4.6,"deliveryFee": 29,"phones": [],"emails": [],"scrapedAt": "2026-10-24T08:00:00Z"}
Export the dataset as JSON, CSV, Excel, XML, RSS, or an HTML table.
Why use this Grab scraper?
- Pay per delivered row. Attempted pages are not dataset rows.
- Keep delivered data. Rows already written remain available after a stop. Collection still in progress is not guaranteed to be saved.
- Inspect problems.
RUN_SUMMARYincludes notes and warnings; failures can also writeERROR_SUMMARY. - Avoid invented details. Missing source fields stay empty; URL-derived names are identified.
- Several inputs. Submit multiple links through
startUrlsrather than creating a run per link. - No proxy setup. You do not need to set up proxies.
How much does it cost to scrape Grab?
Pricing is pay-per-event. Platform usage is included in these prices. Start events cost $0.005 each, with one event per GB of allocated memory and a minimum of one. Default memory is 1024 MB, so one default-memory start costs $0.005.
| Apify plan | Start at 1024 MB | Price per row | Price per 1,000 rows |
|---|---|---|---|
| Free | $0.005 | $0.003 | $3.00 |
| Starter | $0.005 | $0.003 | $3.00 |
| Scale | $0.005 | $0.0026 | $2.60 |
| Business | $0.005 | $0.0022 | $2.20 |
| Platinum | $0.005 | $0.002 | $2.00 |
| Diamond | $0.005 | $0.0016 | $1.60 |
maxResultsapplies per input, defaults to 70, and accepts up to 500. Larger requests are collected in parts of 70.- All row types share the limit, including optional menu, branch, category, promotion, and label rows.
- Free Apify plan limits are 50 rows per run and 3 runs of this Actor, set by the publisher.
- The whole run stops at Maximum cost per run (
maxTotalChargeUsdin the API).
Example: one default-memory run delivering 3 rows on the Free plan costs 3 × $0.003 + $0.005 = $0.014.
What happens when the run timeout is too short
Some Grab collections, such as several startUrls with includeMenuItems: true or a large maxResults, can take longer than the run timeout you chose. In that case the run does not fail. It ends early with the status message "Queued on the collection backend; this run will resume automatically when results are ready (about N s)." and shows as ABORTED for a while.
When the results are ready, the same run starts again by itself, reports "Resumed: delivering N rows.", writes the rows to the same dataset and finishes as SUCCEEDED. Rows that were already delivered are skipped, so no row is delivered or charged twice. You do not need to start another run.
- This can happen at most 3 times per run. To avoid it, keep the default timeout of 3600 seconds.
- The synchronous API endpoints (
run-sync,run-sync-get-dataset-items) wait at most 300 seconds and can return an empty dataset while the run is paused. For larger jobs, start the run asynchronously and read the dataset after the run reaches SUCCEEDED, or use a webhook on the "succeeded" event.
Use with AI agents and the API
Apify MCP server
Add the Actor to a remote MCP client such as Claude, ChatGPT, Cursor, or VS Code:
https://mcp.apify.com?tools=lentic_clockss/grab-scraper
Sign in with Apify using OAuth, or send Authorization: Bearer <YOUR_APIFY_TOKEN>. The tool returns run and dataset IDs; read rows with get-dataset-items. Clients without remote support can use npx @apify/actors-mcp-server --tools lentic_clockss/grab-scraper with APIFY_TOKEN.
Example prompt: “Find 3 pizza restaurants in Makati, Philippines, with Grab Scraper. Return merchant IDs, names, ratings, and URLs.”
Apify API
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("lentic_clockss/grab-scraper").call(run_input={"keyword": "pizza", "countryCode": "ph", "maxResults": 3})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('lentic_clockss/grab-scraper').call({keyword: 'pizza', countryCode: 'ph', maxResults: 3});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Over HTTP, send the input to POST https://api.apify.com/v2/acts/lentic_clockss~grab-scraper/runs with an Authorization: Bearer <YOUR_APIFY_TOKEN> header. After completion, read GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json.
Integrations
Use the Integrations tab for Google Sheets, Make, Zapier, n8n, Slack, Airtable, or webhooks. Schedule repeated collection with Apify Schedules.
FAQ
Is it legal to scrape Grab?
This Actor collects publicly accessible data. You are responsible for complying with Grab's terms and applicable data-protection laws. Processing personal data requires a lawful basis.
Why did my run end as ABORTED?
A cancelled run can show ABORTED. Check its status message and log for the reason. Already delivered rows remain in its dataset; do not assume an aborted run completed collection.
How many results can I get?
Request 1–500 rows per input. Source availability, the shared row limit, free-plan limits, and your maximum charge can reduce delivery. A requested count is not a guarantee.
Why are some fields empty?
Grab does not expose every field on every page. Directory entries are especially sparse. A URL-derived name is not a verified display name; empty contact fields do not prove contacts do not exist.
Can I scrape menus?
Yes. Use restaurant or restaurant links in startUrls with includeMenuItems: true. Listing searches do not fetch menus through this switch.
Can I continue a longer collection?
Pass RUN_SUMMARY.nextCursor as cursor with the same mode, market, location, and query. Keep directory filters unchanged. Deduplicate IDs across runs because live listings can change.
Is this an official Grab API?
No. This is an unofficial scraper, not affiliated with Grab. It does not place orders or access private accounts.
Are member prices or Taiwan supported?
No. GrabUnlimited and other login-only prices, Taiwan, rides, and corporate brand pages are outside this Actor's scope.
Limitations
- Market selection does not guarantee every mode, city, or language has data.
- Directory membership does not confirm opening hours, stock, or delivery availability.
directoryignores keyword, delivery-location, and menu settings; it does not supportbusinessType: "MART".- Delivery-pin coordinates are not merchant coordinates. Public phone, email, person, and website coverage is not guaranteed.
- Saved-URL detail selection needs recent discovered URLs. An empty or stale collection can fail.
- Source failures are not reported as confirmed empty results. Read warnings when a run returns fewer rows than requested.
Related scrapers
More food delivery and grocery scrapers from the same publisher:
- iFood Scraper
- PedidosYa Scraper
- Uber Eats Scraper
- Deliveroo Scraper
- Foodora Scraper
- Foodpanda Scraper
- DoorDash Scraper
- Rappi Scraper
Browse all of our scrapers at apify.com/lentic_clockss.
Support
Report problems or request a field through the Issues tab of this Actor's page. Include the run ID and the input you used.