multiAI Summary Pending

linkedin-connect

Send LinkedIn connection requests to a list of people via browser automation and track status in a CSV/TSV file. Use when the user wants to bulk-connect with a list of people on LinkedIn (founders, speakers, leads, etc.) from a spreadsheet or list containing LinkedIn profile URLs. Handles Connect button, Follow-mode profiles, already-connected detection, stale URL fallback via LinkedIn search and Google search, and incremental status tracking.

3,556 stars

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/linkedin-bulk-connect/SKILL.md --create-dirs "https://raw.githubusercontent.com/openclaw/skills/main/skills/10madh/linkedin-bulk-connect/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/linkedin-bulk-connect/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How linkedin-connect Compares

Feature / Agentlinkedin-connectStandard Approach
Platform SupportmultiLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Send LinkedIn connection requests to a list of people via browser automation and track status in a CSV/TSV file. Use when the user wants to bulk-connect with a list of people on LinkedIn (founders, speakers, leads, etc.) from a spreadsheet or list containing LinkedIn profile URLs. Handles Connect button, Follow-mode profiles, already-connected detection, stale URL fallback via LinkedIn search and Google search, and incremental status tracking.

Which AI agents support this skill?

This skill is compatible with multi.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# LinkedIn Connect

Automates sending LinkedIn connection requests from a list and tracks results in a data file.

## ⚠️ Pre-flight Checklist — Confirm Before Starting

**Before doing anything else**, confirm all of the following with the user. Do not proceed until each item is confirmed.

### 1. Data File
Ask the user to provide their spreadsheet/CSV/TSV file and confirm it has (or can have) these columns:
- **Person/Founder Name** — full name of the person to connect with
- **Company/Brand Name** — their company or brand (used for search fallback)
- **LinkedIn Profile URL** — optional but highly recommended; reduces automation footprint

If the file lacks any column, tell the user which columns are missing and offer to add them.

### 2. Browser Setup
Ask which browser setup they're using:

**Option A — Chrome Browser Relay (recommended for accounts flagged for automation)**
- User must have the OpenClaw Browser Relay Chrome extension installed
- User opens LinkedIn in their regular Chrome browser and clicks the OpenClaw Relay toolbar icon on that tab (badge turns ON)
- Use `profile="chrome"` for all browser tool calls in this mode

**Option B — OpenClaw Isolated Browser (`openclaw` profile)**
- OpenClaw manages a separate Chrome instance
- On first use, navigate to `https://www.linkedin.com` and let the user log in; cookies persist across sessions
- Use `profile="openclaw"` for all browser tool calls in this mode

Confirm which option they've set up. Default to **Option A (Chrome Relay)** if the user's account has been flagged or warned about automation.

### 3. Ready Check
Only proceed once the user says:
- ✅ File is ready and accessible
- ✅ Browser is open with LinkedIn logged in (and relay is attached if Option A)

---

## Browser Profile

Set the `profile` variable based on user's choice in the Pre-flight Checklist:
- **Option A:** `profile="chrome"` — reuse the relay-attached tab; get `targetId` via `browser action=tabs`
- **Option B:** `profile="openclaw"` — OpenClaw-managed isolated Chrome instance

Do not mix profiles mid-run. Pick one and use it consistently for every browser tool call.

## Data File Setup

Ensure the tracking file has a `Connection Status` column. If missing, add it:

```python
import csv
rows = []
with open('file.tsv', 'r') as f:
    reader = csv.DictReader(f, delimiter='\t')
    fieldnames = reader.fieldnames + ['Connection Status']
    rows = list(reader)
with open('file.tsv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter='\t')
    writer.writeheader()
    for row in rows:
        row['Connection Status'] = ''
        writer.writerow(row)
```

## Three-Tier Profile Discovery (Priority Order)

Always try in this order. Move to the next tier only if the current one fails.

### Tier 1 — Direct LinkedIn URL (fastest, zero ambiguity)
Navigate directly to the LinkedIn profile URL from the data file.
- ✅ URL loads → correct profile, proceed to connect
- ❌ Returns 404 → escalate to Tier 2
- Skip Tier 1 if no URL is in the data file for this person

### Tier 2 — Google Search (reliable fallback, preserves accuracy)
Search Google for `"Founder Name" "Brand/Company" linkedin`.
- Navigate to: `https://www.google.com/search?q=<Name>+<Company>+linkedin`
- Find the LinkedIn profile link in results (usually first result), click it
- Once on the profile, proceed to Connect step
- ⚠️ Only escalate to Tier 3 if Google can't find the right person or returns no LinkedIn result

### Tier 3 — LinkedIn People Search (last resort)
Run a LinkedIn people search for the founder + brand directly inside LinkedIn.
- Navigate to: `https://www.linkedin.com/search/results/people/?keywords=<Name>+<Company>`
- Look for inline `Connect` buttons first; otherwise open the profile from search results
- Confirm name + headline/company match before connecting
- ❌ No trustworthy match → mark `Profile Not Found`

See `references/browser-workflow.md` for detailed browser steps for each tier.

## Connecting on a Profile

Once on the correct profile, two patterns exist:

**Pattern A - Direct Connect button** visible on profile → click it → confirm dialog → `Send without a note`

**Pattern B - Follow mode** (no Connect button, only Follow + Message + More) → click `More actions` → use selector `.artdeco-dropdown__content--is-open` to get dropdown → click `Invite [Name] to connect` → confirm dialog → `Send without a note`

If neither Connect nor Invite is available → mark `Follow Only`.

## Status Values

| Status | Meaning |
|---|---|
| `Request Sent` | Connection request sent this session |
| `Already Connected` | 1st degree - no action needed |
| `Pending` | Request already sent previously |
| `Follow Only` | No Connect option available on this profile |
| `Profile Not Found` | All three tiers failed |
| `Skipped` | Intentionally skipped |

## Multi-founder Rows

When a TSV row has multiple founders, track per-founder status separated by ` | `:
```
Founder1Slug: Request Sent | Founder2Slug: Already Connected
```

## Rate Limiting & Anti-Detection

> ⚠️ LinkedIn flags accounts that jump directly between profile URLs. Always visit the feed between profiles — no exceptions.

- **Navigate to `/feed/` before every single profile**, without exception. See `references/browser-workflow.md` for the exact call. This is the primary anti-detection measure.
- Add a short natural pause (2–4 seconds) after loading the feed before navigating to the next profile.
- If >3 consecutive clean URLs return 404, pause for 10 seconds on the feed before continuing (then fall back to Google/LinkedIn search).
- Do not open new browser tabs — the relay breaks; reuse the same attached tab for every action.
- Aim for no more than 20–25 connection requests per session. Stop and tell the user if you're approaching this limit.

## Saving Progress

Use a `linkedin_progress.json` sidecar file:
```json
{ "statuses": { "https://www.linkedin.com/in/username/": "Request Sent" } }
```
Update the TSV from this dict every 10 profiles or at the end.

## References

- `references/browser-workflow.md` - Detailed browser steps for all three tiers and both connect patterns