TTB Distilled Spirits Plant Permits Scraper avatar

TTB Distilled Spirits Plant Permits Scraper

Pricing

from $1.32 / 1,000 item extracteds

Go to Apify Store
TTB Distilled Spirits Plant Permits Scraper

TTB Distilled Spirits Plant Permits Scraper

Download and filter the official TTB distilled spirits plant permittee roster for supplier verification and compliance research.

Pricing

from $1.32 / 1,000 item extracteds

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Download and filter the official US Alcohol and Tobacco Tax and Trade Bureau (TTB) spirits producers and bottlers roster. The Actor turns the public TTB distilled spirits plant permits file into typed dataset rows for supplier verification, compliance research, and repeatable roster refreshes.

The output includes each DSP permit number, legal owner and operating names, premises address, county, industry type, new-permit flag, and regulator provenance. No TTB account or browser automation is required.

What can you do with this Actor?

  • Search the national TTB spirits producer roster by permit, business name, trade name, or address text.
  • Export all permittees for one or more states, cities, or counties.
  • Resolve an exact list of DSP permit numbers for supplier onboarding.
  • Extract records that TTB marks as new since its previous publication.
  • Schedule recurring runs and compare datasets in your own database or automation.
  • Send normalized results to spreadsheets, BI tools, CRMs, or compliance systems.

This Actor covers the official Spirits Producers and Bottlers List. It does not claim to return wine, beer, importer, wholesaler, COLA, application, enforcement, or private account records.

Who is it for?

Compliance teams can create a repeatable regulator-sourced permit roster for screening and periodic review.

Distillers, distributors, and procurement teams can confirm that a prospective supplier appears in the published TTB spirits list.

Researchers and analysts can segment distilled spirits plants by geography, legal owner, operating name, or publication marker.

Data engineers can replace manual CSV downloads with a scheduled API workflow and a stable output schema.

Why use this TTB permit scraper?

TTB publishes a useful CSV, but a raw file still leaves filtering, parsing, limits, provenance, and integrations to you. This Actor:

  1. discovers the current official CSV from TTB's permittee page;
  2. validates the source hostname, response shape, and expected columns;
  3. parses quoted CSV values safely;
  4. applies all filters before charging or saving records;
  5. emits normalized JSON with a combined address and source timestamps.

If TTB changes the file schema or returns an unexpected page, the run fails clearly instead of silently producing misleading empty data.

Data extracted

FieldDescription
permitNumberPublished TTB permit identifier
ownerNameLegal owner name
operatingNameOperating or trade name, when published
streetPremises street address
cityPremises city
stateTwo-letter state or territory code
zipCodePremises ZIP code
countyPremises county, when published
industryTypeTTB industry classification
isNewPermitWhether the source marks the record as new
fullAddressCombined premises address for convenient export
sourceUrlExact official CSV URL used by the run
sourcePageUrlOfficial TTB permittee-list page
fetchedAtUTC retrieval timestamp

Blank values from the regulator are preserved as empty strings. The Actor does not infer missing trade names, counties, or permit status.

Getting started

  1. Open the Actor in Apify Console.
  2. Enter a broad query, exact geography filters, permit numbers, or enable newPermitsOnly.
  3. Set maxItems to control the maximum number of accepted records.
  4. Click Start.
  5. Review the Dataset tab or export results as JSON, CSV, Excel, XML, or RSS.
  6. Save the run as an Apify Task if you want a stable recurring workflow.

A useful first input is:

{
"states": ["KY"],
"maxItems": 50
}

Input parameters

InputTypeDefaultBehavior
querystringemptyCase-insensitive substring search across identity, address, and industry fields
permitNumbersstring[]allExact permit-number match
statesstring[]allExact two-letter state or territory match
countiesstring[]allExact county-name match, case-insensitive
citiesstring[]allExact city-name match, case-insensitive
industryTypesstring[]allExact TTB industry-type match
newPermitsOnlybooleanfalseKeep only rows whose source flag is 1
maxItemsinteger100Save between 1 and 10,000 accepted rows

Filters combine with AND logic. Values within one array use OR logic. For example, states: ["KY", "TN"] plus query: "BOURBON" returns rows in either state that also contain the search text.

Filter examples

Search names and addresses for bourbon-related text:

{
"query": "BOURBON",
"maxItems": 25
}

Look up exact permits:

{
"permitNumbers": ["KY-S-10", "AK-S-15000"],
"maxItems": 10
}

Build a geographic supplier list:

{
"states": ["KY"],
"counties": ["NELSON"],
"maxItems": 500
}

Find records marked new in TTB's latest published roster:

{
"newPermitsOnly": true,
"maxItems": 100
}

Output example

A dataset item follows this shape:

{
"permitNumber": "KY-S-20016",
"ownerName": "EXAMPLE DISTILLING COMPANY LLC",
"operatingName": "EXAMPLE SPIRITS",
"street": "100 DISTILLERY WAY",
"city": "BARDSTOWN",
"state": "KY",
"zipCode": "40004",
"county": "NELSON",
"industryType": "Distilled Spirits Plant",
"isNewPermit": false,
"fullAddress": "100 DISTILLERY WAY, BARDSTOWN, KY, 40004",
"sourceUrl": "https://www.ttb.gov/system/files/2025-04/FRL_Spirits_Producers_and_Bottlers_List.csv",
"sourcePageUrl": "https://www.ttb.gov/public-information/foia/list-of-permittees",
"fetchedAt": "2026-09-12T06:00:00.000Z"
}

