Leafly APIleafly.com ↗
Access Leafly data via API: cannabis strains with terpene and effect filters, dispensary locations, product menus with THC/CBD content, and brand listings.
What is the Leafly API?
The Leafly API exposes 9 endpoints covering cannabis strains, dispensaries, product menus, and brands. Use list_strains to filter thousands of strains by effect, flavor, terpene, or medical symptom, get_dispensary_menu to retrieve live menu items with THC content and pricing, and search_site to query across strains, dispensaries, brands, and articles in a single call.
curl -X GET 'https://api.parse.bot/scraper/a1bdb45f-d7d8-419e-b184-5ff3e3e1608e/list_strains?skip=0&take=5&effect=creative&flavor=berry&terpene=myrcene&helps_with=pain&strain_type=indica' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace leafly-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
from parse_apis.leafly_api import Leafly, StrainType, Effect, ResourceNotFound
leafly = Leafly()
# List indica strains filtered by effect
for strain in leafly.strains.list(strain_type=StrainType.INDICA, effect=Effect.RELAXED, limit=5):
print(strain.name, strain.slug, strain.category, strain.average_rating)
# Search strains by keyword, drill into the first result
strain = leafly.strains.search(query="blue dream", limit=1).first()
if strain:
detail = leafly.strains.get(slug=strain.slug)
print(detail.name, detail.category, detail.top_effect, detail.review_count)
# Find dispensaries near San Francisco and browse menu
dispensary = leafly.dispensaries.nearby(lat="37.7749", lon="-122.4194", limit=1).first()
if dispensary:
print(dispensary.name, dispensary.slug, dispensary.review_rating)
for item in dispensary.menu_items.list(limit=3):
print(item.name, item.price, item.product_category, item.thc_content_label)
# Get full product detail
product_detail = leafly.productdetails.get(
store_slug="purple-star-md",
product_id="650140270",
product_slug="hash-burger-x-crush-mintz-h-1g-ocal-solventless-rosin-preroll"
)
print(product_detail.product.name, product_detail.product.price)
# Typed error handling on a missing strain
try:
leafly.strains.get(slug="nonexistent-strain-xyz-999")
except ResourceNotFound as exc:
print(f"Strain not found: {exc.slug}")
# List brands
for brand in leafly.brands.list(limit=3):
print(brand.name, brand.slug, brand.tagline)
print("exercised: strains.list / strains.search / strains.get / dispensaries.nearby / menu_items.list / productdetails.get / brands.list")
List cannabis strains with pagination and optional filters. Returns an array of strain objects (with name, slug, category, effects, terpenes, cannabinoids, ratings) and a total count. Filters narrow results server-side; omitting all filters returns the default popular strains. Each strain object includes rich detail for display without a detail fetch.
| Param | Type | Description |
|---|---|---|
| skip | integer | Number of results to skip for pagination. |
| take | integer | Number of results to return per page. |
| effect | string | Filter by effect (e.g., 'creative', 'relaxed', 'euphoric', 'sleepy', 'happy', 'energetic', 'focused'). |
| flavor | string | Filter by flavor (e.g., 'berry', 'citrus', 'earthy', 'sweet', 'pine'). |
| terpene | string | Filter by terpene (e.g., 'myrcene', 'limonene', 'caryophyllene', 'pinene', 'linalool'). |
| helps_with | string | Filter by medical symptom (e.g., 'pain', 'stress', 'anxiety', 'insomnia', 'depression'). |
| strain_type | string | Filter by strain type: 'indica', 'sativa', or 'hybrid'. |
{
"type": "object",
"fields": {
"total": "integer total count of matching strains",
"strains": "array of strain summary objects with name, slug, category, effects, terps, cannabinoids, averageRating, reviewCount"
},
"sample": {
"data": {
"total": 5,
"strains": [
{
"id": 75,
"name": "Blue Dream",
"slug": "blue-dream",
"category": "Hybrid",
"topEffect": "Creative",
"reviewCount": 14896,
"averageRating": 4.34
}
]
},
"status": "success"
}
}About the Leafly API
Strain Data
The list_strains endpoint accepts filters for strain_type (indica, sativa, hybrid), effect (e.g. creative, sleepy), flavor (e.g. berry, citrus), terpene (e.g. myrcene, caryophyllene), and helps_with (e.g. pain, anxiety). Each strain object in the response includes name, slug, category, effects, and terpene data. For more depth, get_strain_detail takes a slug and returns the full description, cannabinoid data, images, and an array of user reviews. Keyword-based lookup is available via search_strains, which accepts a query string and supports pagination with skip and take.
Dispensaries and Menus
list_dispensaries accepts lat and lon coordinates and returns dispensary summaries including name, address, rating, review count, and open status. get_dispensary_detail resolves a dispensary slug to its full record: address, operating hours, schedule, photos, and delivery information. get_dispensary_menu takes a dispensary slug and returns paginated menu items, each with name, price, product category, THC and CBD content, associated strain, brand, and variants. For individual products, get_product_detail requires the menu item ID, store slug, and product slug, and returns the full product record alongside dispensary context and similar items from the same menu.
Brands and Global Search
list_brands pages through Leafly's cannabis brand catalog, returning id, slug, name, description, logo URL, and tagline for each brand. search_site provides a single entry point for cross-entity search, returning results grouped into five typed arrays: strain, dispensary, brand, menuItem, and article. This is useful when the category of a search result is unknown in advance.
The Leafly API is a managed, monitored endpoint for leafly.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when leafly.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official leafly.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a strain finder that lets users filter by terpene, effect, and strain type using
list_strainsparameters - Display dispensary hours, delivery availability, and photos on a cannabis locator map using
get_dispensary_detail - Aggregate product pricing and THC content across multiple dispensaries with
get_dispensary_menu - Feed a recommendation engine with strain cannabinoid profiles and user review sentiment from
get_strain_detail - Index the Leafly brand catalog for a cannabis brand discovery tool using
list_brands - Power an autocomplete search bar that returns strains, dispensaries, and brands together via
search_site - Track menu availability and price changes over time by polling
get_dispensary_menufor specific store slugs
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Leafly have an official developer API?+
What does `get_strain_detail` return beyond basic strain info?+
get_strain_detail returns the full strain object including description, effects, terpene breakdown, cannabinoid data, and images, plus a reviews array containing user-submitted review objects for that strain.How does `search_site` differ from `search_strains`?+
search_strains returns only strain objects matching a keyword. search_site returns results grouped into five typed arrays — strain, dispensary, brand, menuItem, and article — making it the right choice when you need cross-entity results from a single query.Does the API cover dispensary inventory history or price change tracking?+
get_dispensary_menu, including price, THC content, and variants, but does not expose historical pricing or inventory snapshots. You can fork this API on Parse and revise it to add a polling-based historical tracking endpoint.Are deals, coupons, or loyalty program data available from dispensaries?+
get_dispensary_detail and get_dispensary_menu endpoints cover hours, delivery info, product pricing, and menu items, but do not expose dispensary deals, coupons, or loyalty rewards. You can fork this API on Parse and revise it to add an endpoint targeting that data.