Find local businesses with no real website → verify WhatsApp → message them.
Built for Kosovo & Albania operators. Runs on your PC in minutes — or use the live CRM.
Cold outreach dies when half the list is a Facebook page with no phone, or a number that was never on WhatsApp.
Balkan Leads scrapes Google Places for businesses that look like real opportunities (weak or missing website), drops them into a CRM with clear tabs, then lets you prove WhatsApp on your own computer before you waste time messaging ghosts.
No SaaS tax. No “upload your leads to our cloud only.” Friends download the repo, double-click a few .bat files, and they’re scraping on their own PC.
SCRAPE CRM VERIFY OUTREACH
Places API → Scraped / Verified → QR on YOUR PC → Copy or open WA
city+keyword Trash / Has website Chrome + phone +383 / +355
| Your PC (recommended) | Live CRM | |
|---|---|---|
| Best for | Friends, private lists, full control | Quick try / shared hosting |
| Data | Stays in web/data/ on that computer |
Per-account in the cloud |
| Start | SETUP.bat → START-CRM.bat |
lead-crm.vendorstore.workers.dev |
| WhatsApp verify | Always on your PC | Export CSV → verify on PC → import |
Tip: leave Supabase URL/keys empty in
web\.env.localfor local mode.
Need once: Node.js LTS + a free Google Places API (New) key.
1. Code → Download ZIP (or git clone)
2. Unzip
3. Double-click SETUP.bat
4. In web\.env.local set:
GOOGLE_PLACES_API_KEY=your_key_here
(leave Supabase lines empty)
5. Double-click START-CRM.bat
6. Browser opens → Create an account → Scrape
| Double-click | What happens |
|---|---|
SETUP.bat |
Installs everything (first time) |
START-CRM.bat |
Local CRM at http://localhost:3000 |
START-SCRAPE.bat |
CLI scrape (prompts for country / city / keyword) |
START-VERIFY.bat |
Drag a verify CSV onto it → scan WhatsApp QR |
START HERE.txt |
Shortest human guide |
HOW-TO-USE.txt |
Full simple walkthrough |
No email verification. Your leads never leave the machine unless you choose the live site.
- Google Places API (New) — country + city + keyword or whole category batch
- Keeps weak / missing websites; real sites land in Has website
- Dedupes by Google
place_id - Optional second check via Google Custom Search (
GOOGLE_CSE_ID) - Blocked categories on purpose (barber, tattoo, massage/spa, nightclub, casino, adult, etc.)
- Strong bias for Kosovo & Albania cities (Prizren, Pristina, Tirana, …)
- Sign up / login (username + password — no email)
- Each account = its own leads & scrape jobs
- Tabs: Scraped · Verified · Trash · Has website
- Statuses: new / contacted / replied / skipped / archived
- Bulk actions, search, phone filter, rating sort
- Export full CSV · Export for WhatsApp verify
- Import verify results (match by phone → Verified / Trash)
- Outreach message → Copy or open WhatsApp (
+383/+355) - In-app guide at
/guide
- Real Chrome session via
whatsapp-web.js - Scan QR with your phone
- Result CSV imports straight back into the CRM
Food & Drink · Health & Medical · Fitness · Retail & Shops · Automotive · Professional Services · Trades & Construction · Home Services · Hospitality & Travel · Education & Kids · Events & Media · Other Local Businesses
CLI example:
npm run batch -- -c "Prizren" -C "Kosovo" --category healthnpm install
cp .env.example .env # set GOOGLE_PLACES_API_KEY
npm run scrape -- -k "dentist" -c "Prizren" -C "Kosovo"
npm run batch -- -c "Prizren" -C "Kosovo" --category automotive
npm run leads
npm run keywords
npm run dashboard
npm run history
npm run verify -- -i "path\to\leads-for-whatsapp-verify.csv" --openBinary name after build: balkan-leads.
| Variable | Needed? |
|---|---|
GOOGLE_PLACES_API_KEY |
Yes |
GOOGLE_CSE_ID |
Optional — better website double-check |
WEBSITE_VERIFICATION_ENABLED |
Optional (default true) |
| Variable | Needed? |
|---|---|
GOOGLE_PLACES_API_KEY |
Yes to scrape |
AUTH_SECRET |
Recommended (session signing) |
OUTREACH_NAME |
Optional |
GOOGLE_CSE_ID |
Optional |
NEXT_PUBLIC_SUPABASE_URL + keys |
Empty = local JSON DB · set only for shared cloud |
Scraper/
├── SETUP.bat / START-*.bat ← double-click these
├── START HERE.txt ← read first
├── HOW-TO-USE.txt
├── docs/assets/ ← banners for this README
├── src/ ← CLI scrape + WhatsApp verify
├── web/ ← Next.js CRM (local + Cloudflare)
├── supabase/ ← cloud DB migrations (owner)
├── data/ output/ exports/ ← CLI artifacts
└── LICENSE ← MIT
More: web/README.md · web/DEPLOY.md · in-app /guide
| Layer | Tech |
|---|---|
| CLI | Node, TypeScript, Commander, ExcelJS, whatsapp-web.js |
| CRM | Next.js 16, React 19, Tailwind 4 |
| Local data | JSON file (web/data/) |
| Live data | Supabase |
| Live host | Cloudflare Workers (OpenNext) |
Do I need the live website?
No. PC mode is the main path for friends.
Do I need Supabase?
Not for local use. Leave those env lines blank.
Why won’t WhatsApp verify run in the browser?
It needs a real Chrome profile + QR on a physical machine. Export → START-VERIFY.bat → import.
Can two people share one PC install?
Use separate OS users / folders, or the live CRM with separate signups.
Why are some keywords blocked?
Intentional — categories that don’t fit this outreach product.
Google Places costs money?
You need a Google Cloud key; free tier usually covers light testing. Monitor usage in Cloud Console.
| Symptom | Fix |
|---|---|
SETUP.bat says no Node |
Install Node LTS, reopen the folder, run again |
| Scrape returns nothing | Check API key + Places API (New) enabled; try a bigger city |
| CRM opens but scrape fails | Confirm GOOGLE_PLACES_API_KEY in web\.env.local |
| Live login/signup fails (owner) | Run FIX-DATABASE.bat / supabase/FIX_RLS.sql |
| WhatsApp QR never appears | Close other Chrome WhatsApp sessions; run START-VERIFY.bat again |
- Star the repo if it saves you time — it helps others find it
- Fork → improve keywords / cities / UX → open a PR
- Share this link: https://github.com/DhurimHalili/Scraper
- Live try: https://lead-crm.vendorstore.workers.dev
Please don’t commit .env, .env.local, or WhatsApp session folders.
MIT © 2026 Dhurim Halili
Built for operators who actually send the message.

