# Weedmaps Dispensary Scraper — Locations, Hours & Menus (`muhammadafzal/weedmaps-dispensary-scraper`) Actor

Extract cannabis dispensaries, storefronts, and deliveries from Weedmaps with locations, addresses, operating hours, phone numbers, ratings, reviews, license details, and menus.

- **URL**: https://apify.com/muhammadafzal/weedmaps-dispensary-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Lead generation, E-commerce, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 dispensary results

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

## Weedmaps Dispensary Scraper

Extract structured cannabis dispensary and delivery data from [Weedmaps](https://weedmaps.com) without logins or cookies. Retrieve comprehensive store profiles, street addresses, phone numbers, contact emails, operating hours, geolocation coordinates, licenses, customer ratings, review counts, active deals, and menu items across the United States and Canada.

> **Free users:** verified Apify Free plan users receive up to **5 delivered records per run**. Upgrade to an Apify paid tier for higher volume.

***

### Features

- **Storefront & Delivery Coverage:** Scrape both physical dispensary storefronts and delivery services.
- **Accurate Contact Leads:** Extract business phone numbers, contact emails, and direct website URLs.
- **Location & Geocoding:** Full street address, city, state, postal code, and precise GPS latitude/longitude coordinates.
- **Compliance & Licensing:** Adult-use (recreational), medical, and hybrid license classifications.
- **Hours & Service Options:** Today's operating hours, current open status, curbside pickup availability, and accepted payment types (cash, debit, cashless).
- **Ratings & Reviews:** Customer star rating, total review count, and Weedmaps ranking metrics.
- **Deals & Menus:** Active promotional deals, menu item counts, and optional detailed menu item extraction.
- **Flexible Search Modes:** Provide Weedmaps city/region URLs, direct dispensary profile URLs, or search by location query (e.g. `Los Angeles, CA` or `Denver, CO`).

***

### Use Cases

- **Cannabis Market Intelligence:** Map local dispensary density, market saturation, and competitor footprint across legal states.
- **B2B Lead Generation:** Build outreach lists for ancillary cannabis software, packaging, equipment, and consulting vendors.
- **Brand Distribution Audits:** Monitor retailer networks and verify where specific cannabis brands are stocked.
- **Regulatory & Compliance Tracking:** Track licensed cannabis dispensaries, license numbers, and operating jurisdictions.
- **Retail Price & Promotion Monitoring:** Analyze active promotional deals, discounts, and regional menu pricing.

***

### Input Parameters

| Field | Type | Description | Default |
|---|---|---|---|
| `startUrls` | Array | Weedmaps URLs to crawl. Supports region listing pages (e.g. `/dispensaries/in/united-states/california/los-angeles`) or individual dispensary pages (e.g. `/dispensaries/stiiizy`). | `[{"url": "https://weedmaps.com/dispensaries/in/united-states/california/los-angeles"}]` |
| `location` | String | City, region, or state to search (e.g. `Denver, CO`, `Los Angeles, CA`, `Detroit`). Used when `startUrls` is empty. | `"Los Angeles, CA"` |
| `maxResults` | Integer | Maximum dispensary records to deliver (1 - 5,000). Free plan is capped at 5 results. | `20` |
| `maxPagesPerLocation` | Integer | Maximum pagination pages to crawl per region URL (1 - 50). Each page has ~30 dispensaries. | `5` |
| `scrapeMenuItems` | Boolean | Whether to fetch menu item details for each dispensary. | `false` |
| `maxMenuItemsPerDispensary` | Integer | Max menu items to extract per dispensary when `scrapeMenuItems` is enabled (1 - 200). | `20` |
| `proxyConfiguration` | Object | Proxy configuration. US residential proxies are used by default for reliability. | `{ "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }` |

***

### Output Example

Each dispensary result delivered to the default dataset contains clean, normalized fields:

```json
{
  "id": 65841,
  "name": "STIIIZY Downtown LA",
  "slug": "stiiizy",
  "url": "https://weedmaps.com/dispensaries/stiiizy",
  "type": "dispensary",
  "wmid": 770072967,
  "address": "728 E Commercial St",
  "city": "Los Angeles",
  "state": "California",
  "zipCode": "90012",
  "country": "United States",
  "latitude": 34.052206,
  "longitude": -118.232052,
  "phoneNumber": "(323) 929-4201",
  "email": "retail.dtla@stiiizy.com",
  "website": null,
  "rating": 4.8,
  "reviewsCount": 8398,
  "ranking": 4.75,
  "licenseType": "hybrid",
  "retailerServices": [
    "storefront",
    "pickup"
  ],
  "hasCurbsidePickup": false,
  "openNow": true,
  "todaysHours": "6:00am - 9:45pm",
  "minAge": 21,
  "menuItemsCount": 2067,
  "verifiedMenuItemsCount": 1827,
  "hasSaleItems": true,
  "hasFeaturedDeal": true,
  "topDeals": [
    {
      "id": 1398219,
      "title": "30% off First Time Customers",
      "brandName": "STIIIZY",
      "slug": "stiiizy-downtown-la-30-off-first-time-customers"
    }
  ],
  "topDealsCount": 4,
  "avatarImageUrl": "https://images.weedmaps.com/dispensaries/000/065/841/avatar/1783453209-46.png",
  "socialEquity": false,
  "acceptsCreditCards": false,
  "acceptsDebitCards": true,
  "acceptsCashlessPayments": true,
  "introBody": "ALL PRICES ARE OUT THE DOOR *Tax included* We accept Debit Cards & Cash Payments",
  "scrapedAt": "2026-09-30T12:00:00.000Z"
}
```

***

### Pricing (Pay Per Event)

This Actor charges under transparent **Pay per event** pricing with no hidden compute surcharges. Platform usage pass-through is disabled (`isPPEPlatformUsagePaidByUser = false`).

#### Event Pricing Tiers

| Event Name | Event Title | FREE Tier | BRONZE Tier (2.5% off) | SILVER Tier (5% off) | GOLD Tier (20% off) |
|---|---|---|---|---|---|
| `apify-actor-start` | Actor start | **$0.005** | **$0.005** | **$0.005** | **$0.005** |
| `apify-default-dataset-item` | Dispensary Result | **$0.001** | **$0.000975** | **$0.00095** | **$0.0008** |

#### Representative Run Costs

- **20 Dispensary Records (FREE list price):** $0.005 (start) + (20 × $0.001) = **$0.025**
- **100 Dispensary Records (FREE list price):** $0.005 (start) + (100 × $0.001) = **$0.105**
- **1,000 Dispensary Records (GOLD tier):** $0.005 (start) + (1,000 × $0.0008) = **$0.805**

***

### How to Run

#### Via Apify Console

1. Open the Actor on Apify.
2. Select your desired search location or enter start URLs.
3. Click **Start** to execute the run.
4. Export your results in JSON, CSV, Excel, or NDJSON.

#### Via Apify Python Client

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("muhammadafzal/weedmaps-dispensary-scraper").call(
    run_input={
        "location": "Denver, CO",
        "maxResults": 50
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["phoneNumber"], item["address"])
```

#### Via Apify JavaScript / Node.js Client

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('muhammadafzal/weedmaps-dispensary-scraper').call({
    location: 'Denver, CO',
    maxResults: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

***

### Limitations & Integrity

- **Anti-bot & Geo-fencing:** Weedmaps enforces geo-restrictions and Fastly WAF protections. Residential proxies within legal jurisdictions (US) are used to maintain high reliability.
- **Menu Scraping Overhead:** Enabling `scrapeMenuItems` fetches individual storefront menus and takes longer per dispensary than storefront directory extraction.
- **Truthful Data Guarantee:** The Actor never fabricates records. Nonexistent locations or empty query regions return truthful empty results with informative diagnostics.

# Actor input Schema

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

Weedmaps URLs to scrape. Accepts region/city listing pages (e.g., https://weedmaps.com/dispensaries/in/united-states/california/los-angeles) or individual dispensary detail pages (e.g., https://weedmaps.com/dispensaries/stiiizy).

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

Optional city, region, or state to search for dispensaries (e.g., 'Los Angeles, CA', 'Denver, CO', 'San Francisco', or 'Detroit'). Used when Start URLs is not specified.

## `maxResults` (type: `integer`):

Maximum number of dispensary records to extract. Free users are capped at 5 results per run.

## `maxPagesPerLocation` (type: `integer`):

Maximum pagination pages to crawl for each region listing page. Each page typically contains 30 dispensaries.

## `scrapeMenuItems` (type: `boolean`):

Whether to extract menu items and product catalogs for each scraped dispensary.

## `maxMenuItemsPerDispensary` (type: `integer`):

Maximum number of menu items to extract per dispensary when Scrape Menu Items is enabled.

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

Proxy configuration. Weedmaps enforces geo-restrictions and anti-bot protection; US residential proxies are strongly recommended.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://weedmaps.com/dispensaries/in/united-states/california/los-angeles"
    }
  ],
  "location": "Los Angeles, CA",
  "maxResults": 20,
  "maxPagesPerLocation": 5,
  "scrapeMenuItems": false,
  "maxMenuItemsPerDispensary": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Link to the dataset containing all extracted Weedmaps dispensary records.

# 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 = {
    "startUrls": [
        {
            "url": "https://weedmaps.com/dispensaries/in/united-states/california/los-angeles"
        }
    ],
    "location": "Los Angeles, CA",
    "maxResults": 20,
    "maxPagesPerLocation": 5,
    "maxMenuItemsPerDispensary": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/weedmaps-dispensary-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 = {
    "startUrls": [{ "url": "https://weedmaps.com/dispensaries/in/united-states/california/los-angeles" }],
    "location": "Los Angeles, CA",
    "maxResults": 20,
    "maxPagesPerLocation": 5,
    "maxMenuItemsPerDispensary": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/weedmaps-dispensary-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 '{
  "startUrls": [
    {
      "url": "https://weedmaps.com/dispensaries/in/united-states/california/los-angeles"
    }
  ],
  "location": "Los Angeles, CA",
  "maxResults": 20,
  "maxPagesPerLocation": 5,
  "maxMenuItemsPerDispensary": 20
}' |
apify call muhammadafzal/weedmaps-dispensary-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/weedmaps-dispensary-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/jUxJPevsPemABls6L/builds/GqwFg85ehNNApPR3G/openapi.json
