# California Cannabis License Search (`muhammadafzal/california-cannabis-license-scraper`) Actor

Search California DCC cannabis business licenses by license number, business name, status, type, county, designation, or term. Export public license records to a dataset.

- **URL**: https://apify.com/muhammadafzal/california-cannabis-license-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 cannabis license records

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

## California Cannabis License Search

Search the California Department of Cannabis Control (DCC) public license directory and export structured cannabis business license records to an Apify dataset. Search by license number, business, owner, address, city, or ZIP code, then narrow the results by status, license type, designation, stage, and premises county.

The Actor reads the public data endpoint used by DCC’s [Cannabis Unified License Search](https://search.cannabis.ca.gov/). DCC says its license search tool is updated daily and contains information about businesses licensed by the Department. Always verify a record with DCC before relying on it for a licensing decision.

### What the Actor returns

Each dataset item represents one state license. It includes the license number and status, type and designation, issue and expiration dates, state licensing authority, legal and DBA names, public owner-name field, business structure, premises address and county, public email and phone, parcel number, coordinates, local jurisdiction, the source refresh timestamp, and collection timestamp.

| Field group | Dataset fields |
|---|---|
| License identity | licenseRecordId, licenseNumber, licenseStatus, licenseStatusDate |
| Terms | licenseTerm, licenseType, licenseDesignation, issueDate, expirationDate |
| Licensee | businessLegalName, businessDbaName, businessOwnerName, businessStructure, activity |
| Premises | premiseStreetAddress, premiseCity, premiseState, premiseCounty, premiseZipCode, premiseLatitude, premiseLongitude, parcelNumber |
| Authority and freshness | licensingAuthority, licensingAuthorityId, localJurisdictionType, localJurisdictionName, dataRefreshedDate, sourceUrl, scrapedAt |
| Run diagnostics | SUMMARY in the default key-value store |

Unavailable source fields are returned as null. The Actor skips a source row only when it lacks a usable DCC record ID or license number. It does not invent a fallback record.

### Search inputs

| Input | Default | Description |
|---|---:|---|
| searchQuery | Empty | Text search using the DCC portal. A license number, business name, owner, street, city, ZIP code, or other directory text can be searched. |
| licenseStatus | Active | Choose one status or All statuses. Status options include Active, Limited Operations, Canceled, Expired, Revoked, Suspended, and Surrendered. |
| licenseType | Empty | Exact DCC license type name. Matching ignores capitalization and repeated spaces; for example, Commercial - Retailer resolves to the source’s current option. |
| licenseDesignation | Any | Optional Adult-Use, Medicinal, or Adult-Use and Medicinal filter. |
| licenseTerm | Any | Optional Annual, Provisional, or Interim filter. |
| premiseCounty | Empty | Exact county name for the licensed premises, such as Alameda or Los Angeles. |
| maxResults | 100 | Maximum dataset records. Paid runs may request up to 25,000; the hosted Apify free-plan ceiling is 5 records per run. Pages contain up to 1,000 records. |

The default status filter returns active licenses. Choose All statuses to include historical or inactive records. A status is not a legal opinion: DCC explains its status meanings on its [license search help page](https://www.cannabis.ca.gov/resources/search-for-licensed-business/).

Example: find a specific license regardless of its current status.

```
{
  "searchQuery": "C10-0000001-LIC",
  "licenseStatus": "All statuses",
  "maxResults": 10
}
```

Example: return active retailer licenses in Alameda County.

```
{
  "licenseStatus": "Active",
  "licenseType": "Commercial - Retailer",
  "premiseCounty": "Alameda",
  "maxResults": 100
}
```

### Output example

```
{
  "licenseRecordId": 6557,
  "licenseNumber": "C10-0000007-LIC",
  "licenseStatus": "Active",
  "licenseTerm": "Annual",
  "licenseType": "Commercial - Retailer",
  "licenseDesignation": "Adult-Use and Medicinal",
  "issueDate": "2018-11-20T00:00:00",
  "expirationDate": "2026-11-20T00:00:00",
  "licensingAuthority": "Bureau of Cannabis Control (BCC)",
  "businessLegalName": "Blue Mountain Collective, Inc.",
  "businessDbaName": "BLUE MOUNTAIN COLLECTIVE, INC.",
  "premiseStreetAddress": "692 Marshall Ave",
  "premiseCity": "San Andreas",
  "premiseState": "CA",
  "premiseCounty": "Calaveras",
  "premiseZipCode": "95249",
  "dataRefreshedDate": "2026-09-23T17:43:44.17",
  "sourceUrl": "https://search.cannabis.ca.gov/",
  "scrapedAt": "2026-09-24T05:55:00.000Z"
}
```

The source example is shortened here; the dataset schema describes every output field. The official directory may show personal names and business contact details as part of its public license records.

### Pricing

This Actor uses Pay per event. Apify automatically charges one start event per run and one apify-default-dataset-item event for each record delivered to the default dataset. It does not manually charge events, and it does not pass platform usage through as a separate bill.

| Event | FREE | BRONZE | SILVER | GOLD | PLATINUM | DIAMOND |
|---|---:|---:|---:|---:|---:|---:|
| Actor start, once per run | $0.005 | $0.005 | $0.005 | $0.005 | $0.005 | $0.005 |
| Cannabis license record, per dataset item | $0.001 | $0.000975 | $0.000950 | $0.000800 | $0.000800 | $0.000800 |

For one record, the event total is $0.006 FREE, $0.005975 BRONZE, $0.005950 SILVER, or $0.005800 for GOLD, PLATINUM, and DIAMOND. For 100 records, it is $0.105 FREE, $0.1025 BRONZE, $0.100 SILVER, or $0.085 for GOLD, PLATINUM, and DIAMOND. These totals exclude any taxes and do not include the separate Apify usage cost when the Actor is run outside the paid event model.

The minimum run charge limit is set to $0.006 so one start plus one record can be delivered. For larger exports, increase the run’s maximum charge limit enough to cover the start event and expected record count. The free-plan run limit is five records even when maxResults is higher.

### Reliability and limits

The Actor reads the current API address from the public DCC search portal configuration and then calls its page-backed license search endpoint. It uses sequential requests, limits each request to 1,000 rows, retries temporary HTTP 429 and 5xx errors up to two times with bounded delays, and stops at the requested result count. It does not use an account, private session, CAPTCHA solver, or third-party provider.

The DCC source may change its portal configuration or response fields. If the public portal returns an access denial or an unexpected response, the Actor reports a BLOCKED or FAILED outcome in the terminal status and SUMMARY; it does not return fabricated data. A successful search with no matches is reported as EMPTY. If the result limit is reached while more records match, SUMMARY.truncated is true.

The Actor’s 25,000-record hard cap, 1,000-row page size, and Apify run charge limit bound the amount of work and output. By default it writes at most 100 records, or 5 records on a hosted Apify free-plan run. For large exports, use a paid Apify plan and set both maxResults and the run’s maximum charge limit intentionally.

### Use and data handling

This Actor is for public-record research, license discovery, and business-data workflows. Its results are a snapshot of DCC’s public directory, not a guarantee that a license is currently valid, that local permits exist, or that a business may operate at a particular location. Confirm high-impact decisions with the [official DCC search](https://search.cannabis.ca.gov/) and relevant local authorities.

License records can include the owner-name and contact fields DCC displays publicly. Use the data in ways permitted by applicable law and DCC’s [privacy policy](https://www.cannabis.ca.gov/dcc-privacy-policy/). The Actor does not enrich these records or infer missing personal or business details.

### Source

- [DCC Search for a licensed business](https://www.cannabis.ca.gov/resources/search-for-licensed-business/)
- [Cannabis Unified License Search](https://search.cannabis.ca.gov/)
- [DCC data dashboards and glossary](https://www.cannabis.ca.gov/resources/data-dashboard/)

For a correction or support request, include the Actor run ID, input filters, and the relevant license number. Do not include private credentials or unrelated personal data.

# Actor input Schema

## `searchQuery` (type: `string`):

Use this to search license number, business name, owner, address, city, ZIP code, county, status, or other DCC directory text. Matching follows the official portal. Example: C10-0000001-LIC or Blue Mountain.

## `licenseStatus` (type: `string`):

Use this to filter the current DCC status. Defaults to Active. Choose All statuses to include inactive records too. Example: Surrendered.

## `licenseType` (type: `string`):

Use this to select one exact official DCC license type, matched without case or repeated-space differences. Examples: Commercial - Retailer, Retailer Non-Storefront, Manufacturer - Type 6, Cultivation - Small Outdoor.

## `licenseDesignation` (type: `string`):

Use this to filter adult-use, medicinal, or combined licenses. Example: Adult-Use and Medicinal. Some license categories use Other or have no designation.

## `licenseTerm` (type: `string`):

Use this to filter the official license term or stage. Examples: Annual, Provisional, Interim. The source may not return every stage for every date.

## `premiseCounty` (type: `string`):

Use this to filter the county of the licensed premises. Enter the DCC county name, for example Alameda or Los Angeles. This is the premises county, not a business mailing county.

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

Use this to bound output and per-record PPE charges. Paid runs can return up to 25,000 records; the hosted Apify free-plan cap is 5 records per run. A 1,000-record page is fetched at a time.

## Actor input object example

```json
{
  "licenseStatus": "Active",
  "maxResults": 100
}
```

# Actor output Schema

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

Structured records from the California Department of Cannabis Control public license search.

## `summary` (type: `string`):

Outcome, source match count, delivered count, DCC data refresh time, and warnings.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/california-cannabis-license-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/california-cannabis-license-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 '{}' |
apify call muhammadafzal/california-cannabis-license-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/california-cannabis-license-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/UkcZMr5GHMkiAy3dP/builds/v6z3KIc2J3qq7nitD/openapi.json
