linkedin-secret-sauce 0.12.2 → 0.12.3
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/README.md +292 -13
- package/dist/enrichment/index.d.ts +22 -1
- package/dist/enrichment/index.js +27 -20
- package/dist/enrichment/types.d.ts +10 -0
- package/docs/COSIALL_PROFILE_EMAILS.md +342 -0
- package/docs/ENRICHMENT.md +622 -0
- package/docs/INTEGRATION.md +405 -0
- package/docs/PLAYGROUND.md +558 -0
- package/docs/SALES_SEARCH.md +171 -0
- package/docs/api/.nojekyll +1 -0
- package/docs/api/assets/hierarchy.js +1 -0
- package/docs/api/assets/highlight.css +92 -0
- package/docs/api/assets/icons.js +18 -0
- package/docs/api/assets/icons.svg +1 -0
- package/docs/api/assets/main.js +60 -0
- package/docs/api/assets/navigation.js +1 -0
- package/docs/api/assets/search.js +1 -0
- package/docs/api/assets/style.css +1633 -0
- package/docs/api/classes/LinkedInClientError.html +37 -0
- package/docs/api/functions/_testGetAccountCookies.html +4 -0
- package/docs/api/functions/_testGetAccountEntry.html +4 -0
- package/docs/api/functions/_testGetAllAccountIds.html +3 -0
- package/docs/api/functions/_testGetPoolState.html +3 -0
- package/docs/api/functions/adminResetAccount.html +1 -0
- package/docs/api/functions/adminSetCooldown.html +1 -0
- package/docs/api/functions/buildCookieHeader.html +1 -0
- package/docs/api/functions/clearAllSmartLeadTokens.html +2 -0
- package/docs/api/functions/clearRequestHistory.html +1 -0
- package/docs/api/functions/clearSessionAccount.html +1 -0
- package/docs/api/functions/clearSmartLeadToken.html +2 -0
- package/docs/api/functions/createEnrichmentClient.html +8 -0
- package/docs/api/functions/extractCsrfToken.html +1 -0
- package/docs/api/functions/extractLinkedInHandle.html +7 -0
- package/docs/api/functions/fetchCookiesFromCosiall.html +14 -0
- package/docs/api/functions/fetchProfileEmailsFromCosiall.html +18 -0
- package/docs/api/functions/forceRefreshCookies.html +1 -0
- package/docs/api/functions/getAccountForSession.html +1 -0
- package/docs/api/functions/getAccountsSummary.html +1 -0
- package/docs/api/functions/getCompaniesBatch.html +5 -0
- package/docs/api/functions/getCompanyById.html +9 -0
- package/docs/api/functions/getCompanyByUrl.html +1 -0
- package/docs/api/functions/getConfig.html +1 -0
- package/docs/api/functions/getCookiePoolHealth.html +1 -0
- package/docs/api/functions/getProfileByUrn.html +17 -0
- package/docs/api/functions/getProfileByVanity.html +10 -0
- package/docs/api/functions/getProfilesBatch.html +1 -0
- package/docs/api/functions/getRequestHistory.html +1 -0
- package/docs/api/functions/getSalesNavigatorProfileDetails.html +1 -0
- package/docs/api/functions/getSalesNavigatorProfileFull.html +16 -0
- package/docs/api/functions/getSmartLeadToken.html +1 -0
- package/docs/api/functions/getSmartLeadTokenCacheStats.html +2 -0
- package/docs/api/functions/getSmartLeadUser.html +2 -0
- package/docs/api/functions/getSnapshot.html +1 -0
- package/docs/api/functions/getYearsAtCompanyOptions.html +2 -0
- package/docs/api/functions/getYearsInPositionOptions.html +2 -0
- package/docs/api/functions/getYearsOfExperienceOptions.html +2 -0
- package/docs/api/functions/incrementMetric.html +1 -0
- package/docs/api/functions/initializeCookiePool.html +1 -0
- package/docs/api/functions/initializeLinkedInClient.html +1 -0
- package/docs/api/functions/isBusinessEmail.html +4 -0
- package/docs/api/functions/isDisposableDomain.html +4 -0
- package/docs/api/functions/isDisposableEmail.html +4 -0
- package/docs/api/functions/isPersonalDomain.html +4 -0
- package/docs/api/functions/isPersonalEmail.html +4 -0
- package/docs/api/functions/isRoleAccount.html +4 -0
- package/docs/api/functions/isValidEmailSyntax.html +4 -0
- package/docs/api/functions/parseFullProfile.html +15 -0
- package/docs/api/functions/parseSalesSearchResults.html +1 -0
- package/docs/api/functions/reportAccountFailure.html +1 -0
- package/docs/api/functions/reportAccountSuccess.html +1 -0
- package/docs/api/functions/resolveCompanyUniversalName.html +1 -0
- package/docs/api/functions/searchSalesLeads.html +16 -0
- package/docs/api/functions/selectAccountForRequest.html +1 -0
- package/docs/api/functions/setAccountForSession.html +1 -0
- package/docs/api/functions/typeahead.html +1 -0
- package/docs/api/functions/verifyEmailMx.html +1 -0
- package/docs/api/hierarchy.html +1 -0
- package/docs/api/index.html +12 -0
- package/docs/api/interfaces/AccountCookies.html +4 -0
- package/docs/api/interfaces/BatchEnrichmentOptions.html +14 -0
- package/docs/api/interfaces/CacheAdapter.html +6 -0
- package/docs/api/interfaces/CanonicalEmail.html +14 -0
- package/docs/api/interfaces/Company.html +17 -0
- package/docs/api/interfaces/ConstructConfig.html +8 -0
- package/docs/api/interfaces/CosiallProfileEmailsResponse.html +11 -0
- package/docs/api/interfaces/DropcontactConfig.html +3 -0
- package/docs/api/interfaces/EnrichmentCandidate.html +34 -0
- package/docs/api/interfaces/EnrichmentClient.html +10 -0
- package/docs/api/interfaces/EnrichmentClientConfig.html +12 -0
- package/docs/api/interfaces/EnrichmentLogger.html +6 -0
- package/docs/api/interfaces/EnrichmentOptions.html +10 -0
- package/docs/api/interfaces/HunterConfig.html +3 -0
- package/docs/api/interfaces/LddConfig.html +4 -0
- package/docs/api/interfaces/LddProfileData.html +6 -0
- package/docs/api/interfaces/LinkedInClientConfig.html +20 -0
- package/docs/api/interfaces/LinkedInCookie.html +9 -0
- package/docs/api/interfaces/LinkedInPosition.html +14 -0
- package/docs/api/interfaces/LinkedInProfile.html +21 -0
- package/docs/api/interfaces/LinkedInSpotlightBadge.html +5 -0
- package/docs/api/interfaces/LinkedInTenure.html +3 -0
- package/docs/api/interfaces/Metrics.html +22 -0
- package/docs/api/interfaces/MetricsSnapshot.html +23 -0
- package/docs/api/interfaces/ProfileEducation.html +8 -0
- package/docs/api/interfaces/ProfileEmailsLookupOptions.html +9 -0
- package/docs/api/interfaces/ProfilePosition.html +12 -0
- package/docs/api/interfaces/ProfileSkill.html +3 -0
- package/docs/api/interfaces/ProviderResult.html +11 -0
- package/docs/api/interfaces/ProvidersConfig.html +17 -0
- package/docs/api/interfaces/RequestHistoryEntry.html +8 -0
- package/docs/api/interfaces/SalesLeadSearchResult.html +31 -0
- package/docs/api/interfaces/SalesNavigatorContactInfo.html +5 -0
- package/docs/api/interfaces/SalesNavigatorPosition.html +11 -0
- package/docs/api/interfaces/SalesNavigatorProfile.html +9 -0
- package/docs/api/interfaces/SalesNavigatorProfileFull.html +24 -0
- package/docs/api/interfaces/SearchSalesResult.html +5 -0
- package/docs/api/interfaces/SmartLeadAuthConfig.html +6 -0
- package/docs/api/interfaces/SmartLeadCredentials.html +3 -0
- package/docs/api/interfaces/SmartLeadLoginResponse.html +3 -0
- package/docs/api/interfaces/SmartLeadUser.html +8 -0
- package/docs/api/interfaces/SmartProspectConfig.html +19 -0
- package/docs/api/interfaces/SmartProspectContact.html +24 -0
- package/docs/api/interfaces/SmartProspectSearchFilters.html +42 -0
- package/docs/api/interfaces/TypeaheadItem.html +3 -0
- package/docs/api/interfaces/TypeaheadResult.html +3 -0
- package/docs/api/interfaces/VerificationResult.html +16 -0
- package/docs/api/types/CostCallback.html +2 -0
- package/docs/api/types/Geo.html +4 -0
- package/docs/api/types/LddApiResponse.html +1 -0
- package/docs/api/types/ProviderFunc.html +2 -0
- package/docs/api/types/ProviderName.html +2 -0
- package/docs/api/types/SalesSearchFilters.html +7 -0
- package/docs/api/types/TypeaheadType.html +1 -0
- package/docs/api/variables/COMPANY_SIZE_OPTIONS.html +1 -0
- package/docs/api/variables/DEFAULT_PROVIDER_ORDER.html +20 -0
- package/docs/api/variables/DISPOSABLE_DOMAINS.html +2 -0
- package/docs/api/variables/FUNCTION_OPTIONS.html +1 -0
- package/docs/api/variables/INDUSTRY_OPTIONS.html +1 -0
- package/docs/api/variables/LANGUAGE_OPTIONS.html +1 -0
- package/docs/api/variables/PERSONAL_DOMAINS.html +2 -0
- package/docs/api/variables/PROVIDER_COSTS.html +15 -0
- package/docs/api/variables/REGION_OPTIONS.html +1 -0
- package/docs/api/variables/SENIORITY_OPTIONS.html +3 -0
- package/docs/api/variables/YEARS_OPTIONS.html +1 -0
- package/docs/index.html +98 -0
- package/package.json +40 -28
package/README.md
CHANGED
|
@@ -4,11 +4,12 @@ A complete LinkedIn Sales Navigator client + Email Enrichment library for Node.j
|
|
|
4
4
|
|
|
5
5
|
**Two main modules:**
|
|
6
6
|
1. **LinkedIn API** - Sales Navigator search, profiles, companies with automatic cookie/account rotation
|
|
7
|
-
2. **Email Enrichment** - Find business emails via multiple providers (Hunter,
|
|
7
|
+
2. **Email Enrichment** - Find business emails via multiple providers (11 providers including Hunter, Bouncer, TryKitt.ai, BounceBan, Snov.io, etc.)
|
|
8
8
|
|
|
9
9
|
## Documentation
|
|
10
10
|
|
|
11
11
|
- [Integration Guide](docs/INTEGRATION.md) - Step-by-step setup
|
|
12
|
+
- [Email Enrichment Guide](docs/ENRICHMENT.md) - All 11 providers, API keys, costs
|
|
12
13
|
- [Sales Search Guide](docs/SALES_SEARCH.md) - Advanced search filters
|
|
13
14
|
- [Playground Guide](docs/PLAYGROUND.md) - Local dev UI
|
|
14
15
|
- [Cosiall Profile Emails](docs/COSIALL_PROFILE_EMAILS.md) - Profile email lookups
|
|
@@ -79,6 +80,50 @@ console.log(company.name, company.industry, company.employeeCount);
|
|
|
79
80
|
| `LINKEDIN_PROXY_STRING` | No | Proxy in format `host:port` or `host:port:user:pass` |
|
|
80
81
|
| `LOG_LEVEL` | No | `debug`, `info`, `warn`, `error` (default: `info`) |
|
|
81
82
|
|
|
83
|
+
### Advanced Configuration
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
initializeLinkedInClient({
|
|
87
|
+
// Required
|
|
88
|
+
cosiallApiUrl: process.env.COSIALL_API_URL!,
|
|
89
|
+
cosiallApiKey: process.env.COSIALL_API_KEY!,
|
|
90
|
+
|
|
91
|
+
// Optional networking
|
|
92
|
+
proxyString: process.env.LINKEDIN_PROXY_STRING,
|
|
93
|
+
logLevel: 'info',
|
|
94
|
+
|
|
95
|
+
// Cache TTLs (milliseconds)
|
|
96
|
+
profileCacheTtl: 15 * 60 * 1000, // 15 minutes (default)
|
|
97
|
+
searchCacheTtl: 15 * 60 * 1000, // 15 minutes (default)
|
|
98
|
+
companyCacheTtl: 10 * 60 * 1000, // 10 minutes (default)
|
|
99
|
+
typeaheadCacheTtl: 60 * 60 * 1000, // 1 hour (default)
|
|
100
|
+
|
|
101
|
+
// Cookie pool & rotation
|
|
102
|
+
cookieRefreshInterval: 15 * 60 * 1000, // 15 minutes (default)
|
|
103
|
+
accountCooldownMs: 5000, // 5 seconds (default)
|
|
104
|
+
maxFailuresBeforeCooldown: 3, // default
|
|
105
|
+
|
|
106
|
+
// Retry behavior
|
|
107
|
+
maxRetries: 2, // default
|
|
108
|
+
retryDelayMs: 700, // default
|
|
109
|
+
|
|
110
|
+
// Request tracking
|
|
111
|
+
maxRequestHistory: 500, // default
|
|
112
|
+
|
|
113
|
+
// Initialization options
|
|
114
|
+
eagerInitialization: true, // Load cookies immediately (default)
|
|
115
|
+
fallbackWithoutProxyOnError: false, // Retry without proxy on 502/503/504
|
|
116
|
+
|
|
117
|
+
// Error handling
|
|
118
|
+
onInitializationError: (error) => {
|
|
119
|
+
console.error('Failed to initialize:', error);
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
// Sentry integration (optional)
|
|
123
|
+
sentryClient: Sentry,
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
82
127
|
### API Reference
|
|
83
128
|
|
|
84
129
|
#### Profiles
|
|
@@ -195,19 +240,43 @@ accounts.forEach(acc => {
|
|
|
195
240
|
|
|
196
241
|
Find and verify business emails using multiple providers with waterfall/parallel strategies.
|
|
197
242
|
|
|
198
|
-
### Supported Providers
|
|
243
|
+
### Supported Providers (11 Total)
|
|
199
244
|
|
|
200
245
|
| Provider | Type | Cost | Best For |
|
|
201
246
|
|----------|------|------|----------|
|
|
202
247
|
| **LDD** | Database | FREE | LinkedIn profile emails (~500M profiles) |
|
|
203
248
|
| **SmartProspect** | Database | FREE* | SmartLead's prospect database |
|
|
204
249
|
| **Cosiall** | Profile Lookup | FREE | Emails from LinkedIn profiles |
|
|
250
|
+
| **TryKitt.ai** | AI Finder | FREE** | AI-powered email finding with catch-all verification |
|
|
205
251
|
| **Construct** | Pattern + MX | FREE | Pattern guessing with MX verification |
|
|
252
|
+
| **BounceBan** | Verification | FREE/$0.003 | Catch-all specialist (85-95% accuracy) |
|
|
206
253
|
| **Bouncer** | SMTP Verify | $0.006/email | Catch-all detection, 99%+ accuracy |
|
|
207
|
-
| **Snov.io** | Email Finder | $0.02/email | Finding emails by name+domain |
|
|
208
254
|
| **Hunter** | Email Finder | $0.005/email | Domain search, email finder |
|
|
255
|
+
| **Dropcontact** | Email Finder | $0.01/email | Email finding API |
|
|
256
|
+
| **Snov.io** | Email Finder | $0.02/email | Finding emails by name+domain |
|
|
257
|
+
|
|
258
|
+
*SmartProspect is FREE if you have a SmartLead subscription
|
|
259
|
+
**TryKitt.ai is FREE for individuals with unlimited searches
|
|
209
260
|
|
|
210
|
-
|
|
261
|
+
### Default Provider Order (3-Phase Strategy)
|
|
262
|
+
|
|
263
|
+
The enrichment client uses an optimized 3-phase strategy:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
PHASE 1 - Free Lookups (Parallel):
|
|
267
|
+
├── LDD → Real verified emails from LinkedIn Data Dump
|
|
268
|
+
├── SmartProspect → Real verified emails from SmartLead
|
|
269
|
+
├── Cosiall → Emails from LinkedIn profiles
|
|
270
|
+
└── TryKitt.ai → AI-powered email finding
|
|
271
|
+
|
|
272
|
+
PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
|
|
273
|
+
├── Construct → Pattern guessing + MX check
|
|
274
|
+
└── BounceBan → Catch-all verification (FREE single)
|
|
275
|
+
|
|
276
|
+
PHASE 3 - Paid Finders (only if Phase 2 inconclusive):
|
|
277
|
+
├── Hunter → $0.005/email
|
|
278
|
+
└── Snov.io → $0.02/email
|
|
279
|
+
```
|
|
211
280
|
|
|
212
281
|
### Cosiall Profile Emails (Standalone)
|
|
213
282
|
|
|
@@ -253,11 +322,23 @@ const enrichment = createEnrichmentClient({
|
|
|
253
322
|
// cosiall: enabled by default (uses global Cosiall config)
|
|
254
323
|
// construct: enabled by default (pattern guessing)
|
|
255
324
|
|
|
325
|
+
// TryKitt.ai - FREE for individuals (AI email finder)
|
|
326
|
+
trykitt: {
|
|
327
|
+
apiKey: process.env.TRYKITT_API_KEY,
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
// BounceBan - FREE single verification, catch-all specialist
|
|
331
|
+
bounceban: {
|
|
332
|
+
apiKey: process.env.BOUNCEBAN_API_KEY,
|
|
333
|
+
useDeepVerify: true, // +15-25% accuracy for pattern-guessed emails
|
|
334
|
+
useWaterfall: true, // Recommended - includes free retries
|
|
335
|
+
},
|
|
336
|
+
|
|
256
337
|
// PAID providers - only used if FREE providers don't find email
|
|
257
338
|
bouncer: { apiKey: process.env.BOUNCER_API_KEY },
|
|
258
339
|
snovio: {
|
|
259
|
-
|
|
260
|
-
|
|
340
|
+
clientId: process.env.SNOVIO_CLIENT_ID,
|
|
341
|
+
clientSecret: process.env.SNOVIO_CLIENT_SECRET
|
|
261
342
|
},
|
|
262
343
|
hunter: { apiKey: process.env.HUNTER_API_KEY },
|
|
263
344
|
},
|
|
@@ -319,11 +400,99 @@ result.emails.forEach(email => {
|
|
|
319
400
|
console.log(email.source); // 'hunter'
|
|
320
401
|
console.log(email.confidence); // 95
|
|
321
402
|
console.log(email.verified); // true
|
|
322
|
-
console.log(email.type); // 'business'
|
|
403
|
+
console.log(email.type); // 'business' | 'personal' | 'role' | 'disposable'
|
|
404
|
+
console.log(email.isCatchAll); // false
|
|
323
405
|
});
|
|
324
406
|
|
|
325
|
-
console.log(result.totalCost);
|
|
326
|
-
console.log(result.providersQueried); // ['
|
|
407
|
+
console.log(result.totalCost); // Total $ spent across providers
|
|
408
|
+
console.log(result.providersQueried); // ['ldd', 'smartprospect', 'construct', 'hunter']
|
|
409
|
+
|
|
410
|
+
// Batch version
|
|
411
|
+
const allResults = await enrichment.enrichAllBatch(candidates, {
|
|
412
|
+
batchSize: 50,
|
|
413
|
+
delayMs: 200,
|
|
414
|
+
});
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### TryKitt.ai Email Finder
|
|
418
|
+
|
|
419
|
+
AI-powered email finding with enterprise identity server catch-all verification:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
import {
|
|
423
|
+
findEmailWithTryKitt,
|
|
424
|
+
verifyEmailWithTryKitt
|
|
425
|
+
} from 'linkedin-secret-sauce';
|
|
426
|
+
|
|
427
|
+
// Find email by name + domain
|
|
428
|
+
const result = await findEmailWithTryKitt(
|
|
429
|
+
'John Doe',
|
|
430
|
+
'acme.com',
|
|
431
|
+
{ apiKey: process.env.TRYKITT_API_KEY },
|
|
432
|
+
'https://linkedin.com/in/johndoe' // Optional - improves accuracy
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
if (result?.status === 'completed') {
|
|
436
|
+
console.log(result.result.email); // john.doe@acme.com
|
|
437
|
+
console.log(result.result.confidence_score); // 0.95
|
|
438
|
+
console.log(result.result.is_catchall); // false
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Verify an existing email
|
|
442
|
+
const verification = await verifyEmailWithTryKitt(
|
|
443
|
+
'john@acme.com',
|
|
444
|
+
{ apiKey: process.env.TRYKITT_API_KEY }
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
console.log(verification?.valid); // true
|
|
448
|
+
console.log(verification?.deliverable); // true
|
|
449
|
+
console.log(verification?.isCatchAll); // false
|
|
450
|
+
console.log(verification?.isDisposable); // false
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### BounceBan Catch-All Verification
|
|
454
|
+
|
|
455
|
+
Specializes in catch-all email verification with 85-95% accuracy without sending emails:
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
import {
|
|
459
|
+
verifyEmailWithBounceBan,
|
|
460
|
+
verifyEmailsBatchWithBounceBan,
|
|
461
|
+
checkCatchAllWithBounceBan
|
|
462
|
+
} from 'linkedin-secret-sauce';
|
|
463
|
+
|
|
464
|
+
// Verify a single email (FREE)
|
|
465
|
+
const result = await verifyEmailWithBounceBan(
|
|
466
|
+
'john@catchall-domain.com',
|
|
467
|
+
{
|
|
468
|
+
apiKey: process.env.BOUNCEBAN_API_KEY,
|
|
469
|
+
useDeepVerify: true, // Better for pattern-guessed emails
|
|
470
|
+
useWaterfall: true, // Recommended - includes 30-min free retry window
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
console.log(result.result); // 'deliverable' | 'risky' | 'undeliverable' | 'unknown'
|
|
475
|
+
console.log(result.score); // 0-100
|
|
476
|
+
console.log(result.is_accept_all); // true (catch-all domain)
|
|
477
|
+
console.log(result.is_disposable); // false
|
|
478
|
+
console.log(result.is_role); // false (not info@, support@, etc.)
|
|
479
|
+
console.log(result.smtp_provider); // 'google' | 'microsoft' | etc.
|
|
480
|
+
|
|
481
|
+
// Check if domain is catch-all
|
|
482
|
+
const isCatchAll = await checkCatchAllWithBounceBan(
|
|
483
|
+
'example.com',
|
|
484
|
+
{ apiKey: process.env.BOUNCEBAN_API_KEY }
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
// Batch verification (for >5 emails, uses bulk API at $0.003/email)
|
|
488
|
+
const batchResults = await verifyEmailsBatchWithBounceBan(
|
|
489
|
+
['john@example.com', 'jane@example.com'],
|
|
490
|
+
{ apiKey: process.env.BOUNCEBAN_API_KEY }
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
batchResults.forEach((result, email) => {
|
|
494
|
+
console.log(`${email}: ${result?.result}`);
|
|
495
|
+
});
|
|
327
496
|
```
|
|
328
497
|
|
|
329
498
|
### Email Verification with Bouncer
|
|
@@ -423,12 +592,14 @@ const enrichment = createEnrichmentClient({
|
|
|
423
592
|
options: {
|
|
424
593
|
// Custom order - cheaper/faster providers first
|
|
425
594
|
providerOrder: [
|
|
426
|
-
'construct', // FREE - pattern matching
|
|
427
595
|
'ldd', // FREE - your database
|
|
428
|
-
'
|
|
596
|
+
'smartprospect', // FREE - SmartLead
|
|
597
|
+
'cosiall', // FREE - LinkedIn profiles
|
|
598
|
+
'trykitt', // FREE - AI finder
|
|
599
|
+
'construct', // FREE - pattern matching
|
|
600
|
+
'bounceban', // FREE single / $0.003 bulk
|
|
429
601
|
'hunter', // $0.005
|
|
430
602
|
'bouncer', // $0.006 (verification only)
|
|
431
|
-
'smartprospect', // $0.01
|
|
432
603
|
'snovio', // $0.02
|
|
433
604
|
],
|
|
434
605
|
|
|
@@ -437,6 +608,9 @@ const enrichment = createEnrichmentClient({
|
|
|
437
608
|
|
|
438
609
|
// Minimum confidence to accept
|
|
439
610
|
minConfidence: 70,
|
|
611
|
+
|
|
612
|
+
// Maximum cost per email
|
|
613
|
+
maxCostPerEmail: 0.05,
|
|
440
614
|
},
|
|
441
615
|
});
|
|
442
616
|
```
|
|
@@ -461,6 +635,62 @@ const enrichment = createEnrichmentClient({
|
|
|
461
635
|
|
|
462
636
|
---
|
|
463
637
|
|
|
638
|
+
## Contact Matching (LinkedIn <-> SmartProspect)
|
|
639
|
+
|
|
640
|
+
Match LinkedIn profiles to SmartProspect contacts for unified email lookup:
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
import {
|
|
644
|
+
getEmailsForLinkedInContact,
|
|
645
|
+
getEmailsForLinkedInContactsBatch,
|
|
646
|
+
salesLeadToContact,
|
|
647
|
+
createLinkedInEnricher,
|
|
648
|
+
} from 'linkedin-secret-sauce';
|
|
649
|
+
|
|
650
|
+
// Convert a Sales Navigator lead to contact format
|
|
651
|
+
const contact = salesLeadToContact(lead);
|
|
652
|
+
|
|
653
|
+
// Get emails for a LinkedIn contact (recommended unified approach)
|
|
654
|
+
const result = await getEmailsForLinkedInContact(
|
|
655
|
+
{
|
|
656
|
+
firstName: 'John',
|
|
657
|
+
lastName: 'Doe',
|
|
658
|
+
company: 'Acme Corp',
|
|
659
|
+
linkedinUrl: 'https://linkedin.com/in/johndoe',
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
// SmartProspect config
|
|
663
|
+
smartprospect: {
|
|
664
|
+
email: process.env.SMARTLEAD_EMAIL,
|
|
665
|
+
password: process.env.SMARTLEAD_PASSWORD,
|
|
666
|
+
},
|
|
667
|
+
// TryKitt.ai (FREE)
|
|
668
|
+
trykitt: { apiKey: process.env.TRYKITT_API_KEY },
|
|
669
|
+
// BounceBan (FREE single)
|
|
670
|
+
bounceban: {
|
|
671
|
+
apiKey: process.env.BOUNCEBAN_API_KEY,
|
|
672
|
+
useDeepVerify: true,
|
|
673
|
+
},
|
|
674
|
+
// Bouncer for final verification
|
|
675
|
+
bouncer: { apiKey: process.env.BOUNCER_API_KEY },
|
|
676
|
+
}
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
console.log(result.emails); // Array of found emails with metadata
|
|
680
|
+
console.log(result.bestEmail); // Highest confidence business email
|
|
681
|
+
console.log(result.providersQueried); // Which providers were called
|
|
682
|
+
console.log(result.matchedContact); // SmartProspect match if found
|
|
683
|
+
|
|
684
|
+
// Batch version
|
|
685
|
+
const results = await getEmailsForLinkedInContactsBatch(
|
|
686
|
+
contacts,
|
|
687
|
+
config,
|
|
688
|
+
{ concurrency: 5 }
|
|
689
|
+
);
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
464
694
|
## Combined Workflow Example
|
|
465
695
|
|
|
466
696
|
Here's a complete example: Search LinkedIn -> Enrich with emails:
|
|
@@ -479,10 +709,12 @@ initializeLinkedInClient({
|
|
|
479
709
|
cosiallApiKey: process.env.COSIALL_API_KEY!,
|
|
480
710
|
});
|
|
481
711
|
|
|
482
|
-
// Initialize enrichment client
|
|
712
|
+
// Initialize enrichment client with new providers
|
|
483
713
|
const enrichment = createEnrichmentClient({
|
|
484
714
|
providers: {
|
|
485
715
|
construct: {},
|
|
716
|
+
trykitt: { apiKey: process.env.TRYKITT_API_KEY },
|
|
717
|
+
bounceban: { apiKey: process.env.BOUNCEBAN_API_KEY, useDeepVerify: true },
|
|
486
718
|
hunter: { apiKey: process.env.HUNTER_API_KEY },
|
|
487
719
|
bouncer: { apiKey: process.env.BOUNCER_API_KEY },
|
|
488
720
|
},
|
|
@@ -529,6 +761,40 @@ console.table(leads);
|
|
|
529
761
|
|
|
530
762
|
---
|
|
531
763
|
|
|
764
|
+
## Environment Variables
|
|
765
|
+
|
|
766
|
+
Complete reference of all environment variables:
|
|
767
|
+
|
|
768
|
+
```bash
|
|
769
|
+
# Required - LinkedIn API
|
|
770
|
+
COSIALL_API_URL=https://...
|
|
771
|
+
COSIALL_API_KEY=...
|
|
772
|
+
|
|
773
|
+
# Optional - LinkedIn networking
|
|
774
|
+
LINKEDIN_PROXY_STRING=host:port:user:pass
|
|
775
|
+
LOG_LEVEL=debug|info|warn|error
|
|
776
|
+
|
|
777
|
+
# Email Enrichment - FREE providers
|
|
778
|
+
LDD_API_URL=https://...
|
|
779
|
+
LDD_API_TOKEN=...
|
|
780
|
+
|
|
781
|
+
SMARTLEAD_EMAIL=...
|
|
782
|
+
SMARTLEAD_PASSWORD=...
|
|
783
|
+
|
|
784
|
+
TRYKITT_API_KEY=... # FREE for individuals
|
|
785
|
+
|
|
786
|
+
BOUNCEBAN_API_KEY=... # FREE single, $0.003 bulk
|
|
787
|
+
|
|
788
|
+
# Email Enrichment - PAID providers
|
|
789
|
+
HUNTER_API_KEY=... # $0.005/email
|
|
790
|
+
BOUNCER_API_KEY=... # $0.006/email
|
|
791
|
+
DROPCONTACT_API_KEY=... # $0.01/email
|
|
792
|
+
SNOVIO_CLIENT_ID=... # $0.02/email
|
|
793
|
+
SNOVIO_CLIENT_SECRET=...
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
532
798
|
## Development
|
|
533
799
|
|
|
534
800
|
```bash
|
|
@@ -555,10 +821,23 @@ pnpm docs
|
|
|
555
821
|
|
|
556
822
|
```bash
|
|
557
823
|
pnpm dev:playground
|
|
824
|
+
# or simply
|
|
825
|
+
pnpm dev
|
|
558
826
|
```
|
|
559
827
|
|
|
560
828
|
Opens a React UI at http://localhost:5173 to test the API interactively.
|
|
561
829
|
|
|
830
|
+
**Playground Features:**
|
|
831
|
+
|
|
832
|
+
| Tab | Features |
|
|
833
|
+
|-----|----------|
|
|
834
|
+
| **LinkedIn** | Sales Navigator search, profile lookup, company tools, typeahead |
|
|
835
|
+
| **SmartLead** | Contact search, email lookup, bulk operations |
|
|
836
|
+
| **LDD** | Profile lookup by username/ID |
|
|
837
|
+
| **Cosiall** | Profile email lookup (objectUrn, URL, vanity) |
|
|
838
|
+
| **Email Tools** | Validation, provider testing (side-by-side), contact matching debugger |
|
|
839
|
+
| **System** | Account management, real-time logs (SSE), metrics, cost analytics |
|
|
840
|
+
|
|
562
841
|
---
|
|
563
842
|
|
|
564
843
|
## Publishing
|
|
@@ -27,7 +27,28 @@
|
|
|
27
27
|
* });
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
import type
|
|
30
|
+
import { type EnrichmentClientConfig, type EnrichmentClient } from "./types";
|
|
31
|
+
/**
|
|
32
|
+
* Provider order is imported from types.ts as DEFAULT_PROVIDER_ORDER
|
|
33
|
+
*
|
|
34
|
+
* 3-Phase Strategy:
|
|
35
|
+
*
|
|
36
|
+
* PHASE 1 - Free lookups (parallel):
|
|
37
|
+
* - ldd: LinkedIn Data Dump - real verified emails (FREE)
|
|
38
|
+
* - smartprospect: SmartLead API - real verified emails (FREE with subscription)
|
|
39
|
+
* - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
|
|
40
|
+
* - trykitt: TryKitt.ai - AI-powered email finder (FREE for individuals)
|
|
41
|
+
*
|
|
42
|
+
* PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
|
|
43
|
+
* - construct: Pattern guessing + MX check (FREE)
|
|
44
|
+
* - bounceban: BounceBan catch-all verification (FREE single / $0.003 bulk)
|
|
45
|
+
*
|
|
46
|
+
* PHASE 3 - Paid finders (only if Phase 2 inconclusive):
|
|
47
|
+
* - hunter: Hunter.io ($0.005/email)
|
|
48
|
+
* - snovio: Snov.io ($0.02/email)
|
|
49
|
+
*
|
|
50
|
+
* Note: bouncer ($0.006) and dropcontact ($0.01) available but not in default order
|
|
51
|
+
*/
|
|
31
52
|
/**
|
|
32
53
|
* Create an enrichment client with the given configuration
|
|
33
54
|
*
|
package/dist/enrichment/index.js
CHANGED
|
@@ -46,40 +46,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
46
|
exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.enrichAllBatch = exports.enrichAllEmails = exports.enrichBatch = exports.enrichBusinessEmail = exports.createSmartProspectClient = exports.extractNumericLinkedInId = exports.clearSnovioTokenCache = exports.verifyEmailWithSnovio = exports.findEmailsWithSnovio = exports.checkCatchAllWithBounceBan = exports.verifyEmailsBatchWithBounceBan = exports.verifyEmailWithBounceBan = exports.verifyEmailsBatch = exports.checkCatchAllDomain = exports.verifyEmailWithBouncer = exports.verifyEmailWithTryKitt = exports.findEmailWithTryKitt = exports.createSnovioProvider = exports.createBounceBanProvider = exports.createBouncerProvider = exports.createDropcontactProvider = exports.createHunterProvider = exports.createTryKittProvider = exports.createCosiallProvider = exports.createSmartProspectProvider = exports.createLddProvider = exports.createConstructProvider = exports.verifyEmailsExist = exports.checkDomainCatchAll = exports.verifyEmailMx = exports.extractLinkedInUsername = exports.hostnameFromUrl = exports.cleanNamePart = exports.asciiFold = exports.isRoleAccount = exports.isValidEmailSyntax = exports.DISPOSABLE_DOMAINS = exports.isDisposableDomain = exports.isDisposableEmail = exports.PERSONAL_DOMAINS = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = exports.DEFAULT_PROVIDER_ORDER = exports.PROVIDER_COSTS = void 0;
|
|
47
47
|
exports.salesLeadToContact = exports.getEmailsForLinkedInContactsBatch = exports.getEmailsForLinkedInContact = exports.createLinkedInEnricher = exports.enrichLinkedInContactsBatch = exports.enrichLinkedInContact = exports.parseLinkedInSearchResponse = exports.buildSmartProspectFiltersFromLinkedIn = exports.matchContacts = exports.findBestMatch = exports.classifyMatchQuality = exports.calculateMatchConfidence = exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = void 0;
|
|
48
48
|
exports.createEnrichmentClient = createEnrichmentClient;
|
|
49
|
+
const types_1 = require("./types");
|
|
49
50
|
const orchestrator_1 = require("./orchestrator");
|
|
50
51
|
const construct_1 = require("./providers/construct");
|
|
51
52
|
const ldd_1 = require("./providers/ldd");
|
|
52
53
|
const smartprospect_1 = require("./providers/smartprospect");
|
|
53
54
|
const cosiall_1 = require("./providers/cosiall");
|
|
55
|
+
const trykitt_1 = require("./providers/trykitt");
|
|
54
56
|
const hunter_1 = require("./providers/hunter");
|
|
55
57
|
const dropcontact_1 = require("./providers/dropcontact");
|
|
56
58
|
const bouncer_1 = require("./providers/bouncer");
|
|
59
|
+
const bounceban_1 = require("./providers/bounceban");
|
|
57
60
|
const snovio_1 = require("./providers/snovio");
|
|
58
61
|
/**
|
|
59
|
-
*
|
|
62
|
+
* Provider order is imported from types.ts as DEFAULT_PROVIDER_ORDER
|
|
60
63
|
*
|
|
61
|
-
*
|
|
64
|
+
* 3-Phase Strategy:
|
|
65
|
+
*
|
|
66
|
+
* PHASE 1 - Free lookups (parallel):
|
|
62
67
|
* - ldd: LinkedIn Data Dump - real verified emails (FREE)
|
|
63
68
|
* - smartprospect: SmartLead API - real verified emails (FREE with subscription)
|
|
64
69
|
* - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
|
|
70
|
+
* - trykitt: TryKitt.ai - AI-powered email finder (FREE for individuals)
|
|
71
|
+
*
|
|
72
|
+
* PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
|
|
65
73
|
* - construct: Pattern guessing + MX check (FREE)
|
|
74
|
+
* - bounceban: BounceBan catch-all verification (FREE single / $0.003 bulk)
|
|
66
75
|
*
|
|
67
|
-
* PHASE
|
|
68
|
-
* -
|
|
69
|
-
* - snovio:
|
|
70
|
-
* - hunter: Hunter.io fallback ($0.005/email)
|
|
76
|
+
* PHASE 3 - Paid finders (only if Phase 2 inconclusive):
|
|
77
|
+
* - hunter: Hunter.io ($0.005/email)
|
|
78
|
+
* - snovio: Snov.io ($0.02/email)
|
|
71
79
|
*
|
|
72
|
-
* Note: dropcontact available but not in default order
|
|
80
|
+
* Note: bouncer ($0.006) and dropcontact ($0.01) available but not in default order
|
|
73
81
|
*/
|
|
74
|
-
const DEFAULT_ORDER = [
|
|
75
|
-
"ldd",
|
|
76
|
-
"smartprospect",
|
|
77
|
-
"cosiall",
|
|
78
|
-
"construct",
|
|
79
|
-
"bouncer",
|
|
80
|
-
"snovio",
|
|
81
|
-
"hunter",
|
|
82
|
-
];
|
|
83
82
|
/**
|
|
84
83
|
* Create an enrichment client with the given configuration
|
|
85
84
|
*
|
|
@@ -103,6 +102,10 @@ function createEnrichmentClient(config) {
|
|
|
103
102
|
if (providerConfigs.cosiall?.enabled !== false) {
|
|
104
103
|
providerFuncs.set("cosiall", (0, cosiall_1.createCosiallProvider)(providerConfigs.cosiall));
|
|
105
104
|
}
|
|
105
|
+
// TryKitt.ai - FREE for individuals with unlimited searches
|
|
106
|
+
if (providerConfigs.trykitt) {
|
|
107
|
+
providerFuncs.set("trykitt", (0, trykitt_1.createTryKittProvider)(providerConfigs.trykitt));
|
|
108
|
+
}
|
|
106
109
|
if (providerConfigs.hunter) {
|
|
107
110
|
providerFuncs.set("hunter", (0, hunter_1.createHunterProvider)(providerConfigs.hunter));
|
|
108
111
|
}
|
|
@@ -115,8 +118,12 @@ function createEnrichmentClient(config) {
|
|
|
115
118
|
if (providerConfigs.snovio) {
|
|
116
119
|
providerFuncs.set("snovio", (0, snovio_1.createSnovioProvider)(providerConfigs.snovio));
|
|
117
120
|
}
|
|
121
|
+
// BounceBan - FREE single verification, catch-all specialist
|
|
122
|
+
if (providerConfigs.bounceban) {
|
|
123
|
+
providerFuncs.set("bounceban", (0, bounceban_1.createBounceBanProvider)(providerConfigs.bounceban));
|
|
124
|
+
}
|
|
118
125
|
// Build ordered provider list
|
|
119
|
-
const providerOrder = options.providerOrder ??
|
|
126
|
+
const providerOrder = options.providerOrder ?? types_1.DEFAULT_PROVIDER_ORDER;
|
|
120
127
|
const orderedProviders = [];
|
|
121
128
|
for (const name of providerOrder) {
|
|
122
129
|
const provider = providerFuncs.get(name);
|
|
@@ -247,9 +254,9 @@ function buildCacheKey(candidate) {
|
|
|
247
254
|
}
|
|
248
255
|
// Re-export types and constants
|
|
249
256
|
__exportStar(require("./types"), exports);
|
|
250
|
-
var
|
|
251
|
-
Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return
|
|
252
|
-
Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return
|
|
257
|
+
var types_2 = require("./types");
|
|
258
|
+
Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return types_2.PROVIDER_COSTS; } });
|
|
259
|
+
Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return types_2.DEFAULT_PROVIDER_ORDER; } });
|
|
253
260
|
// Re-export utilities
|
|
254
261
|
var personal_domains_1 = require("./utils/personal-domains");
|
|
255
262
|
Object.defineProperty(exports, "isPersonalEmail", { enumerable: true, get: function () { return personal_domains_1.isPersonalEmail; } });
|
|
@@ -24,10 +24,20 @@ export interface CanonicalEmail {
|
|
|
24
24
|
/**
|
|
25
25
|
* Raw result from a provider before normalization
|
|
26
26
|
*/
|
|
27
|
+
/**
|
|
28
|
+
* Result returned by a single-email provider
|
|
29
|
+
*/
|
|
27
30
|
export interface ProviderResult {
|
|
31
|
+
/** The email address found */
|
|
28
32
|
email?: string | null;
|
|
33
|
+
/** Whether the email was verified */
|
|
29
34
|
verified?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Confidence score (0-100)
|
|
37
|
+
* @deprecated Use `confidence` instead - both are supported for backwards compatibility
|
|
38
|
+
*/
|
|
30
39
|
score?: number;
|
|
40
|
+
/** Confidence score (0-100) */
|
|
31
41
|
confidence?: number;
|
|
32
42
|
}
|
|
33
43
|
/**
|