惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
博客园 - 聂微东
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
Jina AI
Jina AI
D
Docker
B
Blog
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
D
DataBreaches.Net
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Y
Y Combinator Blog
N
Netflix TechBlog - Medium
月光博客
月光博客
F
Fortinet All Blogs
爱范儿
爱范儿
H
Help Net Security
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
The Cloudflare Blog
有赞技术团队
有赞技术团队
T
Tailwind CSS Blog
U
Unit 42

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Built a Chrome Extension That Writes LinkedIn DMs Using...
Sujal Meena · 2026-05-12 · via DEV Community

The Problem

Every time I wanted to connect with someone on LinkedIn,
I'd spend way too long staring at a blank message box.

Generic messages like "I'd love to add you to my network"
get ignored 90% of the time.

Personalized messages work — but writing them manually
for every single person is exhausting.

So I automated it.


What I Built

ConnectAI — a Chrome Extension that scrapes any
LinkedIn profile and generates 3 personalized connection
request messages using the Anthropic Claude API.

Live on Chrome Web Store: [YOUR LINK]


How It Works

1. Content Script — LinkedIn Scraper

The content script runs on any linkedin.com/in/* page
and scrapes:

  • Full name
  • Current role / headline
  • Current company
  • Top 3 skills
  • Recent activity snippet
  • Profile URL
function scrapeProfile() {
  const profileData = {};

  profileData.fullName = getMultipleTexts([
    "h1.text-heading-xlarge",
    "h1[class*='heading']",
    "h1"
  ]);

  profileData.currentRole = getMultipleTexts([
    ".text-body-medium.break-words",
    ".pv-top-card .text-body-medium"
  ]);

  // Store in chrome.storage.local
  chrome.storage.local.set({ profileData });
}

Enter fullscreen mode Exit fullscreen mode

The trickiest part? LinkedIn is a React SPA that
constantly changes its class names. I had to use
multiple selector fallbacks for every field.


2. Background Service Worker — Claude API Call

I route all API calls through the background service
worker instead of calling directly from the popup.

Why? CORS. The popup can't make direct API calls
to external URLs in MV3.

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "GENERATE_MESSAGES") {
    handleGenerateMessages(message.payload)
      .then(result => sendResponse({ success: true, data: result }))
      .catch(err => sendResponse({ success: false, error: err.message }));
    return true; // Keep channel open for async
  }
});

Enter fullscreen mode Exit fullscreen mode


3. Claude Prompt Engineering

Getting Claude to return consistent JSON under
300 characters per message took some iteration.

The system prompt enforces strict rules:

  • Never use "I came across your profile"
  • Always reference something specific
  • Sound like a peer, not a fan
  • Strict JSON output format
const systemPrompt = `
You are a LinkedIn outreach specialist.

STRICT RULES:
1. Each message MUST be under 300 characters
2. NEVER use "I came across your profile"
3. Reference something SPECIFIC about the target
4. Sound human — not AI-generated

OUTPUT: strict JSON only, no markdown
`;

Enter fullscreen mode Exit fullscreen mode


4. Popup UI

The popup is 420px wide with a dark theme and shows:

  • Scraped target profile info
  • Your saved sender info (editable inline)
  • 4 purpose pills (networking, referral, etc.)
  • Generate button
  • 3 message cards with character count badges
  • One-click copy

Character count badge logic:

  • 🟢 Green = under 300 chars (LinkedIn limit)
  • 🔴 Red = over 300 chars

Tech Stack

Part Tech
Extension Manifest V3
Language Vanilla JS (no bundler)
AI Anthropic Claude API
Storage Chrome Storage API
Scraping Content Scripts
Styling Pure CSS, dark theme

Biggest Challenges

1. LinkedIn DOM Scraping
LinkedIn changes class names constantly and uses
React under the hood. Had to write multiple selector
fallbacks and re-scrape on SPA navigation using
a MutationObserver.

2. CORS in MV3
Popup can't make external API calls directly.
Solved by routing everything through the background
service worker using chrome.runtime.sendMessage.

3. Consistent JSON from Claude
Claude sometimes wraps JSON in markdown code fences.
Added a cleaning step to strip backticks before
JSON.parse() with a fallback regex extraction.


What's Next

  • [ ] Auto-detect purpose from profile context
  • [ ] Message history per profile
  • [ ] Custom tone settings
  • [ ] Firefox support

Try It

Chrome Web Store: https://chromewebstore.google.com/detail/cjfnhjpheldgcfmipcmibbmlfmpflfij?utm_source=item-share-cb
GitHub: https://github.com/sujalmeena7/Connect-AI

You need a free Anthropic API key to use it.
New accounts get $5 free credits — enough for
~500 message generations.


If you've built Chrome Extensions before, I'd love
to know how you handle LinkedIn's DOM changes.
Drop your approach in the comments 👇