The example anonymizes business identity while preserving the real output types. Actual runs return the public values supplied by TTB.

How much does it cost to export TTB spirits permittees?

Pay-per-event pricing has a one-time $0.00005 run start and an item fee based on your Apify plan:

TierPrice per saved permittee
Free$0.00253
Bronze$0.00220
Silver$0.001716
Gold$0.00132
Platinum$0.00132
Diamond$0.00132

At the Bronze rate, 25 saved permittees cost about $0.05505, 100 cost about $0.22005, and 1,000 cost about $2.20005, including the start event. Failed, filtered-out, and duplicate rows do not incur the item event.

Apify platform compute is handled by the Actor's pricing model. Check the live pricing panel before a large run because platform pricing can change.

Scheduling compliance refreshes

Create an Apify Task with a stable filter, then add a weekly or monthly schedule. Each run receives the latest roster URL advertised by the official TTB page and stamps every row with fetchedAt and sourceUrl.

For change monitoring, retain datasets in your destination and compare records by permitNumber. The isNewPermit field reflects TTB's source marker; it is not a complete historical change log. Your own snapshots are the durable way to detect changed names or addresses.

Integrations and exports

Use Apify integrations to send results to:

  • Google Sheets for a review queue;
  • Make or Zapier for supplier onboarding;
  • webhooks for downstream validation;
  • cloud storage or a data warehouse for snapshots;
  • Python, JavaScript, or any HTTP client through the Apify API.

The stable deduplication key is permitNumber. Keep sourceUrl and fetchedAt when audit provenance matters.

Run with the API using cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~ttb-distilled-spirits-plant-permittees/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"states":["KY"],"maxItems":50}'

For synchronous dataset output, use the run-sync-get-dataset-items endpoint when the requested volume fits your client timeout.

Run with JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/ttb-distilled-spirits-plant-permittees').call({
query: 'BOURBON',
maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Run with Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/ttb-distilled-spirits-plant-permittees').call(
run_input={'newPermitsOnly': True, 'maxItems': 100}
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)

Use through MCP

Add the Apify MCP server to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/ttb-distilled-spirits-plant-permittees"

For Claude Desktop, add this JSON under mcpServers in the desktop configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/ttb-distilled-spirits-plant-permittees"
}
}
}

For Cursor, open MCP settings and add the same apify server URL. For VS Code, add the URL as an HTTP MCP server in your workspace or user MCP configuration.

Example prompts:

  • “Export 50 Kentucky TTB distilled spirits plant permittees.”
  • “Find current TTB spirits roster records containing bourbon.”
  • “Return permits marked new in the latest TTB producer list.”

Reliability and source behavior

The Actor fetches two lightweight official resources: the TTB permittee index and its current spirits CSV. Transient timeouts, 429 responses, and temporary server errors receive bounded retries. It does not use proxies or browser automation.

The run intentionally fails when:

  • TTB returns a non-success status after retries;
  • the page or CSV has an unexpected content shape;
  • required columns disappear or unknown columns appear;
  • a CSV row has the wrong number of fields;
  • input values violate documented limits.

A valid query with no matches succeeds with an empty dataset.

Limits and interpretation

  • Coverage is limited to the current public TTB spirits producers and bottlers file.
  • TTB controls publication timing, field contents, and the meaning of its new-permit flag.
  • Presence in the list is not legal advice and does not prove present good standing for every purpose.
  • The roster does not provide a complete permit history, revocation history, application status, contacts, or ownership graph.
  • Exact geography filters depend on regulator spelling. Use query when you need broader text matching.
  • maxItems limits accepted rows, not rows scanned in the downloaded source.

Responsible use

The Actor processes a public US government roster. Use results for lawful compliance, research, procurement, and data-quality purposes. Verify consequential decisions against the linked official TTB source and applicable rules. Do not present an Actor result as legal advice or as a substitute for regulator confirmation.

Respect Apify's terms, TTB's website policies, and any laws governing your downstream use, retention, matching, or redistribution of records.

Troubleshooting

Why did my run return zero records?

Filters combine with AND logic. Remove filters one at a time, verify two-letter state codes, and check regulator spelling for cities and counties. A valid no-match input produces an empty dataset.

Why did the run fail after TTB changed its page?

The Actor fails closed when it cannot validate the source or schema. Review the run log for HTTP, content, or changed-column details and retry after the official file is available again.

Why is operatingName or county blank?

TTB does not publish those values on every row. The Actor preserves the source rather than inventing missing data.

Frequently asked questions

Does this search TTB COLAs Online?
No. COLA label approvals are a separate dataset and workflow.

Does isNewPermit mean the permit was issued today?
No. It mirrors TTB's “new permit” marker in the current file. TTB controls the publication interval.

Can I download the full roster?
Yes. Leave filters empty and set maxItems high enough for the current source volume, up to 10,000.

Can I filter several states?
Yes. Values within states are ORed, while different filter fields are ANDed.

Are filtered-out rows charged?
No. The per-item event applies only to records saved to the dataset.

These are separate official-registry workflows and do not enrich or alter TTB permittee results automatically.