lacspace-leads
Find local-business leads from Google Maps — free, no API keys.
npx lacspace-leads restaurants --city Kathmandu --area Baneshwor -f xlsxEverything, in one command
lacspace-leads is a complete, keyless lead-generation tool. It sweeps whole cities neighbourhood-by-neighbourhood, verifies emails by MX lookup, normalises phones to E.164, and de-duplicates as it accumulates a master list across runs — everything a real prospecting workflow needs, from the terminal or as a typed library. Every lead lands in your file the moment it's found (CSV, NDJSON, JSON or Excel), so you can watch it grow and Ctrl-C never loses a row; --resume carries on from the file. It captures opening hours, price level, ratings, business status and open-now, filters on all of them, prints run-summary stats, and can pipe straight into lacspace-enrich.
lacspace-leads drives a real browser over Google Maps, so it runs on your machine — not as a hosted button here (that would break Google's Terms and can't run in a serverless function). It's one command to try locally, no setup.
What's inside
Live file, row by row
Each lead is written to your CSV / NDJSON / JSON / Excel file the moment it's found — open it mid-run; Ctrl-C never loses what was collected.
~4 s per listing
Finished leads stream out while the browser opens the next one; website enrichment runs in the background.
Ask for a number
--target 500 keeps searching until it has 500 unique leads. One Google search stops near 120; this sweeps past it.
Map tiling
Re-centres the same query on a grid across the city, walking outwards — no geocoding service, no API key.
City sweep
Comma-separate cities/areas/types and it runs each search, then merges and de-duplicates into one list.
Split by place
--split city writes one file per city or area alongside the master export.
No-website list
--no-website keeps only businesses missing a site — an instant pitch list for web work.
Verified emails
Visit each website to find an email, then MX-verify the domain — keep only deliverable contacts.
8 social networks
Facebook, Instagram, WhatsApp, LinkedIn, X, YouTube, TikTok and Telegram from the business site.
E.164 phones
Normalise every phone to +CC… with one flag — CRM-ready out of the box.
Radius search
Centre on a coordinate and keep only what's within range, sorted nearest-first.
Master list
--append merges each run into your file and de-duplicates, so daily runs build one clean database.
Saved campaigns
Describe repeatable searches + shared options in one --config JSON file; run them on a schedule.
Deep controls
Presets, filters (incl. has-contact / name-exclude), sort, proxy, retries, jitter, concurrency and callbacks.
Any format
JSON, NDJSON, CSV or Excel — plus a built-in converter between all four, both ways.
Resume anything
--resume continues from the rows already in your file (or a sweep's checkpoint) and fills up to --target — nothing re-scraped.
Rich filters
--min-rating / --min-reviews / --open-now / --price / --category / --business-status narrow the list on the spot.
Run summary
--summary prints per-run stats — totals, with-phone/email, average rating, dedupe hits.
How to use it
From your first command to a repeatable workflow.
Your first list, in two minutes
Nothing to install and no account anywhere. You need Node 18+ and a few minutes of a real browser running on your machine.
- Run it with no arguments and answer the questions
The walkthrough asks for a business type, the city, the areas, how many you want and the file format. Every answer has a sensible default, so you can press Enter through it.
npx lacspace-leadsPrefer flags? Everything the walkthrough asks can be passed directly, as in the steps below.
- Or say it in one line
A business type, where to look, and the format you want out. The file lands in the folder you ran it from.
npx lacspace-leads restaurants --city Kathmandu --area Baneshwor -f xlsx - Watch the browser do the work
A real Chromium window opens and walks the map, which is how it works without an API key. Add --headless once you trust it and it runs invisibly.
npx lacspace-leads dentists --city Pokhara --headless -f csv
Getting the number of leads you actually asked for
One Google Maps search stops serving results at roughly 120, so a big --limit quietly returns about 114. --target is the flag that goes past that.
- Ask for a total, not a per-search limit
--target keeps searching until it has that many unique businesses: first every place you named, then tiles of the map around the city, de-duplicating the whole way.
npx lacspace-leads restaurants --city Kathmandu --target 500 -f xlsx-n / --limit still exists and still means listings per single search. Use --target whenever you want more than ~120.
- Name the neighbourhoods you care about
Each area becomes its own search before any tiling happens, so naming them puts your priorities first and usually finishes sooner.
npx lacspace-leads restaurants --city Kathmandu \ --areas "Baneshwor, Thamel, Patan, Lazimpat" --target 400 - Tune how the map is tiled
--step sets the spacing between tiles and --tiles caps how many are tried. Tighter steps find more in a dense city and take longer.
npx lacspace-leads cafes --city Lalitpur --target 600 --step 1.5km --tiles 60If the map genuinely runs out, the tool says so and suggests widening rather than pretending the target was reachable.
Several cities at once
- Cross cities with areas and business types
Comma-separate any of them. Every combination runs as its own search and the results merge into one de-duplicated list.
npx lacspace-leads \ --type "restaurant, cafe" \ --cities "Kathmandu, Lalitpur, Bhaktapur" \ --areas "Baneshwor, Thamel" \ --target 600 -f xlsx - Write one file per city
--split gives each city, area or category its own file next to the master export, which is what you want when handing lists to different people.
npx lacspace-leads gyms --cities "Kathmandu, Pokhara" --target 300 --split city -f xlsx - Pick the run back up if it stops
--resume writes a checkpoint next to the output, so an interrupted sweep continues from the next search instead of re-scraping.
npx lacspace-leads salons --city Kathmandu --areas "Thamel,Patan,Baneshwor" --resume -o salons.csv
Turning listings into a contact list
- Add emails and social profiles
--enrich visits each business website to find an email address and links to eight social networks. It is slower, so it is opt-in.
npx lacspace-leads clinics --city Pokhara --target 200 --enrich -f xlsx - Keep only contacts that can actually receive mail
--verify-emails checks each domain has MX records, and --has-valid-email drops everything that fails.
npx lacspace-leads hotels --city Kathmandu --target 150 \ --enrich --verify-emails --has-valid-email -f csv - Normalise the phone numbers
--country rewrites every phone into international format, which is what a CRM or bulk-SMS tool expects.
npx lacspace-leads pharmacies --city Biratnagar --target 200 --country NP --has-phone
Narrowing to the right prospects
- Find the businesses that need what you sell
--no-website keeps only businesses with no website at all. Pair it with --has-phone and you have a call list for web work.
npx lacspace-leads "beauty salon" --city Pokhara --target 200 \ --no-website --has-phone -f csv - Filter on quality and status
Rating, review count, price tier, category, open-now and business status all filter the list before it is written.
npx lacspace-leads restaurants --city Kathmandu --target 300 \ --min-rating 4 --min-reviews 50 --sort reviews --desc - Choose the columns
A preset picks a sensible bundle, or name exactly the fields you want. Fewer columns means a faster run.
npx lacspace-leads cafes --city Lalitpur --target 200 --preset outreach
Making it a repeatable workflow
- Build one master file that grows
--append merges each run into the same file and de-duplicates, so running weekly builds a single clean database instead of twelve overlapping exports.
npx lacspace-leads restaurants --city Kathmandu --target 300 \ --append -o master.csv - Export only what is new
--dedupe-across drops anything already present in your master file, so the new export contains only businesses you have not seen before.
npx lacspace-leads restaurants --city Kathmandu --target 300 \ --dedupe-across master.csv -o new-this-week.csv - Save the whole campaign in a file
A --config JSON holds the searches and shared options, so the same campaign runs identically every time and can go on a schedule.
npx lacspace-leads --config campaign.json - Use it as a typed library
Everything the CLI does is exported, including the sweep engine, so you can build it into your own tooling.
import { sweepLeads, serialize } from "lacspace-leads"; const { leads, stats } = await sweepLeads({ type: "restaurants", city: "Kathmandu", target: 500, headless: true, country: "NP", }); console.log(stats); // { searches, tiles, unique, saturated } const { data } = serialize(leads, "csv");
When something looks wrong
- It returned far fewer than you asked for
That is the map running out, and the tool says so. Widen it: more areas, more cities, related business types, or a bigger --step so the tiles cover more ground.
npx lacspace-leads --type "restaurant, cafe, bakery" \ --cities "Kathmandu, Lalitpur" --target 800 --step 3km - It found nothing at all
Usually a CAPTCHA or a changed page. Run without --headless to see the window, slow it down with --delay, and try again in a few minutes.
npx lacspace-leads restaurants --city Kathmandu --delay 1500 - Addresses or websites are missing
--no-details skips opening each listing, so only names and map links come back. Filters like --no-website and --split need those details, and will turn them back on for you.
Copy, paste, done
Real commands and snippets — from a one-liner to the typed library.
npx lacspace-leads restaurants --city Kathmandu \
--target 500 -f xlsxSweeps every area you name, then tiles the map, until it has 500 unique businesses.
npx lacspace-leads restaurants \
--cities "Kathmandu, Lalitpur, Bhaktapur" \
--areas "Baneshwor, Thamel" --target 400 --split cityCross-product of cities x areas, de-duplicated, then written out one Excel file per city.
npx lacspace-leads "beauty salon" --city Pokhara \
--target 200 --no-website --has-phone -f csvEvery salon in town missing a website, with a phone number to call.
npx lacspace-leads bars --city Pokhara \
--open-now --price 2 --summaryKeeps places open right now at price level $$, then prints run-summary stats.
npx lacspace-leads cafes --city Kathmandu \
--area "Thamel,Patan,Baneshwor" --resume -o sweep.csvInterrupt it and re-run — --resume continues from the next area, nothing re-scraped.
npx lacspace-leads gyms --city Lalitpur \
--dedupe-across master.csv --append -o new.csvDrops anything already in master.csv, appends only the genuinely new leads.
npx lacspace-leads clinics --city Pokhara \
--enrich-out sites.ndjson -o clinics.csvWrites an NDJSON of sites ready for `lacspace-enrich --input`.
import { searchLeads, serialize } from "lacspace-leads";
const leads = await searchLeads({
city: "Kathmandu", type: "restaurants", limit: 40,
enrich: true, country: "NP", headless: true,
});
const { data } = serialize(leads, "csv");What people build with it
✓ Build a prospect list for cold outreach or field sales
✓ Map every business of a type across a city
✓ Enrich an existing list with phones, emails and socials
✓ Keep a living, de-duplicated master database updated daily
Run lacspace-leads today
Free, open-source, no API keys. It's a CLI and a typed library.
npx lacspace-leads restaurants --city Kathmandu --area Baneshwor -f xlsx