LinkedIn Company Scraper: Enrich B2B Leads With Firmographic Data
If you do B2B sales, you know this grind. A lead lands: john@acme.com. Before you can do anything useful with it, you're Googling "Acme," finding their LinkedIn page, eyeballing the employee count to gauge if they're a startup or an enterprise, checking the HQ for time zone, and pasting it all into your CRM. Five to ten minutes a lead. Fifty leads a day and that's your whole morning gone — on copy-paste.
The fix is to enrich leads automatically: feed in a company's LinkedIn URL, get back a clean firmographic record ready for your CRM. This guide builds exactly that with SociaVault, in JavaScript and Python, and shows how to layer in a growth signal that most enrichment tools miss.
What "enrichment" gets you
For each company you want the fields that actually drive qualification and routing:
- Size (employee count or range) — startup vs. mid-market vs. enterprise
- Industry — fit and segmentation
- Location / HQ — territory and time zone routing
- Website and description — quick context for the rep
- Follower count — a rough proxy for brand footprint
That's enough to score, route, and prioritize a lead automatically instead of by hand.
Step 1: Enrich one company
The company endpoint takes a LinkedIn company URL and returns the page's public data.
const API_KEY = process.env.SOCIAVAULT_API_KEY;
const BASE = "https://api.sociavault.com/v1";
async function enrichCompany(linkedinUrl) {
const res = await fetch(
`${BASE}/scrape/linkedin/company?url=${encodeURIComponent(linkedinUrl)}`,
{ headers: { "x-api-key": API_KEY } },
);
const json = await res.json();
if (!json.success) {
console.error(`Failed: ${linkedinUrl} — ${json.error}`);
return null;
}
const c = json.data;
// Log `c` once to confirm exact field names, then map what you need.
return {
name: c.name,
industry: c.industry,
headcount: c.employee_count ?? c.employeeCount ?? c.staff_count ?? null,
followers: c.follower_count ?? c.followerCount ?? null,
website: c.website ?? null,
description: c.description ?? null,
};
}
I read the fields defensively (employee_count ?? employeeCount ?? ...) because field naming can drift. On your first run, log the raw json.data, confirm the exact keys, and tighten the mapping to match.
Step 2: Batch a list of leads
In practice you've got a CSV of company URLs. Loop them with a small delay so you're not hammering the endpoint, and you have a batch enricher:
const leads = [
"https://www.linkedin.com/company/stripe",
"https://www.linkedin.com/company/airbnb",
"https://www.linkedin.com/company/notion-hq",
];
async function enrichAll(urls) {
const enriched = [];
for (const url of urls) {
const company = await enrichCompany(url);
if (company) {
enriched.push(company);
console.log(
`✓ ${company.name} — ${company.industry}, ${company.headcount} employees`,
);
}
await new Promise((r) => setTimeout(r, 300));
}
return enriched; // push these into HubSpot/Salesforce
}
enrichAll(leads);
The same thing in Python
import os, time, requests
API_KEY = os.environ["SOCIAVAULT_API_KEY"]
BASE = "https://api.sociavault.com/v1"
HEADERS = {"x-api-key": API_KEY}
def enrich_company(url):
r = requests.get(f"{BASE}/scrape/linkedin/company",
params={"url": url}, headers=HEADERS).json()
if not r.get("success"):
return None
c = r["data"]
return {
"name": c.get("name"),
"industry": c.get("industry"),
"headcount": c.get("employee_count") or c.get("employeeCount"),
"website": c.get("website"),
}
leads = [
"https://www.linkedin.com/company/stripe",
"https://www.linkedin.com/company/notion-hq",
]
for url in leads:
company = enrich_company(url)
if company:
print(f"{company['name']}: {company['industry']}, {company['headcount']} employees")
time.sleep(0.3)
Step 3: Add the signal most tools skip — growth
Static firmographics are table stakes. The thing that actually tells a rep when to reach out is movement. If you run this enrichment once a month and store the headcount each time, you can flag companies that are scaling fast — exactly the accounts most likely to have budget and new needs.
// After enriching, compare against last month's stored value
function growthSignal(name, current, previousByName) {
const prev = previousByName[name];
if (!prev || !current.headcount || !prev.headcount) return null;
const pct = ((current.headcount - prev.headcount) / prev.headcount) * 100;
if (pct >= 10)
return `🔥 ${name} grew ${pct.toFixed(0)}% — prioritize outreach`;
if (pct <= -10)
return `⚠️ ${name} shrank ${pct.toFixed(0)}% — deprioritize / check news`;
return null;
}
That single addition turns a static enrichment job into a prioritization engine. We go deeper on tracking it over time in tracking LinkedIn company growth.
A note on accuracy and scope
Enrichment from a public company page is excellent for firmographics — size, industry, location, description. It is not a substitute for verified contact data or precise financials, and the headcount is a public estimate (often a range), not an exact payroll figure. Use it to qualify, segment, and prioritize; pair it with your verified contact sources for outreach. And keep it to public company data — that's standard B2B research. For the broader landscape, see LinkedIn API alternatives.
Frequently Asked Questions
How do I enrich leads with LinkedIn company data?
Pass each company's LinkedIn URL to a company endpoint and map the returned fields (name, industry, headcount, location, website) into your CRM. Batch a list of URLs with a short delay between calls, as the code above shows, and you can enrich hundreds of leads automatically instead of researching each by hand.
Can I extract company information from a LinkedIn URL?
Yes. Given a public LinkedIn company URL, you can retrieve the page's public firmographic data — company name, industry, employee count, follower count, website, and description — as structured JSON. That's the core of automated lead enrichment.
Is the employee count exact?
No — it's a public estimate, often shown as a range (e.g. 501–1,000). It's reliable for segmenting companies by size and for tracking growth trends over time, but it isn't an exact, real-time payroll number. Treat it as a band, not a precise figure.
Is scraping LinkedIn company pages legal?
Reading publicly visible company-page data is standard competitive and sales research. Stay on public company information, respect rate limits, and don't attempt to access private profiles, connections, or anything behind a login. Use enrichment data responsibly and in line with privacy regulations for your market.
How much does enriching a lead cost?
With SociaVault, each company lookup is one credit. Enriching a list of 100 companies costs roughly 100 credits, and re-running monthly to capture growth signals adds the same again — trivial compared to the time it replaces.
Can I push this straight into HubSpot or Salesforce?
Yes. The enricher returns a clean object per company, so you map those fields to your CRM's API and upsert. Most teams run the enrichment as a scheduled job that reads new leads, enriches them, and writes the firmographics (and growth flag) back to the record automatically.
The bottom line
Lead enrichment shouldn't eat your sales team's morning. Feed in LinkedIn company URLs, get back clean firmographics, and add a monthly headcount comparison to surface the accounts that are actually heating up. The code is short; the time it saves is not.
Want to automate your enrichment? Start free with SociaVault — 50 credits, no card, enough to enrich your next batch of leads.
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API. No credit card required.