# Victorian Liquor Licences + New Licence Tracker (`metal_spinney/vic-liquor-licences`) Actor

Every Victorian liquor licence from official DataVic open data (CC BY 4.0), with a new-since-last-run mode that outputs only newly granted licences - ideal for sales leads.

- **URL**: https://apify.com/metal_spinney/vic-liquor-licences.md
- **Developed by:** [Open Registry Data](https://apify.com/metal_spinney) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## Victorian Liquor Licences + New Licence Tracker

Every current liquor licence in Victoria (about 23,000) from the official monthly register that **Liquor Control Victoria** publishes on DataVic. Each record comes with its trading name, licensee, category, trading hours, patron capacity, address, council, region and lat/long.

**Diff mode** compares the two most recent monthly files and returns only licences that are **new**, **changed** (licensee, trading name, address, capacity, hours or category) or **removed**. Each changed record lists its field-level `from` → `to` values. Example: Jul → Aug 2026 had 259 new, 193 changed and 30 removed licences.

### Who it's for

Hospitality suppliers and sales reps (beverage, POS, linen, insurance, security, glassware), market researchers, compliance teams, and AI agents that need a structured lookup of Victorian venues. Run diff mode monthly on a schedule to feed a "new venues" lead list.

### Input

| Field | Meaning |
|---|---|
| `mode` | `snapshot` (full current register) or `diff` (changes since the previous month) |
| `changeTypes` | Diff mode only: any of `new`, `changed`, `removed` |
| `categories` | Substring match on the official category names, e.g. `Restaurant and cafe Licence`, `Late night`, `Packaged Liquor`, `BYO Permit` (case, accents and licence/license spelling ignored) |
| `councils` | Substring match, e.g. `Yarra` |
| `suburbs`, `postcodes`, `regions` | Exact match |
| `metroRegional` | `any` / `Metro` / `Regional` |
| `nameContains`, `minPatronCapacity` | Optional name and capacity filters |
| `includePostalAddress` | Off by default. Many licensees are individuals, so postal addresses are left out unless you ask for them |
| `maxItems` | Default 1000; 0 means no limit |

### Output (one item per licence)

See `samples/`. Fields: `licenceNumber, licensee, tradingAs, category, tradingHours, patronCapacity, streetAddress, suburb, postcode, state, council, region, metroRegional, latitude, longitude, snapshotDate`, plus `changeType/changes/comparedWith` in diff mode and a `source` attribution block.

### Pricing (pay per result)

- Suggested **US$0.003 per result** in snapshot mode. The full state costs about US$69, a typical council/category slice of under 500 rows costs under US$1.50.
- Diff mode is the high-value product. Charge it as a separate event at around **US$0.01 per change record**. A month's full diff is about 480 rows, roughly US$5 a month per subscriber.
- Why: the raw file is free, so the price pays for not having to discover and download a new XLSX with a changing filename each month, parse its messy header rows, normalise categories and casing, geocode-join the data and compute the diff. It is priced below the cost of a person doing this by hand (more than 30 minutes a month). Compute per run is small: about 20 s and 2 file downloads of about 5 MB each.

### Source and licence

- Data: *Victorian liquor licences by location*, Liquor Control Victoria, https://discover.data.vic.gov.au/dataset/victorian-liquor-licences-by-location. Licence: **Creative Commons Attribution 4.0** (DataVic `cc-by`).
- Attribution included in every record: "Contains information from Victorian liquor licences by location, Liquor Control Victoria, via DataVic, licensed under CC BY 4.0. Not endorsed by Liquor Control Victoria or the State of Victoria."
- Only the official bulk file is used. No scraping. The latest files are found through the DataVic CKAN API. Each file is checked after parsing (at least 5,000 rows, licence number / category / suburb columns filled); if the newest monthly file is missing, malformed or blocked, the actor falls back to the previous month and says so in the log.
- The data is a monthly snapshot. Check the official register before relying on a licence's status. Users are responsible for their own Privacy Act and Spam Act compliance when they contact licensees.

### Run locally

```
pip install -r requirements.txt
mkdir -p storage/key_value_stores/default && echo '{"mode":"diff"}' > storage/key_value_stores/default/INPUT.json
python -m src      # output in storage/datasets/default
```

# Actor input Schema

## `mode` (type: `string`):

Diff mode compares the latest two monthly files.

## `changeTypes` (type: `array`):

Which changes to return.

## `categories` (type: `array`):

Case-insensitive substring match against the official LCV category names (accents, dashes and licence/license spelling are ignored). Real values: Restaurant and cafe Licence, Limited Licence, Packaged Liquor Licence, General Licence, On-premises Licence, Pre-retail Licence, Producer's Licence, Remote Seller's Licence, Restricted Club Licence, Full Club Licence, BYO Permit, Late night (general) Licence, Late night (On-premises) Licence, Late night (packaged liquor) Licence. Short forms such as 'Late night' or 'Club' also work.

## `councils` (type: `array`):

Substring match, e.g. 'Melbourne City', 'Yarra'.

## `suburbs` (type: `array`):

Exact suburb (case-insensitive).

## `postcodes` (type: `array`):

Exact postcode.

## `regions` (type: `array`):

e.g. 'Metro West', 'Hume'.

## `metroRegional` (type: `string`):

Metro or regional Victoria.

## `nameContains` (type: `string`):

Case-insensitive.

## `minPatronCapacity` (type: `integer`):

Only venues with at least this capacity.

## `includePostalAddress` (type: `boolean`):

Off by default: postal addresses can be private individuals' addresses.

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

0 = no limit (you pay per result).

## Actor input object example

```json
{
  "mode": "snapshot",
  "changeTypes": [
    "new",
    "changed",
    "removed"
  ],
  "categories": [
    "Restaurant and cafe Licence"
  ],
  "metroRegional": "any",
  "includePostalAddress": false,
  "maxItems": 1000
}
```

# Actor output Schema

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

No description

## `resultsView` (type: `string`):

No description

# 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 = {
    "categories": [
        "Restaurant and cafe Licence"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("metal_spinney/vic-liquor-licences").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 = { "categories": ["Restaurant and cafe Licence"] }

# Run the Actor and wait for it to finish
run = client.actor("metal_spinney/vic-liquor-licences").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 '{
  "categories": [
    "Restaurant and cafe Licence"
  ]
}' |
apify call metal_spinney/vic-liquor-licences --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,metal_spinney/vic-liquor-licences"
        }
    }
}
```

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/bhTWrB4b8arqwJYAg/builds/ZywsEmX55xVJyBbeq/openapi.json
