lacspace-leads 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +51 -0
- package/README.md +127 -0
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Lacspace Free Licence
|
|
2
|
+
Version 1.0, August 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Lacspace
|
|
5
|
+
|
|
6
|
+
PREAMBLE
|
|
7
|
+
|
|
8
|
+
This software is published by Lacspace under the Lacspace Free Licence — a free,
|
|
9
|
+
permissive licence that lets you use this software for any purpose, including in
|
|
10
|
+
commercial products and services, at no cost. It grants the same freedoms as
|
|
11
|
+
common permissive open-source licences; the only condition is that this notice
|
|
12
|
+
travels with the software. The canonical, always-current text of this licence is
|
|
13
|
+
maintained at https://lacspace.com/licenses/lacspace-free-1.0
|
|
14
|
+
|
|
15
|
+
GRANT OF RIGHTS
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person or organisation
|
|
18
|
+
obtaining a copy of this software and its associated documentation and data files
|
|
19
|
+
(the "Software"), to deal in the Software without restriction, including without
|
|
20
|
+
limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
21
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
|
22
|
+
Software is furnished to do so, subject to the conditions below. These rights are
|
|
23
|
+
granted for any purpose, personal or commercial, and are perpetual, worldwide,
|
|
24
|
+
non-exclusive, and royalty-free.
|
|
25
|
+
|
|
26
|
+
CONDITIONS
|
|
27
|
+
|
|
28
|
+
The above copyright notice, this permission notice, and the name of this licence
|
|
29
|
+
("Lacspace Free Licence") shall be included in all copies or substantial portions
|
|
30
|
+
of the Software.
|
|
31
|
+
|
|
32
|
+
TRADEMARKS
|
|
33
|
+
|
|
34
|
+
This licence does not grant permission to use the trade names, trademarks, service
|
|
35
|
+
marks, logos, or product names of Lacspace, except as required to reproduce the
|
|
36
|
+
notice above or to describe the origin of the Software in a truthful manner.
|
|
37
|
+
|
|
38
|
+
DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
42
|
+
FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
43
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN
|
|
44
|
+
AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
|
45
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
The Lacspace Free Licence is a source-available, permissive licence and is not (as
|
|
50
|
+
of this version) an OSI-approved licence. In substance it grants the same freedoms
|
|
51
|
+
as the MIT Licence. Learn more at https://lacspace.com/licenses
|
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ That opens a browser, searches Maps for *"restaurants in Baneshwor, Kathmandu"*,
|
|
|
11
11
|
## Why it's different
|
|
12
12
|
|
|
13
13
|
- **Free & keyless** — uses a real browser (via [Playwright](https://playwright.dev)), not a paid Places API.
|
|
14
|
+
- **Ask for a number, get that number** — one Google search stops at ~120 results; `--target 500` keeps searching (every area you name, then tiles of the map) until it has 500 unique businesses.
|
|
14
15
|
- **Sweep a whole city** — comma-separate areas and it runs each search, then **merges and de-duplicates** into one list: `--area "Thamel,Baneshwor,Patan"`.
|
|
15
16
|
- **Search by radius** — centre on a coordinate and keep only what's within range: `--near "27.72,85.32" --radius 2km`. Each lead gets a `distanceKm`, sorted nearest-first.
|
|
16
17
|
- **Accumulate a master list** — `--append` merges each run into your existing file and de-duplicates, so daily runs build one clean database.
|
|
@@ -27,6 +28,132 @@ That opens a browser, searches Maps for *"restaurants in Baneshwor, Kathmandu"*,
|
|
|
27
28
|
- **Robust & polite** — `--proxy`, `--retries`, `--jitter`, per-listing delays and a permission-first prompt before it opens a browser.
|
|
28
29
|
- **Library too** — `import { searchLeads, searchLeadsBatch, searchLeadsDetailed } from "lacspace-leads"`.
|
|
29
30
|
|
|
31
|
+
## How to use it
|
|
32
|
+
|
|
33
|
+
### 1. Run it and answer the questions
|
|
34
|
+
|
|
35
|
+
No flags to learn first. Run it bare and it walks you through business type, city, areas, how many leads you want and the file format — every question has a default, so you can press Enter through it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx lacspace-leads
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Type more than ~120 at the "how many" question and it automatically switches to a full sweep, because a single Google search cannot return more than that.
|
|
42
|
+
|
|
43
|
+
### 2. Or say it in one line
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx lacspace-leads restaurants --city Kathmandu --area Baneshwor -f xlsx
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A real Chromium window opens, walks the map and writes the file into the folder you ran it from. Add `--headless` once you trust it and the window stays hidden.
|
|
50
|
+
|
|
51
|
+
### 3. Ask for the number of leads you actually want
|
|
52
|
+
|
|
53
|
+
`-n / --limit` is the cap for **one search**, and Google itself stops serving a single search at roughly **120 results** — which is why `--limit 500` comes back with about 114. `--target` is the flag that goes past that:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 500 unique restaurants, however many searches that takes
|
|
57
|
+
npx lacspace-leads restaurants --city Kathmandu --target 500 -f xlsx
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
It expands coverage in this order, stopping the moment it has enough:
|
|
61
|
+
|
|
62
|
+
1. **Every place you named** — each city x area x type is its own search.
|
|
63
|
+
2. **Map tiles** — the same query re-centred on a grid of points walking outwards from the city centre. The centre comes from the map itself, so no geocoding service and no API key.
|
|
64
|
+
|
|
65
|
+
Name your neighbourhoods to put the areas you care about first, and to finish sooner:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx lacspace-leads restaurants --city Kathmandu \
|
|
69
|
+
--areas "Baneshwor, Thamel, Patan, Lazimpat" --target 400
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Tune the grid with `--step` (spacing between tiles — tighter finds more in a dense city) and `--tiles` (how far out to go):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx lacspace-leads cafes --city Lalitpur --target 600 --step 1.5km --tiles 60
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If the map genuinely runs out before the target, it tells you instead of pretending:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
! The map ran out of new results at 214 — that is everything Google lists here.
|
|
82
|
+
Widen it: more areas, more cities, a bigger --step, or related --types.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 4. Several cities, several areas, several business types
|
|
86
|
+
|
|
87
|
+
Comma-separate any of them. Every combination becomes its own search and the results merge into one de-duplicated list:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx lacspace-leads \
|
|
91
|
+
--type "restaurant, cafe" \
|
|
92
|
+
--cities "Kathmandu, Lalitpur, Bhaktapur" \
|
|
93
|
+
--areas "Baneshwor, Thamel" \
|
|
94
|
+
--target 600 -f xlsx
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Add `--split city` to also write one file per city (or `area`, or `type`) beside the master export:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx lacspace-leads gyms --cities "Kathmandu, Pokhara" --target 300 --split city -f xlsx
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Long sweeps are resumable — `--resume` checkpoints after every search, so an interruption continues instead of re-scraping.
|
|
104
|
+
|
|
105
|
+
### 5. Turn listings into contacts
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Emails + social profiles from each business website
|
|
109
|
+
npx lacspace-leads clinics --city Pokhara --target 200 --enrich -f xlsx
|
|
110
|
+
|
|
111
|
+
# Only addresses whose domain really accepts mail
|
|
112
|
+
npx lacspace-leads hotels --city Kathmandu --target 150 \
|
|
113
|
+
--enrich --verify-emails --has-valid-email -f csv
|
|
114
|
+
|
|
115
|
+
# Phones in international format, ready for a CRM or bulk SMS
|
|
116
|
+
npx lacspace-leads pharmacies --city Biratnagar --target 200 --country NP --has-phone
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 6. Narrow it to the right prospects
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Businesses with NO website — the pitch list for web work
|
|
123
|
+
npx lacspace-leads "beauty salon" --city Pokhara --target 200 --no-website --has-phone -f csv
|
|
124
|
+
|
|
125
|
+
# Only well-reviewed places, best first
|
|
126
|
+
npx lacspace-leads restaurants --city Kathmandu --target 300 \
|
|
127
|
+
--min-rating 4 --min-reviews 50 --sort reviews --desc
|
|
128
|
+
|
|
129
|
+
# Just the columns an outreach list needs
|
|
130
|
+
npx lacspace-leads cafes --city Lalitpur --target 200 --preset outreach
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 7. Make it repeatable
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# One master file that grows and de-duplicates every run
|
|
137
|
+
npx lacspace-leads restaurants --city Kathmandu --target 300 --append -o master.csv
|
|
138
|
+
|
|
139
|
+
# Export only the businesses that aren't already in it
|
|
140
|
+
npx lacspace-leads restaurants --city Kathmandu --target 300 \
|
|
141
|
+
--dedupe-across master.csv -o new-this-week.csv
|
|
142
|
+
|
|
143
|
+
# The whole campaign saved in one file, ready for a schedule
|
|
144
|
+
npx lacspace-leads --config campaign.json
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### When something looks wrong
|
|
148
|
+
|
|
149
|
+
| What you see | What it means | What to do |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| Far fewer leads than the target | The map ran out — that really is everything Google lists for that query | More areas or cities, related `--type`s, or a bigger `--step` |
|
|
152
|
+
| About 114 back from `--limit 500` | Google's per-search ceiling | Use `--target 500` instead |
|
|
153
|
+
| No leads at all | Usually a CAPTCHA or a page change | Drop `--headless` to watch it, raise `--delay`, try again shortly |
|
|
154
|
+
| Empty address / website columns | `--no-details` was on, so listings were never opened | Remove it (`--no-website` and `--split` turn details back on for you) |
|
|
155
|
+
| Everything grouped under "other" with `--split` | Same cause — no addresses to match against | Same fix |
|
|
156
|
+
|
|
30
157
|
## Install
|
|
31
158
|
|
|
32
159
|
Needs **Node 20+** and a Chromium-based browser. It uses your installed **Google Chrome** or **Microsoft Edge** automatically; if you have neither, run:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lacspace-leads",
|
|
3
|
-
"version": "1.7.
|
|
4
|
-
"description": "Free, open-source local-business lead finder
|
|
3
|
+
"version": "1.7.2",
|
|
4
|
+
"description": "Free, open-source local-business lead finder \u2014 name a city/area/business type, or search by coordinates + radius, and it drives a real browser over Google Maps to collect names, phones, websites, ratings, addresses, emails and social links, then exports to JSON, NDJSON, CSV or Excel. Sweep multiple areas at once, verify emails by MX, normalise phones to E.164, accumulate into a master file, and enrich in parallel through an optional proxy. No API keys.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"lacspace-leads": "dist/cli.js"
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
-
"README.md"
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
23
24
|
],
|
|
24
25
|
"scripts": {
|
|
25
26
|
"build": "tsup",
|