DoorDash Store & Menu Scraper avatar

DoorDash Store & Menu Scraper

Pricing

from $1.33 / 1,000 results

Go to Apify Store
DoorDash Store & Menu Scraper

DoorDash Store & Menu Scraper

Extract a DoorDash restaurant's full menu with prices, plus its street address, city and cuisine category. Reads the page's structured data, so every section and item comes back with its price. HTTP-only, no account, no browser.

Pricing

from $1.33 / 1,000 results

Rating

0.0

(0)

Developer

Farhan Febrian Nauval

Farhan Febrian Nauval

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Extract a DoorDash restaurant's full menu with prices, plus its street address, city and cuisine category. HTTP-only, no account, no browser.

Input

FieldTypeDefaultDescription
storesarrayrequiredStore URLs or bare numeric store ids
maxProfilesinteger6TLS profiles to try before giving up on a store
maxConcurrencyinteger3Stores in parallel
proxyConfigurationobjectRESIDENTIALResidential strongly recommended

The slug in a store URL is decoration. /store/panda-express-san-francisco-303380/ and /store/rosalind-coffee-company-garland-303380/ both resolve to store 303380 — only the trailing number is identity. The actor extracts it and rebuilds a canonical URL.

Output

{
"_input": "…/store/rosalind-coffee-company-garland-303380/",
"_source": "S1-jsonld",
"_scrapedAt": "2026-09-07T02:03:40Z",
"_tlsProfile": "chrome124", // which profile got through
"storeId": "303380",
"name": "Rosalind Coffee Company",
"address": "107 N 6th St, Garland, TX 75040, USA",
"city": "Garland",
"cuisine": "Coffee",
"menuSectionCount": 4,
"menuItemCount": 22,
"menuSections": [
{ "name": "Not Coffee", "itemCount": 8, "items": [
{ "name": "Matcha", "description": null,
"price": "$4.75", "priceAmount": 4.75, "priceCurrency": "USD" }
]}
],
"faqs": [ { "question": "…", "answer": "…" } ],
"breadcrumbs": [ { "position": 1, "name": "Home", "item": "/" } ]
}

Every item in testing came back priced — 57 of 57 across three stores.

How it works

All of it comes from the page's JSON-LD, which carries more than the rendered page conveniently shows: a Menu block with every section and item, a FAQPage whose answers contain the street address, and a BreadcrumbList giving the city and cuisine DoorDash files the store under.

Cloudflare: the TLS ladder is the normal path, not a fallback

No single TLS profile is reliable here. Measured over six independent rounds from Apify residential, the winning profile changed almost every time — safari180 twice, chrome124 twice, chrome131 once, and one round where none of six landed. A fixed profile fails often enough to look like an outage.

So the actor rotates a six-profile ladder, each rung on its own session and its own exit IP (Cloudflare decides per connection, so reusing a session would make the attempts correlated). That took the hit rate to 5 of 6 rounds, and 2 of 2 on a re-run.

A block is detected from a positive data marker — the presence of the JSON-LD Menu block — not from the status code, because Cloudflare serves some interstitials as a 200 with a large body.

Prices come back in two different spellings

The same store returned "$4.75" on one fetch and "USD 4.75" (ISO code, non-breaking space) on the next, minutes apart. The raw string is passed through unchanged, and priceAmount (float) and priceCurrency are added alongside it so you never have to handle both.

Parsing respects separator conventions: 1,234.56 and 1.234,56 are both 1234.56, and 3,50 is 3.50 — whichever of . or , comes last is the decimal separator. Getting that backwards inflates a price 100-fold without any error, which is why it is unit-tested rather than eyeballed.

Known limits

LimitDetail
No ratings or reviewsNot present in the structured data on this surface
No opening hoursNot in the JSON-LD; the FAQ answers sometimes mention delivery/pickup availability
Deleted vs blockedDoorDash does not 404 a missing store — it serves a challenge, so a bad id reports blocked rather than not_found
Cost per storeA store can take several requests when the first profiles are challenged