DoorDash Scraper at a glance
DoorDash Scraper is a ready-to-run Apify actor from abotapi for collecting ecommerce data. Its documented output includes store id, name, change type (incremental mode), url 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
- 23 options
- Run success
- 97.2% of completed public runs in the last 30 days
Extract structured doordash.com data at scale. Search by keyword or paste store URLs to get store details, ratings, price tier, location, full menus, contact info, opening hours, review insights, star-rating breakdowns, and Google rating data.
What DoorDash Scraper can do
- Two ways to find stores. Run keyword searches localized to a city, or paste store links or bare numeric IDs directly. No need to build URLs by hand.
- One rich record per store. Meta (name, rating, price tier, cuisines, geo) is always included; menu, contact info and reviews are added on top when you turn them on.
- The exact numeric rating count. Not a rounded bucket like "500+": the real count, plus the full 1 to 5 star histogram, review theme highlights and the Google rating aggregate. The written review text itself is capped at roughly the 5 most recent public reviews per store; see the reviews note under Input Parameters.
- Full menu with markdown detection. Item names, prices, photos and dietary tags, with isOnSpecial, savingsAmount and discountPercent derived from the store's own listed price and strikethrough price.
- Pay only for what you turn on. Menu, contact info and reviews all come from one store-detail fetch, billed as a single surcharge per returned store no matter how many of the three you enable; a lean search with all three off skips that fetch and surcharge entirely.
- Opening hours by day, phone number, website and precise latitude and longitude for every enriched store.
Choose what to collect
These inputs let you configure DoorDash Scraper - Menus, Prices, Reviews & Ratings. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring · required | How to discover stores. 'search' runs keyword searches; 'url' takes store links or IDs directly. |
searcharray | Keywords to search on DoorDash (e.g. "pizza", "sushi", "McDonald's"). One search runs per term. Only used when mode = search. |
storeTypestring | Limit search to a store category. 'restaurant' excludes convenience/grocery stores. Only used when mode = search. |
ratedOnlyboolean | Only return stores that have a customer rating (drops unrated / very low rated stores). Only used when mode = search. |
dealsOnlyboolean | Only return stores currently offering deals/offers. Only used when mode = search. |
minRatingstring | Only return stores rated at least this many stars using DoorDash's rating filter. When set, this overrides the 'Well-rated only' filter. Search mode only. |
fastDeliveryOnlyboolean | Only return stores with delivery estimates of 30 minutes or less for your location, using DoorDash's 'Under 30 min' filter. Search mode only. |
Show 16 more inputs
| Input | What it controls |
|---|---|
urlsarray | DoorDash store links or bare numeric store IDs. Supported link shapes: the canonical page (with or without a name slug, with any query string), a specific menu (/store/-//), /convenience/store//, the store's reviews page (/reviews/store//), and any locale-prefixed variant (/en-CA/, /fr-CA/, /es-US/, /en/...) of those. Links copied from page source with & or ' escapes are decoded. Multiple supported. A business/chain page (/business/-/ or /b//-/), a category, dish, city or search-results page, a drd.sh short link or a non-DoorDash link has no single store id and is skipped with a warning in the log -- open an individual store link instead. If you leave this untouched in URL mode, the example links shown here are scraped. Only used when mode = url. |
includeMenuboolean | Fetch the full menu (categories + items with price, image, dietary tags). Requires a store-detail fetch per store. |
includeBusinessboolean | Fetch phone number, website and opening hours by day. |
includeReviewsboolean | Fetch reviews preview (up to ~5 recent public reviews), the full 1-5 star histogram, theme highlights and Google rating aggregate. |
maxReviewsinteger | Maximum written reviews kept in reviews.items for each store when 'Include reviews' is on. DoorDash itself serves at most about 5 recent public reviews per store to a logged-out visitor, so the default of 20 keeps everything it serves; lower it to keep fewer. 0 = no written reviews (the star histogram, review counts, themes and Google rating are still included). Never adds a charge: reviews ride on the store's single detail fetch. |
maxStoresinteger | Maximum number of stores to return across all searches/URLs. 0 = no limit. |
maxPagesinteger | Optional bound on result pages walked per search query (50 stores per page). Leave empty to walk every result page -- the run already stops at the Max stores cap, so this only matters if you also want to limit page depth. Only used when mode = search. |
resumeFromRunIdstring | Optional: paste a previous run ID (or dataset ID) from this actor. Stores already collected there are skipped, so this run only returns new ones. |
incrementalModeboolean | Turn this on for daily or recurring monitoring. The first run returns all matching stores as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED stores. Turn on "Emit unchanged" or "Emit expired" below to also see stores that did not change or that disappeared. |
stateKeystring | Optional. 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 search/URLs and filters you set (Max stores/Max pages do not affect this key). |
emitUnchangedboolean | Off by default. Turn on to also return stores 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 need the full snapshot every run. |
emitExpiredboolean | Off by default. Turn on to also return stores 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 stores/Max pages capped the run, and not on a Resume run. |
ignoreFieldsForChangesarray | Optional. Field names to exclude from UPDATED change detection (in addition to the fields that never count: nextOpenTime/nextCloseTime/asapAvailable/searchEtaMinutes and the currently-served menuId/menuName/menuHours tick with the clock or live load rather than reflecting a real store change, and reviews.items.reviewerDescription describes the reviewer, not the store). Accepts a top-level field name (e.g. "rating") or a dotted path into a nested field (e.g. "reviews.items"). Use this if a field in your setup turns out to be noisy. |
mcpConnectorsarray | Optionally 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). |
notionParentPageUrlstring | URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListingsinteger | Cap 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.
storeIdStore IDnameNamechangeTypeChange type (incremental mode) (text)urlURL (link)ratingRatingratingCount# RatingsratingCountDisplayRating count displaypriceTierPricepriceRangePrice level (1-4)cuisinesCuisines (array)cityCitystateStateShow 88 more fields
latitudeLatlongitudeLngphonePhonewebsiteWebsite (link)deliveryFeeDelivery feeetaMinutesETA (min)pickupEtaMinutesPickup ETA (min)isSponsoredSponsoredisDashpassDashpass partnermenuItemCount# Menu itemsreviewCount# ReviewschangedFieldsChanged fields (incremental mode) (array)firstSeenAtFirst seen (incremental mode) (date)lastSeenAtLast seen (incremental mode) (date)descriptionDescriptionstoreBioStore bioisConvenienceIs convenience storeisShippingOnlyShipping onlycurrencyCurrencyoffersDeliveryOffers deliveryoffersPickupOffers pickupoffersCateringOffers cateringoffersGroupOrderOffers group orderoffersSchedulingOffers schedulingadditionalImagesAdditional images (array)coverImageUrlCover image URL (link)coverSquareImageUrlCover square image URL (link)businessHeaderImageUrlBusiness header image URL (link)photoCountTextPhoto countbusinessIdBusiness IDbusinessNameBusiness namebusinessLinkBusiness link (link)businessTagsBusiness tags (array)distanceDistancestreetStreetdisplayAddressDisplay addressdistanceMilesDistance (miles)nextOpenTimeNext open timenextCloseTimeNext close timesubmarketIdSubmarket IDasapAvailableOpen now (ASAP delivery)pickupAvailablePickup available (search)badgesBadges & offers (array)searchEtaMinutesETA to search location (min)timezoneTimezonecountryCountryoffersCannabisOffers cannabisreviewCountDisplayReview count displaymenuIdCurrent menu IDmenuNameCurrent menumenuHoursCurrent menu hoursmenusAll menus (array)menuMenu details (json)reviewsReview details (json)contactContact details (json)scrapedAtScraped at (date)storeNameStoreidReview IDreviewerReviewerstarsStarstextReviewisVerifiedVerifiedreviewedAtReviewed atsourceSourceratingTagRating tagexperienceExperiencetaggedItemsTagged items (array)taggedItemIdsTagged item IDs (array)markedUpReviewTextMarked-up review textreviewerDescriptionReviewer descriptionreviewerProfileImageUrlReviewer photo (link)photosReview photos (array)categoryCategorypricePricestrikethroughPriceWas-pricepriceCentsPrice (cents)isOnSpecialOn specialsavingsAmountSavingsdiscountPercentDiscount %imageUrlImage URL (link)ratingPctItem rating %calloutCalloutservingSizeServing sizequickAddEligibleQuick-add eligibledietaryTagsDietary tags (array)hoursHours (array)hoursDescriptionHours descriptionaddressAddress (object)Example output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"storeId": "1673363",
"name": "Sample Pizza Place",
"url": "https://www.doordash.com/store/1673363/",
"rating": 4.5,
"ratingCount": 1234,
"priceTier": "$$",
"cuisines": [
"Pizza",
"Italian"
],
"city": "Sampleton",
"state": "CA",
"latitude": 25,
"longitude": 55,
"etaMinutes": 25,
"deliveryFee": "$0 delivery fee",
"isSponsored": false,
"isDashpass": true,
"phone": "+10000000000",
"website": "https://example.com",
"contact": {
"phone": "+10000000000",
"website": "https://example.com",
"hours": [
{
"day": "MONDAY",
"slots": [
"10 AM - 10 PM"
]
}
],
"address": {
"street": "1 Sample St",
"city": "Sampleton",
"state": "CA"
}
},
"menu": {
"categories": [
{
"name": "Most Ordered",
"numItems": 6
}
],
"items": [
{
"name": "Sample Item",
"price": "$7.99",
"strikethroughPrice": "$9.99",
"isOnSpecial": true,
"savingsAmount": 2,
"discountPercent": 20,
"dietaryTags": [
"Vegetarian"
]
}
],
"popularItems": [
{
"name": "Sample Item",
"price": "$9.99",
"strikethroughPrice": "",
"isOnSpecial": false,
"savingsAmount": null,
"discountPercent": null
}
]
},
"menuItemCount": 42,
"reviews": {
"avgRating": 4.5,
"numRatings": 1234,
"numReviews": 18,
"histogram": {
"1": 5,
"2": 3,
"3": 4,
"4": 20,
"5": 90
},
"items": [
{
"reviewer": "Jane D",
"stars": 5,
"text": "Sample review text.",
"isVerified": true
}
],
"themes": [
{
"label": "Great value",
"count": 12,
"sentiment": "POSITIVE"
}
],
"google": {
"avgRating": 4.4,
"numRatings": 500
}
},
"reviewCount": 18
}Ways to use this data
- Food delivery market research: compare pricing tiers, delivery fees and ETAs for a cuisine across a city or a whole metro area.
- Local business directories: republish store contact details, opening hours and menus for a region.
- Competitive intelligence for restaurants: track a competitor's menu prices, specials and rating trends over time with Incremental mode.
- Data science and demand modeling: build historical datasets of ratings, reviews and menu changes for machine learning.
- Lead generation and outreach: find stores that are missing a website or offering deals right now.
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 DoorDash Scraper return?
The documented output for DoorDash Scraper includes store id, name, change type (incremental mode), url, rating, # ratings, rating count display and price. Availability of each field depends on the source page and the selected mode.
How much does DoorDash 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.
Can I get only new or changed stores on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated stores, and unchanged ones are suppressed and not billed unless you turn on Emit unchanged.
What is the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues one specific interrupted or previous run: paste its run or dataset id once and this run skips what it already collected. Incremental mode is for running the exact same search or URLs again and again on a schedule; the actor remembers the previous run itself, with nothing to paste. Turning both on together for a search that already has saved incremental state is rejected before any scraping happens; pick one. Also note that REAPPEARED only ever appears for a store a previous run already marked EXPIRED, which itself requires emitExpired to have been on for that campaign.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
