scrapercity 1.0.22 → 1.0.23
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/AGENT_DOCS.txt +3 -0
- package/SKILL.md +1 -1
- package/bin/cli.mjs +9 -0
- package/bin/mcp.mjs +13 -0
- package/lib/catalog.generated.mjs +1 -1
- package/lib/client.mjs +18 -0
- package/package.json +1 -1
package/AGENT_DOCS.txt
CHANGED
|
@@ -276,6 +276,9 @@ GET /api/v1/autoleads/lookalike?id=<job id>
|
|
|
276
276
|
filters to that database's endpoint to pull the records. $0.01 per site read, from credits when the
|
|
277
277
|
job finishes; sites that can't be read are free. 402 = balance under $0.01 x every site (required,
|
|
278
278
|
available). 409 = a job is already running (job_id). At least 3 company sites; personal emails skipped.
|
|
279
|
+
GET /api/v1/autoleads/lookalike?id=<job id>&format=csv returns the finished job as a CSV, one row per
|
|
280
|
+
site: Domain, Read, Group, Sells, Sells To, Business Model, Industry, Keywords, Size, Country,
|
|
281
|
+
Contact Emails, Contact Titles. No extra charge.
|
|
279
282
|
|
|
280
283
|
────────────────────────────────────────
|
|
281
284
|
ERROR CODES
|
package/SKILL.md
CHANGED
|
@@ -82,7 +82,7 @@ Apollo scrapes take **up to 4 days** to deliver. Do NOT poll in a loop.
|
|
|
82
82
|
| GET | `/api/v1/database/local-businesses?category=Dentist&country=US&hasContact=true&limit=100` | Local biz DB ($149/mo plan and up, 100k new businesses/day). Search like Google Maps: `keyword` (repeat; names and categories, any keyword) and `location` (repeat; cities, states, countries, postal codes), with `searched_as` in the response and `lead_database` when nothing is found but the Lead Database has 100+ people. Filters: `category`, `country`, `state`, `city`, `postalCode`, `query`, `minRating`/`maxRating`, `minReviews`/`maxReviews`, `hasEmail`, `hasPhone`, `hasWebsite`, `hasContact` (only businesses with a named contact person), `title` (business name), `box=minLat,minLng,maxLat,maxLng` (a map area). Exclusions: `notCategory`. `url=<Google Maps search URL>` searches with that URL's keyword and place. POST with a JSON body takes the same parameters (use it for a long `url`). Same optional `excludeDelivered` / `after` |
|
|
83
83
|
| GET | `/api/v1/database/ecommerce?...` | Ecommerce DB ($149/mo plan and up). Same optional `excludeDelivered` / `after`. Technologies: `technologies` (any of), `technologiesAll` (all of), `notTechnologies` (none of) |
|
|
84
84
|
| POST | `/api/v1/database/plan` | $149/mo plan and up (GET with `?query=` also works). `{ "query": "dentists in Austin", "database"?: "leads" or "local" or "ecommerce" }` -> ready-to-run searches: `{ targeting, searches: [{ database, name, filters, count, apiEndpoint, apiParams, link }] }`. Send `apiParams` as they are to `/api/v1/<apiEndpoint>` |
|
|
85
|
-
| POST | `/api/v1/autoleads/lookalike` | $149/mo plan and up, $0.01 per site read. `{ "domains": ["acme.com", "mike@globex.com", ...] }` (websites or work emails, at least 3 company sites) -> 202 `{ job }`. Then GET `/api/v1/autoleads/lookalike?id=<job id>` until `job.status` is `done`: `job.groups` = `[{ name, description, sites, database, filters, count, tool }]`. Send a group's `filters` to that database's endpoint. 402 = balance under $0.01 x every site; 409 = a job is already running |
|
|
85
|
+
| POST | `/api/v1/autoleads/lookalike` | $149/mo plan and up, $0.01 per site read. `{ "domains": ["acme.com", "mike@globex.com", ...] }` (websites or work emails, at least 3 company sites) -> 202 `{ job }`. Then GET `/api/v1/autoleads/lookalike?id=<job id>` until `job.status` is `done`: `job.groups` = `[{ name, description, sites, database, filters, count, tool }]`. Send a group's `filters` to that database's endpoint. 402 = balance under $0.01 x every site; 409 = a job is already running. Add `&format=csv` to the GET for every site as a CSV (no extra charge) |
|
|
86
86
|
|
|
87
87
|
## Status Values
|
|
88
88
|
`RUNNING` → `SUCCEEDED` or `FAILED` or `CANCELLED`
|
package/bin/cli.mjs
CHANGED
|
@@ -486,6 +486,14 @@ async function main() {
|
|
|
486
486
|
break
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
+
case 'lookalike-csv': {
|
|
490
|
+
const out = flag('-o') || flag('--output')
|
|
491
|
+
if (!args[0]) die('Usage: scrapercity lookalike-csv <jobId> [-o lookalike.csv]')
|
|
492
|
+
const dl = await sc.lookalikeCsv(args[0], typeof out === 'string' ? out : undefined)
|
|
493
|
+
console.log(`✓ Saved ${dl.path} (${Math.round(dl.bytes / 1024)} KB)`)
|
|
494
|
+
break
|
|
495
|
+
}
|
|
496
|
+
|
|
489
497
|
case 'lookalike-status': {
|
|
490
498
|
if (!args[0]) die('Usage: scrapercity lookalike-status <jobId>')
|
|
491
499
|
console.log(json((await sc.lookalikeJob(args[0])).job))
|
|
@@ -550,6 +558,7 @@ ScraperCity CLI - B2B lead generation from your terminal
|
|
|
550
558
|
scrapercity lookalike acme.com mike@globex.com ... Group your customers into lookalike audiences
|
|
551
559
|
--file customers.txt One website or work email per line
|
|
552
560
|
scrapercity lookalike-status <jobId> Read a lookalike job
|
|
561
|
+
scrapercity lookalike-csv <jobId> [-o f.csv] Every site of a finished job as a CSV
|
|
553
562
|
|
|
554
563
|
Database ($149/mo plan and up):
|
|
555
564
|
scrapercity db-leads [filters] Query lead database
|
package/bin/mcp.mjs
CHANGED
|
@@ -70,6 +70,14 @@ const UTILITY_TOOLS = [
|
|
|
70
70
|
id: { type: 'string', description: 'The job id from find_lookalike_groups' }
|
|
71
71
|
}, required: ['id'] }
|
|
72
72
|
},
|
|
73
|
+
{
|
|
74
|
+
name: 'download_lookalike_csv',
|
|
75
|
+
description: 'Save a finished lookalike job (find_lookalike_groups) as a CSV file, one row per uploaded site: whether it was read, what it sells and to whom, business model, industry, keywords, size, country, the contacts from your upload with their titles, and its group. No extra charge.',
|
|
76
|
+
inputSchema: { type: 'object', properties: {
|
|
77
|
+
id: { type: 'string', description: 'The job id from find_lookalike_groups' },
|
|
78
|
+
outputPath: { type: 'string', description: 'File path to save the CSV (default: lookalike-{id}.csv)' }
|
|
79
|
+
}, required: ['id'] }
|
|
80
|
+
},
|
|
73
81
|
{
|
|
74
82
|
name: 'query_lead_database',
|
|
75
83
|
description: 'Query the B2B lead database directly. Returns contacts with names, emails, phones, titles, companies (plus company website, revenue, HQ location and keywords). Up to 100 per request. Included with the $149/mo plan (100,000 new leads a day; leads you already have do not count again). For a daily pull of only new leads set excludeDelivered=true. For big pulls page with after: send after="0" first, then the pagination.next_after from each response until it is null. Have a saved people-search URL? Pass it as url to search with its filters right away (search_translation in the response says what was applied). Target by the technologies a company\'s website runs: technologies (any of), technologiesAll (all of), notTechnologies (none of), e.g. technologiesAll ["Klaviyo", "PayPal", "Shopify"] with notTechnologies ["Facebook Pixel"].',
|
|
@@ -196,6 +204,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
196
204
|
case 'plan_search': result = await sc.planSearch(args.query, args.database); break
|
|
197
205
|
case 'find_lookalike_groups': result = await sc.lookalikeStart(args.domains); break
|
|
198
206
|
case 'get_lookalike_groups': result = await sc.lookalikeJob(args.id); break
|
|
207
|
+
case 'download_lookalike_csv': {
|
|
208
|
+
const dl = await sc.lookalikeCsv(args.id, args.outputPath)
|
|
209
|
+
result = { success: true, path: dl.path, sizeKB: Math.round(dl.bytes / 1024) }
|
|
210
|
+
break
|
|
211
|
+
}
|
|
199
212
|
case 'query_lead_database': {
|
|
200
213
|
const params = { ...args }
|
|
201
214
|
if (params.hasEmail) params.hasEmail = 'true'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/generate.mjs — DO NOT EDIT BY HAND.
|
|
2
2
|
// Source of truth: scraperConfigs.ts (+ src/config/scrapers.ts). Regenerate: npm run generate
|
|
3
|
-
// Generated: 2026-10-
|
|
3
|
+
// Generated: 2026-10-27T22:10:20.665Z
|
|
4
4
|
export const TOOLS = [
|
|
5
5
|
{
|
|
6
6
|
"name": "scrape_apollo",
|
package/lib/client.mjs
CHANGED
|
@@ -216,6 +216,24 @@ export const planSearch = (query, database) =>
|
|
|
216
216
|
export const lookalikeStart = (domains) => post('/api/v1/autoleads/lookalike', { domains })
|
|
217
217
|
export const lookalikeJob = (id) => get(`/api/v1/autoleads/lookalike?id=${encodeURIComponent(id)}`)
|
|
218
218
|
|
|
219
|
+
// A finished lookalike job as a CSV file, one row per site (what was read, contacts, group).
|
|
220
|
+
export async function lookalikeCsv(id, outputPath) {
|
|
221
|
+
const key = getApiKey()
|
|
222
|
+
if (!key) throw new Error('No API key. Run: scrapercity login OR export SCRAPERCITY_API_KEY=...')
|
|
223
|
+
const res = await fetch(`${BASE}/api/v1/autoleads/lookalike?id=${encodeURIComponent(id)}&format=csv`, {
|
|
224
|
+
headers: { 'Authorization': `Bearer ${key}`, 'User-Agent': 'scrapercity-cli/1.0' }
|
|
225
|
+
})
|
|
226
|
+
if (!res.ok) {
|
|
227
|
+
let msg = `HTTP ${res.status}`
|
|
228
|
+
try { msg = (await res.json()).error || msg } catch {}
|
|
229
|
+
throw new Error(msg)
|
|
230
|
+
}
|
|
231
|
+
const buf = Buffer.from(await res.arrayBuffer())
|
|
232
|
+
const out = outputPath || `lookalike-${id}.csv`
|
|
233
|
+
fs.writeFileSync(out, buf)
|
|
234
|
+
return { path: out, bytes: buf.length }
|
|
235
|
+
}
|
|
236
|
+
|
|
219
237
|
// ── Poll until done ───────────────────────────────────────────
|
|
220
238
|
export async function pollUntilDone(runId, { interval = 15000, timeout = 3600000, onStatus } = {}) {
|
|
221
239
|
const start = Date.now()
|