DoorDash Stores, Menus & Reviews
Pricing
from $0.42 / 1,000 store scrapeds
DoorDash Stores, Menus & Reviews
Every DoorDash store in a city with rating, review count, delivery fee, ETA, distance and address, plus each store full menu with prices and item ids, and its customer reviews.
Pricing
from $0.42 / 1,000 store scrapeds
Rating
0.0
(0)
Developer
Superslow Sloth
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Give it a US, Canadian or Australian city and get every DoorDash restaurant DoorDash lists there — rating, review count, delivery fee, delivery estimate, distance and full postal address. Switch the mode and the same input returns each store's whole menu with prices, descriptions and DoorDash item ids, or its customer reviews with the text, the stars, the date and the reviewer's name.
No account, no cookies, no login.
Three modes, one dataset
| Mode | One row is | Where it comes from |
|---|---|---|
| Stores | a restaurant | one request for the whole city |
| Menu items | a dish | one request per store |
| Reviews | a customer review | one request for the whole city |
Rows from every mode share store_id, store_name and store_url, so a
dataset that holds more than one mode still joins on the store.
Input
| Field | Notes |
|---|---|
mode | stores, menu-items or reviews. |
location | "San Francisco, CA", "Austin, TX", or a doordash.com/food-delivery/... URL. Not a bare zip code — see below. |
storeUrls | Specific stores instead of a city search. Overrides location. |
cuisine | Asks DoorDash for its own cuisine page for the city — mexican, sushi, fast food. A different, usually longer list, not a filter. |
searchTerm | Keeps only stores whose name or cuisine tags contain this text. Applied here, not sent to DoorDash. |
maxResults | Row cap. |
includeStoreStatus | Stores mode only. Adds one request per store to fill is_open. |
Why a zip code is refused
DoorDash keys its public city pages on a city and a state.
/food-delivery/94110-restaurants/ is a redirect to DoorDash's country index,
which renders no store list at all (measured 2026-08-25). A zip is therefore
rejected with that explanation before the run starts, rather than turning into
a paid run that returns nothing.
Why the search term is applied here
DoorDash's own store search refuses a client that has not picked a delivery
address — it renders with no store feed. There is no cold search endpoint to
forward a term to, so searchTerm narrows what the city page returned. To
widen the pool before narrowing it, set cuisine as well.
What one row contains
Stores
| Field | Notes |
|---|---|
store_id | DoorDash's numeric id, as a string. It is an identifier, not a quantity — kept as text so a spreadsheet cannot round it. |
store_name, store_url | |
cuisine_tags | DoorDash's own labels — ["Mexican", "Burritos"]. DoorDash occasionally puts a price bucket ("$$$") here instead of a cuisine; that is what it publishes and it is not corrected. |
rating, review_count | Null on a row that came from a store URL — see below. |
delivery_fee | The string DoorDash displays ("$0 delivery fee"), not a number: it is often a promotion rather than a price, and parsing it to a float would throw that away. |
delivery_time_minutes, delivery_time_display | A number where DoorDash gives one, and its own text where it gives a range ("32 - 42 min"). |
distance | From the searched location ("1.8 mi"). Null on a store-URL row: there is no consumer location to measure from. |
address, city, state, latitude, longitude | |
price_range | "$$", "$$$". Only the store page reports it. |
is_open | Accepting delivery orders right now. Only the store page reports this — null on a city search unless includeStoreStatus is on. |
offers_pickup, is_sponsored | is_sponsored marks paid placement in the city feed. |
Menu items: item_id, item_name, item_description, price,
price_display, category (the menu section).
price is filled only when DoorDash's price slot holds one plain amount.
DoorDash reuses that slot for bundle offers — "2 for $17.79",
"Buy 1, Get 1 Free" — and neither number in those is the item's price, so
price is null and price_display keeps DoorDash's own text.
Reviews: review_id, review_rating, review_text, review_date,
reviewer_display_name, review_source.
Nulls are real
A field DoorDash did not report is null, never 0 and never false. The two
that catch people out:
- The city feed carries no open/closed flag at all, so
is_openis null there.falsewould say DoorDash told us the store was shut. - The store page zeroes its rating block for a client with no delivery
address. A
0.0rating on a restaurant with 1,362 reviews would be a lie, so it is published as null and the rating comes from the city feed instead.
Both are why the stores mode is worth running from a city even when you already know the store: the city feed is the richer of the two sources.
review_id is derived, not DoorDash's
DoorDash publishes no review identifier. review_id is a stable digest of the
store, the reviewer, the date and the text: identical on every run and unique
within a store, which is what deduplication needs. It is not a DoorDash id and
cannot be handed back to DoorDash.
item_id can be null
The store page publishes its menu twice — as the rendered menu feed, which
carries item ids, and as schema.org, which does not. Where the feed arrives
empty the schema.org menu is used instead, and those rows carry null ids
rather than invented ones. Names, descriptions, prices and sections are the
same either way.
Ceilings worth knowing before you set maxResults
A DoorDash city page lists roughly 40–50 stores and up to two published reviews
per store. So one location cannot yield much beyond ~50 store rows or ~100
review rows however high the cap is set. Add a cuisine to reach a different
page, or run several locations.
Proxy
Residential pinned to the US, and neither half is optional. DoorDash answers a datacenter address with HTTP 403.
Measured on the Apify platform, 2026-08-25: an unpinned residential run was
refused 403 on all four attempts across four exit addresses. The same input
with apifyProxyCountry: "US" returned 25 stores on the first try. DoorDash
operates in the US, Canada and Australia only, so an exit anywhere else is
refused on sight — set CA or AU for those storefronts.
An HTTP 200 whose body carries no page payload is treated as a block and retried on a fresh address, not reported as a store with no data.
Pricing
Pay per event: a small actor-start fee, plus one event per row named for what
the row is (store-scraped, menu-item-scraped, review-scraped). The start
fee is charged only after the input parses, so a run that fails on a typo costs
nothing.