---
name: moltsets-batch-enrich-linkedin-list
description: Use this skill when the user has a list of LinkedIn URLs (10 or more) and wants to bulk enrich them with contact data.
---

# Batch Enrich LinkedIn List

Bulk enrich a list of up to 100 LinkedIn URLs. Email lookups run as parallel per-URL calls; phone runs as a single batch array call. Credit pre-check required.

## Triggers

"I have a CSV of LinkedIn URLs", "enrich this list", "bulk enrich", "get emails for all of these", "enrich my Sales Nav export", "process this list". Handles large lists with mandatory credit pre-check, the phone batch chunked at 100, and a hit-rate summary. For 1–9 URLs, enrich-contact is simpler.

## Set Expectations

Before firing any calls, give the user a brief, dry heads-up. Deadpan over enthusiastic - no filler, no corporate speak.

Facts to work with (scale to list size and tools selected). Email lookups are N parallel single calls; phone is a single array call (chunked at 100):
- ≤10 URLs: ~10–20 seconds
- 11–50 URLs: ~30–60 seconds
- 51–100 URLs: ~60–90 seconds, phone in one array call of 100
- >100 URLs: phone runs in array calls of 100, a few minutes - note you'll report after each chunk

Include the URL count, which data types are being fetched, and roughly how long it'll take.

## Risk scores - confirm before enriching

Every email MoltSets returns carries a deliverability risk score - a grade from A to F. Ask which grades to keep before running anything:

> "MoltSets grades email deliverability risk from A (best) to F (no data). Which grades should I keep? I'd recommend **A, B, C and F** - and dropping **D**, since D is a confirmed bounce, complaint or spam trap."

| Grade | Meaning | Best practice |
| --- | --- | --- |
| A | Strongest engagement signal available | Safe to send immediately |
| B | Solid | Fine in regular sends; on a new or warming domain, send a smaller batch before scaling |
| C | Deliverability can't be confirmed | Segment separately from A/B, warm at low volume, watch engagement, suppress non-responders after 1-2 attempts |
| D | Confirmed bounce, complaint or spam trap | Never send - fastest way to trip spam traps and damage sender reputation for the whole list |
| F | No data - unknown risk, not "safe" | Re-verify before sending, or treat like C |

Use whatever set the user confirms. Treat the grade as a filter, not a guarantee - it lowers risk, it doesn't remove it. Pair it with the user's own sending domain reputation and list hygiene.

## Step 1 - Parse input

Accept:
- Line-separated paste
- Comma-separated list
- CSV (extract the LinkedIn URL column)

Deduplicate and normalise. Flag malformed URLs separately.

Report: "Found X unique LinkedIn URLs."

## Step 2 - Credit pre-check (required before every batch)

Call `MoltSets:get_billing` and `MoltSets:get_usage` with `period: billing_cycle` in parallel (both free).

Calculate:
```
X URLs × [cost per tool] × [tools selected] = estimated cost
Current balance: Y credits
Remaining after: ~Z credits
```

Note: "not found" results are free - personal email hit rates (~25–40%) are lower than business email (~60–75%). Adjust estimate accordingly.

**If estimated cost > balance:** stop. Report the shortfall, how many rows the balance covers, and ask whether to proceed partially, prioritise a subset, or wait for a top-up.

## Step 3 - Choose what to enrich

| User says | Run |
|---|---|
| "email" (unspecified) | `linkedin_to_best_email` (hybrid - business preferred, personal fallback) |
| "business email" / "work email" | `linkedin_to_business_email` only |
| "personal email" | `linkedin_to_personal_email` only |
| "phone" / "mobile" | `linkedin_to_mobile_phone` only |
| "everything" / "all contact info" / no preference | All three in parallel |

## Step 4 - Fire the calls

- **Email tools** (`linkedin_to_best_email` / `linkedin_to_business_email` / `linkedin_to_personal_email`): one call per URL with `linkedin_url`. There is no array param - fire these in parallel across the list.
- **Phone** (`linkedin_to_mobile_phone`): pass the `linkedin_urls` array (max 100). If the list > 100, split the phone calls into chunks of 100 and process sequentially. Inform the user: "Processing phone in X batches of 100."

## Step 5 - Present results

| LinkedIn URL | Business Email | Risk | Personal Email | Risk | Mobile |
|---|---|---|---|---|---|
| linkedin.com/in/janesmith | jane@acme.com | A | Not found | - | +1 415 555 0192 |
| linkedin.com/in/samlee | sam@oldco.com | D (held) | sam@gmail.com | B | Not found |

Show the risk score on every row that has an email, including grades outside the accepted set - flag those rather than dropping them silently, so the user can see what was filtered and why.

**Hit rate summary:**
```
Business emails: 34/50 (68%)
Personal emails: 12/50 (24%)
Mobile numbers:  21/50 (42%)
Estimated credits used: ~XXX

Email risk scores:
  A: X   B: X   C: X   D: X   F: X
  kept (accepted grades):  X
  filtered (excluded):     X
```

## Edge cases

- Mid-batch credit exhaustion: stop immediately, output completed rows marked clearly, report exact resume point
- Malformed URLs: skip and list in a "skipped" section at the end
- Slugs without full URL to construct `https://www.linkedin.com/in/<slug>` before passing
