You have a list of LinkedIn profile URLs and need names, titles, companies and career history in a spreadsheet or your app. Here are the four ways people do it, what each one costs you, and working code for the one that doesn't touch your LinkedIn account.
Whatever tool you use, the goal is the same: turn a profile URL into structured fields. With EnrichGrid one profile comes back as JSON with:
No emails or phone numbers: this is professional profile data. See a full sample response.
| Approach | Uses your LinkedIn login? | Upkeep | Cost | Good for |
|---|---|---|---|---|
| Your own scraper (Python + headless browser) | Usually: logged-out visitors see a limited profile and soon hit a sign-in wall | High: page changes, blocks, proxies | Proxies and your time | Learning, small one-off jobs |
| Browser extensions that read the page | Yes, they run inside your session | Low for you; the risk sits with your account | Varies, often a subscription | A few profiles while browsing |
| Scraper platforms (Apify Actors, Bright Data, ScrapingDog) | Depends on the tool: many don't, some ask for your session cookie | Low | Per result, from about $1.30 per 1,000 at list price | Large jobs, many websites |
| Data APIs (EnrichGrid and others) | No | None: one HTTP call | EnrichGrid: $1.00–2.90 per 1,000 found profiles | Apps, CRMs, AI agents, steady pipelines |
Prices for other providers, with sources, are on the LinkedIn data API comparison.
LinkedIn's User Agreement forbids scraping and using bots or browser add-ons that copy profile data, and LinkedIn restricts accounts it connects to such tools. That's the main risk of anything that runs in your own session. EnrichGrid's API, Chrome extension and integrations don't use your LinkedIn login or act in your account.
On the legal side (not legal advice): in the US, hiQ Labs v. LinkedIn is the best-known case. The Ninth Circuit found that scraping publicly visible profiles likely isn't "access without authorization" under the CFAA, but hiQ was later found in breach of LinkedIn's User Agreement and the case ended in a settlement in 2022. In the EU and UK, profile data is personal data under the GDPR no matter who collects it: you need a lawful basis (often legitimate interest), should keep only what you need, and must honour objections and deletion requests.
Put one LinkedIn URL per line in profiles.txt, set ENRICHGRID_KEY to the key from your dashboard, and run:
import csv, os, time, requests
from concurrent.futures import ThreadPoolExecutor
API = "https://enrichgrid.com/v1"
H = {"x-api-key": os.environ["ENRICHGRID_KEY"]}
FIELDS = ["first_name", "last_name", "headline", "current_title", "current_company_name",
"location", "location_country", "follower_count", "num_connections"]
def enrich(url, max_wait=300):
for _ in range(5):
r = requests.post(f"{API}/enrich/person", headers=H, json={"identifier": url}, timeout=120)
if r.status_code in (429, 503): # too fast or busy: wait and retry
time.sleep(float(r.headers.get("Retry-After", 2)))
continue
r.raise_for_status() # 401 bad key, 402 out of credits
data = r.json()
poll, deadline = data.get("poll"), time.time() + max_wait
while data.get("status") == "pending" and time.time() < deadline: # 202: still collecting
time.sleep(3) # polling is free
data = requests.get("https://enrichgrid.com" + poll, headers=H, timeout=30).json()
return data
return {"found": False}
urls = [line.strip() for line in open("profiles.txt", encoding="utf-8") if line.strip()]
with ThreadPoolExecutor(max_workers=4) as pool: # results come back in input order
results = list(pool.map(enrich, urls))
with open("profiles.csv", "w", newline="", encoding="utf-8") as f:
out = csv.writer(f)
out.writerow(["linkedin_url", "found", *FIELDS])
for url, data in zip(urls, results):
profile = data.get("profile") or {}
out.writerow([url, bool(data.get("found")), *(profile.get(k, "") for k in FIELDS)])Most profiles come back in a few seconds. Slower ones return 202 with a poll link, which the loop checks for free. Free accounts can send 2 requests a second and paid plans 5 to 50; a 429 just means wait and retry, as the code does. More patterns are in the Python guide.
=ENRICHGRID() formula per row (guide).One credit per found profile; profiles we can't find cost nothing. Every account starts with 50 free credits, no card. Monthly plans run from $29 for 10,000 credits ($2.90 per 1,000) to $999 for 1,000,000 ($1.00 per 1,000), and a $10 top-up adds 2,500 credits. See pricing.
It depends on where you are, what you collect and how you use it. Courts in the US have treated public profile data differently from private data, and in the EU the GDPR applies to any personal data. LinkedIn's User Agreement forbids scraping, so tools that run in your account put that account at risk. This isn't legal advice.
Not with EnrichGrid. You send a profile URL to the API and get JSON back; your LinkedIn login isn't used.
No. EnrichGrid returns professional data: role, company, work history, education and skills.
A profile is collected live the first time it's requested and kept for up to 30 days. Send "live": true to collect it again.
There's no daily cap: your credits and requests per second are the limits (2 a second on the free plan, 5 to 50 on paid plans).
50 free credits. No credit card. Pay only for what we find.
Create a free account →