# DoorDash Scraper (`datascrapers/doordash-scraper`) Actor

Delivers structured DoorDash store, menu, product, collection, and deal records for a delivery location, queried by search term, store URL, or collection URL.

- **URL**: https://apify.com/datascrapers/doordash-scraper.md
- **Developed by:** [Farhan Ali](https://apify.com/datascrapers) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**DoorDash Scraper** creates a structured dataset of DoorDash store, menu, product, collection, and deal records for a US delivery location. Each dataset item can include the item or store name, price, description, category, rating, merchant identifiers, and the resolved delivery location. Query the source using a search term, a DoorDash store or collection URL, or both, control the result limit with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, or XML.

### Dataset at a glance

| Property | Value |
|---|---|
| Source | doordash.com |
| Record unit | One store, menu/retail product, product detail, store collection, or deal item |
| Input methods | Delivery location, search queries, DoorDash start URLs |
| Main identifiers | `storeId`, `productId`, `collectionId`, `url` |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, XML |
| Update model | Fresh records per Actor run |
| Pricing | Pay per event, from $1.50 per 1,000 events |

### Coverage and available records

The Actor resolves records for the delivery location you supply (address, city, or postal code) and returns the following record types, controlled by the extraction toggles:

- **Products** (`scrapeProducts`) — menu items and retail/grocery products. `scrapeProductDetails` switches to a fuller product payload.
- **Store information** (`scrapeStoreDetails`) — store address, ratings, hours-related flags, and delivery/pickup options.
- **Store collections** (`scrapeStoreCollections`) — menu categories and grocery/retail collections. Collection URLs always extract the opened collection.
- **Deals** (`scrapeDeals`) — featured deal products from the grocery and retail deal surfaces at the delivery location.

Location-specific availability means prices and search results are tied to the resolved delivery pin. A US residential proxy is used by default; results are not currently collected for non-US delivery locations.

### Data dictionary

| Field | Type | Nullable | Description | Example |
|---|---:|---|---|---|
| `recordType` | string | No | `product`, `product-details`, `store`, or `store-collection`; drives pay-per-event billing | `product` |
| `name` | string | No | Menu item, product, store, or collection title | `Big Mac` |
| `description` | string | Yes | Item description when exposed | `Two beef patties...` |
| `price` | string | Yes | Localized price string | `$5.99` |
| `storeName` | string | Yes | Merchant name for the record | `McDonald's` |
| `storeId` | string | Yes | DoorDash store identifier | `24508264` |
| `productId` | string | Yes | Product identifier | `104892...` |
| `collectionId` | string | Yes | Collection identifier | `12345` |
| `category` | string | Yes | Menu category or retail collection name | `Burgers` |
| `rating` | string | Yes | Item- or store-level rating text when exposed | `4.6 (1.2k)` |
| `url` | string | Yes | Canonical DoorDash link for the record | `https://www.doordash.com/...` |
| `imageUrl` | string | Yes | Product or store image | `https://...` |
| `searchQuery` | string | Yes | Search term that discovered the record | `McDonald's` |
| `sourceQuery` | string | Yes | Source query context | `McDonald's` |
| `source` | string | Yes | How the record was discovered (`search`, URL type) | `search` |

Store records (`recordType: store`) additionally include address, phone, website, DashPass flags, delivery/pickup options, and business tags. Collection records describe menu categories or retail aisles.

### Example dataset record

```json
{
  "recordType": "product",
  "name": "Big Mac",
  "price": "$5.99",
  "storeName": "McDonald's",
  "storeId": "24508264",
  "productId": "1048928277",
  "category": "Burgers",
  "url": "https://www.doordash.com/store/24508264",
  "imageUrl": "https://img.cdn4dd.com/...",
  "searchQuery": "McDonald's",
  "source": "search"
}
```

The record above was produced by the input in the next section: a delivery location of `72076` with the search query `McDonald's`.

### Query and input reference

| Input | Type | Required | Default | Accepted values | Description |
|---|---:|---|---|---|---|
| `location` | string | Yes | — | Any address, city, or postal code | DoorDash drop-off location used to resolve search, availability, and prices |
| `searchQueries` | array | No | — | List of search terms | Cuisine, store name, or item searches |
| `startUrls` | array | No | — | DoorDash URLs | Search, store, collection, grocery/retail tab, or product URLs |
| `scrapeProducts` | boolean | No | `true` | `true` / `false` | Extract menu and retail products |
| `scrapeProductDetails` | boolean | No | `false` | `true` / `false` | Fuller product payload; charges `product-details` instead of `product` |
| `scrapeStoreDetails` | boolean | No | `false` | `true` / `false` | Push store information records |
| `scrapeStoreCollections` | boolean | No | `false` | `true` / `false` | Push category/collection records |
| `scrapeDeals` | boolean | No | `false` | `true` / `false` | Extract featured deal products |
| `maxItems` | integer | No | `0` | `0` = unlimited | Maximum records across all types |
| `proxyConfiguration` | object | No | US residential | Apify proxy settings | Proxy configuration for the run |

Minimal request:

```json
{
  "location": "72076",
  "searchQueries": ["McDonald's"]
}
```

Advanced request:

```json
{
  "location": "72076",
  "searchQueries": ["McDonald's"],
  "maxItems": 200,
  "scrapeProducts": true,
  "scrapeStoreDetails": true,
  "scrapeStoreCollections": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

### Retrieve the data through the API

1. Start the Actor with a JSON input containing at least a `location`.
2. Wait for the run to finish, or use the synchronous dataset endpoint for smaller jobs.
3. Read records from the run's default dataset.
4. Paginate or export the dataset.

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("datascrapers/doordash-scraper").call(
    run_input={
        "location": "72076",
        "searchQueries": ["McDonald's"],
        "maxItems": 8,
        "scrapeProducts": True,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["recordType"], item["name"], item.get("price"))
```

Apify's generated API tab documents the equivalent calls for other languages.

### Data quality and record handling

- **Completeness** — fields such as `description`, `price`, `rating`, `category`, and `imageUrl` are conditional on what the source exposes for a given record and location.
- **Record-type-specific fields** — store and collection records carry fields not present on product records.
- **Deduplication** — the Actor does not deduplicate across runs; within a run, a product should appear once per discovery path.
- **Recommended dedup key** — combine `productId`, `storeId`, and the resolved postal code for recurring monitoring.
- **Retry/error behavior** — records that cannot be resolved are skipped; the run continues.
- **Normalization** — prices are localized strings; identifiers are passed through as source values.

### Export and pipeline examples

| Destination | Recommended method | Typical use |
|---|---|---|
| PostgreSQL/Supabase | Dataset API or webhook consumer | Price history and menu intelligence |
| Google Sheets | Apify integration | Competitive menu tracking |
| S3/cloud storage | Scheduled export or integration | Archival snapshots per location |

### Pricing and cost examples

Billing is **pay per event**: each dataset record pushed is one charge, and each event type is priced the same. Platform compute is included in the actor usage fee.

| Event | What counts | Price (no plan discount) |
|---|---|---|
| `product` | Standard menu or retail product listing | $1.50 / 1,000 |
| `product-details` | Fuller product payload | $1.50 / 1,000 |
| `store` | Store profile record | $1.50 / 1,000 |
| `store-collection` | Menu category or retail collection | $1.50 / 1,000 |

| Records | Estimated base cost |
|---:|---:|
| 1,000 | $1.50 |
| 10,000 | $15.00 |
| 100,000 | $150.00 |

Apify plan discounts reduce the per-event rate (for example Gold plans pay about $1.20 per 1,000 events). Estimates depend on the verified pricing model and the extraction toggles you enable.

### Limitations and responsible data use

- Only publicly accessible DoorDash data is returned.
- Availability and pricing are location-specific and tied to the delivery pin you provide.
- Fields may be missing or conditional depending on the store, record type, and region.
- No historical snapshots are stored unless you keep them yourself.
- You are responsible for complying with DoorDash's terms and applicable laws.

### Dataset questions

#### What does one dataset item represent?

One store, product, product detail, store collection, or deal item, depending on the extraction toggles enabled.

#### Which field should I use as a unique identifier?

Use `productId` for products and `storeId` for stores; combine them with the resolved postal code for location-aware deduplication.

#### Are fields nullable or conditional?

Yes. `description`, `price`, `rating`, `category`, and `imageUrl` are conditional on the source, and store/collection records carry fields that product records do not.

#### Can I retrieve the records as CSV or JSON?

Yes. Export the default dataset as JSON, CSV, Excel, or XML, or read it through the Apify Dataset API.

#### How do I paginate large datasets?

Read items through the Dataset API in pages, or export the full dataset once the run completes.

#### What counts as a billable result?

Each record pushed to the dataset is one event charge, at the same per-event rate regardless of record type.

### Related datasets from Data Scrapers

- **[Instacart Scraper](https://apify.com/datascrapers/instacart-scraper)** — grocery and store data from Instacart, for the same competitive assortment and pricing analyses.
- **[Publix Scraper](https://apify.com/datascrapers/publix-scraper)** — grocery product records for price monitoring across delivery regions.
- **[OpenTable Scraper](https://apify.com/datascrapers/opentable-scraper)** — restaurant records with availability for the food-service market.
- **[Yelp Scraper](https://apify.com/datascrapers/yelp-scraper)** — business and rating records that join with DoorDash store identifiers.

### Data Scrapers support

Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.

# Actor input Schema

## `location` (type: `string`):

Address, city, or postal code used as the DoorDash drop-off location (for example "72076" or "Flushing, OH"). Search, store availability, and prices are resolved for this location.

## `searchQueries` (type: `array`):

Cuisine, store name, or item searches (for example Fast Food, McDonald's, burgers). Each query is searched at the delivery location.

## `startUrls` (type: `array`):

Search, store, collection, grocery/retail tab, or product URLs from doordash.com (for example https://www.doordash.com/store/24508264 or a /convenience/store/{id}/collection/{id} URL). Collection URLs always extract that collection.

## `scrapeProducts` (type: `boolean`):

Extract menu items and retail products. Charged as the product event (or product-extra when that option is on).

## `scrapeProductDetails` (type: `boolean`):

Include the fuller product payload and charge the product-extra event instead of the listing product event. Off by default.

## `scrapeStoreDetails` (type: `boolean`):

Push a store record (address, ratings, hours-related flags, delivery options). Off by default. Charged as the store event.

## `scrapeStoreCollections` (type: `boolean`):

Push menu categories and grocery/retail collections. Off by default. Collection URLs still extract the opened collection. Charged as the store-collection event.

## `scrapeDeals` (type: `boolean`):

Also open the grocery and retail deal surfaces for the delivery location and extract featured deal products.

## `maxItems` (type: `integer`):

Maximum number of records to scrape across all types (0 = unlimited).

## `proxyConfiguration` (type: `object`):

Use Apify Residential proxies. DoorDash availability is location-specific.

## Actor input object example

```json
{
  "location": "72076",
  "searchQueries": [
    "McDonald's"
  ],
  "startUrls": [
    {
      "url": "https://www.doordash.com/store/mcdonald's-belmont-24508264/"
    }
  ],
  "scrapeProducts": true,
  "scrapeProductDetails": false,
  "scrapeStoreDetails": false,
  "scrapeStoreCollections": false,
  "scrapeDeals": false,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset of products, product details, stores, and store collections.

## `runStats` (type: `string`):

Record counts and timestamps for this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "location": "72076",
    "searchQueries": [
        "McDonald's"
    ],
    "startUrls": [
        {
            "url": "https://www.doordash.com/store/mcdonald's-belmont-24508264/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/doordash-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "location": "72076",
    "searchQueries": ["McDonald's"],
    "startUrls": [{ "url": "https://www.doordash.com/store/mcdonald's-belmont-24508264/" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("datascrapers/doordash-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "location": "72076",
  "searchQueries": [
    "McDonald'\''s"
  ],
  "startUrls": [
    {
      "url": "https://www.doordash.com/store/mcdonald'\''s-belmont-24508264/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call datascrapers/doordash-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascrapers/doordash-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/odYwY66RaBn59bVtF/builds/CybJGcpJ73WPmNJU4/openapi.json
