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 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-27T21:55:24.779Z
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()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrapercity",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "ScraperCity CLI & MCP Server - B2B lead generation for AI agents",
5
5
  "type": "module",
6
6
  "bin": {