Roughly 900 dispensaries across two states, each one running on one of nine menu platforms. Every platform has its own shape, its own quirks, and its own dedicated scraper.
State 01
Ohio
Adult-use and medical menus, full coverage.
Every active Ohio dispensary tracked on a rolling 25-minute pipeline. Scrapes route through a secondary WAN to keep upstream load even.
State 02
Michigan
Adult-use menus, the larger half of the footprint.
Same pipeline, same reports, same matching rules across state lines. Side-by-side comparisons fall out of the data naturally.
Nine platforms
A scraper per platform. By design.
No generic HTML scraper, no shared parser. Each platform has API-shaped or storefront-shaped quirks that only get clean data with a dedicated implementation. We pay that tax once, you get the upside every cycle.
Dutchie
API + storefront + detail scrape
iHeartJane
Algolia + API + storefront
Leafly
API + storefront
Weedmaps
API + storefront
Treez
API + storefront
Blaze
API + storefront
Dispense
API + storefront
Sweed
API
Under the hood
A small, sharp service mesh.
Six containers run the operation: a scraper pipeline, three reports services, an API, an email gateway, plus Postgres and Redis. A controller container watches everything and exposes an operator CLI.
You never see any of that. You see the email.
hawk-scraper · pipeline across nine platforms
prycehawk-reports · three report types + scheduler
cannquest-api · public REST API (FastAPI + asyncpg)
prycehawk-email · SMTP and Microsoft Graph delivery
Postgres 17 with pg_trgm + Redis 7 cache
Optional Cloudflare Tunnel for the public API
Closed beta
Get on the list.
New stores get added when there is an operator on the other end watching the alerts. Tell us about yours.