scrapercity 1.0.11 → 1.0.13
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 +11 -4
- package/README.md +1 -1
- package/SKILL.md +3 -3
- package/bin/cli.mjs +9 -4
- package/bin/mcp.mjs +7 -2
- package/lib/catalog.generated.mjs +24 -22
- package/package.json +1 -1
package/AGENT_DOCS.txt
CHANGED
|
@@ -183,18 +183,25 @@ GET /api/v1/apollo-status
|
|
|
183
183
|
Returns: { useApify, message } - check if Apollo URL endpoint is available
|
|
184
184
|
|
|
185
185
|
────────────────────────────────────────
|
|
186
|
-
DATABASES (GET, $
|
|
186
|
+
DATABASES (GET, $149/mo plan and up, 100k new records/day)
|
|
187
187
|
────────────────────────────────────────
|
|
188
188
|
|
|
189
189
|
GET /api/v1/database/leads?title=CTO&country=United States&hasEmail=true&page=1&limit=100
|
|
190
190
|
Filters: title, industry, country, state, city, companyName, companyDomain,
|
|
191
|
-
|
|
191
|
+
seniority, department, hasEmail, hasPhone, minEmployees, maxEmployees, socialUrl
|
|
192
192
|
Array params use repeated keys: ?seniority=vp&seniority=director
|
|
193
|
-
|
|
193
|
+
Optional:
|
|
194
|
+
excludeDelivered=true skip leads this account already has (from the API or the
|
|
195
|
+
dashboard). For daily pulls. Keep page=1 (or use after).
|
|
196
|
+
after=<id> cursor paging in id order. Send after=0 first, then
|
|
197
|
+
pagination.next_after from each response until it is null.
|
|
198
|
+
Every lead returned is saved to your account. Only NEW leads count toward the
|
|
199
|
+
100k/day limit; fetching a lead you already have again is free.
|
|
200
|
+
Returns: { data: [...leads], pagination: { page, limit, total, totalPages, has_more, next_after }, rate_limit }
|
|
194
201
|
|
|
195
202
|
GET /api/v1/database/local-businesses?...
|
|
196
203
|
GET /api/v1/database/ecommerce?...
|
|
197
|
-
Same pattern, different datasets.
|
|
204
|
+
Same pattern (including excludeDelivered and after), different datasets.
|
|
198
205
|
|
|
199
206
|
────────────────────────────────────────
|
|
200
207
|
ERROR CODES
|
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ curl -O https://app.scrapercity.com/api/downloads/RUN_ID \
|
|
|
104
104
|
| **Store Leads** | Shopify/WooCommerce stores with contacts | $0.0039/lead |
|
|
105
105
|
| **BuiltWith** | All sites using a technology | $4.99/search |
|
|
106
106
|
| **Criminal Records** | Background check by name | $1.00 if found |
|
|
107
|
-
| **Lead Database** | 3M+ B2B contacts, instant query ($
|
|
107
|
+
| **Lead Database** | 3M+ B2B contacts, instant query ($149/mo plan and up) | Included |
|
|
108
108
|
|
|
109
109
|
## How It Works
|
|
110
110
|
|
package/SKILL.md
CHANGED
|
@@ -79,9 +79,9 @@ Apollo scrapes take **up to 4 days** to deliver. Do NOT poll in a loop.
|
|
|
79
79
|
| POST | `/api/v1/scrape/cancel/{runId}` | Cancel running job |
|
|
80
80
|
| GET | `/api/v1/scrape/logs/{runId}` | Run logs |
|
|
81
81
|
| GET | `/api/v1/apollo-status` | Apollo service health |
|
|
82
|
-
| GET | `/api/v1/database/leads?title=CTO&country=
|
|
83
|
-
| GET | `/api/v1/database/local-businesses?...` | Local biz DB ($
|
|
84
|
-
| GET | `/api/v1/database/ecommerce?...` | Ecommerce DB ($
|
|
82
|
+
| GET | `/api/v1/database/leads?title=CTO&country=United%20States&hasEmail=true&limit=100` | Lead DB ($149/mo plan and up, 100k new leads/day). Optional: `excludeDelivered=true` (only leads you don't have yet), `after=0` then `pagination.next_after` (cursor paging) |
|
|
83
|
+
| GET | `/api/v1/database/local-businesses?...` | Local biz DB ($149/mo plan and up). Same optional `excludeDelivered` / `after` |
|
|
84
|
+
| GET | `/api/v1/database/ecommerce?...` | Ecommerce DB ($149/mo plan and up). Same optional `excludeDelivered` / `after` |
|
|
85
85
|
|
|
86
86
|
## Status Values
|
|
87
87
|
`RUNNING` → `SUCCEEDED` or `FAILED` or `CANCELLED`
|
package/bin/cli.mjs
CHANGED
|
@@ -365,12 +365,12 @@ async function main() {
|
|
|
365
365
|
break
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
// ── Database: Leads ($
|
|
368
|
+
// ── Database: Leads ($149/mo plan and up) ─────────────
|
|
369
369
|
case 'db-leads': {
|
|
370
370
|
const params = {}
|
|
371
371
|
for (const f of ['--title', '--industry', '--country', '--state', '--city',
|
|
372
372
|
'--company', '--domain', '--company-size', '--seniority',
|
|
373
|
-
'--department', '--page', '--limit', '--min-employees', '--max-employees']) {
|
|
373
|
+
'--department', '--page', '--limit', '--min-employees', '--max-employees', '--after']) {
|
|
374
374
|
const v = flag(f)
|
|
375
375
|
if (v === undefined) continue
|
|
376
376
|
const key = { '--title': 'title', '--industry': 'industry', '--country': 'country',
|
|
@@ -378,13 +378,16 @@ async function main() {
|
|
|
378
378
|
'--domain': 'companyDomain', '--company-size': 'companySize',
|
|
379
379
|
'--seniority': 'seniority', '--department': 'department',
|
|
380
380
|
'--page': 'page', '--limit': 'limit',
|
|
381
|
-
'--min-employees': 'minEmployees', '--max-employees': 'maxEmployees'
|
|
381
|
+
'--min-employees': 'minEmployees', '--max-employees': 'maxEmployees',
|
|
382
|
+
'--after': 'after' }[f]
|
|
382
383
|
params[key] = v
|
|
383
384
|
}
|
|
384
385
|
if (flagBool('--has-email')) params.hasEmail = 'true'
|
|
385
386
|
if (flagBool('--has-phone')) params.hasPhone = 'true'
|
|
387
|
+
if (flagBool('--exclude-delivered')) params.excludeDelivered = 'true'
|
|
386
388
|
const r = await sc.dbLeads(params)
|
|
387
389
|
console.log(`${r.pagination?.total || '?'} total leads, page ${r.pagination?.page || 1} of ${r.pagination?.totalPages || '?'}`)
|
|
390
|
+
if (r.pagination?.next_after) console.log(`Next page: --after ${r.pagination.next_after}`)
|
|
388
391
|
console.log(json(r.data?.slice(0, 3) || r))
|
|
389
392
|
if (r.data?.length > 3) console.log(`... and ${r.data.length - 3} more`)
|
|
390
393
|
break
|
|
@@ -440,8 +443,10 @@ ScraperCity CLI - B2B lead generation from your terminal
|
|
|
440
443
|
scrapercity logs <runId> View run logs
|
|
441
444
|
scrapercity runs [--hours 24] List recent runs
|
|
442
445
|
|
|
443
|
-
Database ($
|
|
446
|
+
Database ($149/mo plan and up):
|
|
444
447
|
scrapercity db-leads [filters] Query lead database
|
|
448
|
+
--exclude-delivered Only leads you don't already have
|
|
449
|
+
--after <id> Cursor paging (start with 0, then use the printed next id)
|
|
445
450
|
|
|
446
451
|
Env: SCRAPERCITY_API_KEY=... or scrapercity login
|
|
447
452
|
Docs: https://scrapercity.com/agents
|
package/bin/mcp.mjs
CHANGED
|
@@ -50,7 +50,7 @@ const UTILITY_TOOLS = [
|
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
name: 'query_lead_database',
|
|
53
|
-
description: 'Query the B2B lead database directly. Returns contacts with names, emails, phones, titles, companies. 100 per request
|
|
53
|
+
description: 'Query the B2B lead database directly. Returns contacts with names, emails, phones, titles, companies. 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.',
|
|
54
54
|
inputSchema: { type: 'object', properties: {
|
|
55
55
|
title: { type: 'string', description: 'Job title filter' },
|
|
56
56
|
industry: { type: 'string', description: 'Company industry' },
|
|
@@ -64,7 +64,9 @@ const UTILITY_TOOLS = [
|
|
|
64
64
|
hasEmail: { type: 'boolean', description: 'Only contacts with email' },
|
|
65
65
|
hasPhone: { type: 'boolean', description: 'Only contacts with phone' },
|
|
66
66
|
page: { type: 'number', description: 'Page number (default 1)', default: 1 },
|
|
67
|
-
limit: { type: 'number', description: 'Results per page (max 100)', default: 50 }
|
|
67
|
+
limit: { type: 'number', description: 'Results per page (max 100)', default: 50 },
|
|
68
|
+
excludeDelivered: { type: 'boolean', description: 'Skip leads this account already has (from the API or unlocked in the dashboard). With this on, keep page at 1 or use after.' },
|
|
69
|
+
after: { type: 'string', description: 'Cursor paging: return leads after this lead id. Use "0" to start, then the pagination.next_after from each response.' }
|
|
68
70
|
} }
|
|
69
71
|
}
|
|
70
72
|
]
|
|
@@ -95,6 +97,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
95
97
|
const params = { ...args }
|
|
96
98
|
if (params.hasEmail) params.hasEmail = 'true'
|
|
97
99
|
if (params.hasPhone) params.hasPhone = 'true'
|
|
100
|
+
if (params.excludeDelivered) params.excludeDelivered = 'true'
|
|
101
|
+
else delete params.excludeDelivered
|
|
102
|
+
if (params.after !== undefined && params.after !== null) params.after = String(params.after)
|
|
98
103
|
result = await sc.dbLeads(params)
|
|
99
104
|
break
|
|
100
105
|
}
|
|
@@ -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-09-
|
|
3
|
+
// Generated: 2026-09-28T13:03:17.780Z
|
|
4
4
|
export const TOOLS = [
|
|
5
5
|
{
|
|
6
6
|
"name": "scrape_apollo",
|
|
@@ -559,29 +559,31 @@ export const TOOLS = [
|
|
|
559
559
|
"contacts": {
|
|
560
560
|
"type": "array",
|
|
561
561
|
"items": {
|
|
562
|
-
"type": "object"
|
|
562
|
+
"type": "object",
|
|
563
|
+
"properties": {
|
|
564
|
+
"first_name": {
|
|
565
|
+
"type": "string",
|
|
566
|
+
"description": "Person's first name (required if full_name not provided)"
|
|
567
|
+
},
|
|
568
|
+
"last_name": {
|
|
569
|
+
"type": "string",
|
|
570
|
+
"description": "Person's last name"
|
|
571
|
+
},
|
|
572
|
+
"full_name": {
|
|
573
|
+
"type": "string",
|
|
574
|
+
"description": "Full name (alternative to first_name + last_name)"
|
|
575
|
+
},
|
|
576
|
+
"domain": {
|
|
577
|
+
"type": "string",
|
|
578
|
+
"description": "Company domain (preferred over company_name)"
|
|
579
|
+
},
|
|
580
|
+
"company_name": {
|
|
581
|
+
"type": "string",
|
|
582
|
+
"description": "Company name (use if domain not available)"
|
|
583
|
+
}
|
|
584
|
+
}
|
|
563
585
|
},
|
|
564
586
|
"description": "Array of contact objects to look up"
|
|
565
|
-
},
|
|
566
|
-
"contacts[].first_name": {
|
|
567
|
-
"type": "string",
|
|
568
|
-
"description": "Person's first name (required if full_name not provided)"
|
|
569
|
-
},
|
|
570
|
-
"contacts[].last_name": {
|
|
571
|
-
"type": "string",
|
|
572
|
-
"description": "Person's last name"
|
|
573
|
-
},
|
|
574
|
-
"contacts[].full_name": {
|
|
575
|
-
"type": "string",
|
|
576
|
-
"description": "Full name (alternative to first_name + last_name)"
|
|
577
|
-
},
|
|
578
|
-
"contacts[].domain": {
|
|
579
|
-
"type": "string",
|
|
580
|
-
"description": "Company domain (preferred over company_name)"
|
|
581
|
-
},
|
|
582
|
-
"contacts[].company_name": {
|
|
583
|
-
"type": "string",
|
|
584
|
-
"description": "Company name (use if domain not available)"
|
|
585
587
|
}
|
|
586
588
|
},
|
|
587
589
|
"required": [
|