How to Get LinkedIn Profile Data with an API (2026)
You want a person's public LinkedIn profile as data: their name, what they do, where they are. Doing it by hand means opening the page, copying fields, and pasting them somewhere — fine for one person, hopeless for a thousand. An API turns that into a single request that returns clean JSON.
This guide shows you exactly how, with one endpoint and a few lines of Python. But it also does something most "LinkedIn profile API" posts refuse to do: it tells you the truth about coverage. Public profile data is best-effort. Most well-formed public profiles return solid basics; some return sparse records or nothing at all. I ran five real profiles to show you both outcomes, so you build with correct expectations instead of discovering the gaps in production.
TL;DR: Call GET /api/linkedin/profile?username=<vanity> (or ?url=) with an X-API-Key header and get back the public profile card — name, headline, current role, location, photo and summary — as JSON. Coverage is best-effort, so always handle missing fields. Basic profile is $0.50/1K on Default, down to $0.025/1K at Scale. It reads publicly available LinkedIn data only; no login required. Real data and working code below.
What the basic profile endpoint returns
The basic profile endpoint gives you the public headline card of a LinkedIn profile — the part anyone can see without being connected — as structured JSON. Here is a real response, pulled live on July 2, 2026, trimmed to the fields that matter:
{
"success": true,
"data": {
"public_identifier": "williamhgates",
"profile_url": "https://www.linkedin.com/in/williamhgates",
"first_name": "Bill",
"last_name": "Gates",
"full_name": "Bill Gates",
"headline": "Co-chair / Founder / Co-founder",
"occupation": "Co-chair / Founder / Co-founder",
"summary": "Chair of the Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft. Voracious reader. Avid traveler. Active blogger.",
"location": { "city": "Seattle, Washington, United States", "country": "US" },
"profile_pic_url": "https://media.licdn.com/dms/image/..."
}
}
Every one of these fields is drawn from the public top of the profile:
| Field | What it is |
|---|---|
full_name / first_name / last_name | The person's display name, split for convenience |
headline | The tagline under the name (roles, title) |
occupation | Current role summary |
summary | The "About" text, when the person has one |
location | City and country object |
profile_pic_url | Public profile photo URL |
public_identifier / profile_url | The stable vanity slug and canonical URL |
The endpoint: two ways to identify a person
There is one endpoint, and you can identify the person either by their vanity username or by their full profile URL. Both resolve to the same profile.
GET https://apiserpent.com/api/linkedin/profile?username=williamhgates
# or, equivalently:
GET https://apiserpent.com/api/linkedin/profile?url=https://www.linkedin.com/in/williamhgates
Header: X-API-Key: YOUR_API_KEY
A minimal cURL check:
curl "https://apiserpent.com/api/linkedin/profile?username=williamhgates" \
-H "X-API-Key: YOUR_API_KEY"
The public_identifier in the response is the vanity slug (williamhgates) — the stable key to store, since display names change but the slug rarely does.
What "best-effort" really means (real data)
This is the part I promised to be straight about. Public profile retrieval is best-effort, and the honest way to prove it is to run several profiles and show you the mix. So I called five well-known public figures on July 2, 2026. Here is exactly what came back:
| Username | Result | Name | Headline (first role) |
|---|---|---|---|
| williamhgates | ✅ full | Bill Gates | Co-chair |
| reidhoffman | ✅ full | Reid Hoffman | Co-Founder, Executive Board Chair |
| melindagates | ✅ full | Melinda French Gates | Founder |
| satyanadella | ⚠️ no record | — | — |
| jeffweiner | ⚠️ inconsistent | Jeff Weiner | (partial on some calls) |
Method: one live GET /api/linkedin/profile?username=… per person on 2026-07-02. Three returned clean, complete basics; one returned no usable record on that pull; one varied between calls.
Three of five came back clean and complete — good name, headline, location, summary and photo. Two did not: one returned no usable record, and one was inconsistent between calls. That is the reality of the public profile surface, and it leads to three rules you should build in from the start:
- Never assume a field exists. Any field — even the name — can be absent. Read defensively.
- Treat it as an enrichment, not a guarantee. Budget for a meaningful fraction of profiles to come back thin, and design the flow to keep going rather than to require every record.
- When you need reliability, lean on company data. Serpent's company endpoint is the most complete and consistent LinkedIn dataset; profile basics are a lighter, best-effort complement to it.
Fetching a profile in Python
Here is a small, defensive fetcher. It accepts either a username or a URL, treats "not found" and "temporarily unavailable" as a graceful None instead of a crash, and prints a clean one-line summary that survives missing fields.
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://apiserpent.com/api/linkedin/profile"
def get_profile(identifier):
"""Fetch a basic public profile by vanity username or full URL.
Returns the data dict, or None if the profile can't be retrieved."""
key = "url" if identifier.startswith("http") else "username"
r = requests.get(BASE, headers={"X-API-Key": API_KEY},
params={key: identifier}, timeout=60)
if r.status_code in (404, 503): # not found / temporarily unavailable
return None
r.raise_for_status()
return r.json().get("data", {})
def summarize(identifier):
d = get_profile(identifier)
if not d:
return f"{identifier}: no data (404/503)"
if not d.get("full_name"):
return f"{identifier}: empty record (best-effort miss)"
loc = (d.get("location") or {}).get("city") or ""
role = (d.get("headline") or "").split(" / ")[0]
return f"{identifier}: {d['full_name']} | {role} | {loc}"
for user in ["williamhgates", "reidhoffman", "melindagates"]:
print(summarize(user))
The load-bearing detail is that get_profile returns None on a miss and every reader uses .get() with fallbacks. Run this over a list of a few thousand usernames and it will process the whole batch unattended — the misses become skipped rows, not exceptions.
Try it on your own list. Create a key in under a minute — new accounts include 10 free Google searches to explore the platform. Grab a free key, drop it into the script, and fetch your first profiles.
What the basic endpoint does not return
Being honest about coverage also means being clear about scope. The basic endpoint returns the public card — the top of the profile. It does not return:
- Full work history with dates and descriptions
- Education, certifications, or skills lists
- Connections, followers, or the person's network
- Email addresses, phone numbers, or any private contact detail
If you genuinely need the deeper fields — detailed experience and education — those are handled by a separate premium profile endpoint, priced on its own tier. But for the large majority of enrichment jobs, the basic card plus company firmographics is all you need, and it is a fraction of the cost. Reach for the premium endpoint only when the deeper fields are the actual requirement.
What basic profile data is good for
The public card is lightweight, but it answers a surprising number of real questions:
1. Confirming and normalizing a contact
You have an email and a guessed LinkedIn handle. One call confirms the person exists, gives you their canonical name and current role, and returns the stable public_identifier to store — turning a fuzzy contact into a clean record.
2. Lightweight lead context
Before a call, the headline and location tell a rep who they are talking to and roughly what they do. Combined with the account's firmographic fit score, it is enough context to personalize an opener without a research rabbit hole.
3. Directory and profile displays
Building a partner directory, a speaker page, or a team roster? The name, headline, photo and profile link are exactly the fields such a display needs — pulled once and cached.
Errors and missing fields
The endpoint uses neutral, predictable status codes so your handling stays simple:
| Status | Meaning | What to do |
|---|---|---|
200 | Success — {"success": true, "data": {…}} | Read fields with .get() fallbacks |
400 | Missing url/username | Fix the request; don't retry |
404 | Profile not found | Skip the record |
429 | Rate limit for your bracket | Honor Retry-After, retry |
503 | Temporarily unavailable | Back off and retry, then skip |
Because coverage is best-effort, treat a thin 200 (a record with a null full_name) the same way you treat a 404: log it and move on. The full semantics are in the API docs.
Pricing
Basic profile is the lightest LinkedIn dataset and is priced accordingly — pay-as-you-go, no subscription.
| Tier | Unlock | Profile price | Per call |
|---|---|---|---|
| Default | None | $0.50 / 1,000 | $0.0005 |
| Growth | One $100 deposit (10× off) | $0.05 / 1,000 | $0.00005 |
| Scale | One $500 deposit (20× off) | $0.025 / 1,000 | $0.000025 |
At Default, ten thousand profile lookups is $5.00; at Scale it is $0.25. The same deposit unlocks the discount across every endpoint, so profile, company and jobs all draw from one balance. See the full pricing page for the other LinkedIn datasets and the SERP APIs.
A note on compliance
Profile data deserves more care than any other dataset, so be precise about what this is. Serpent's basic profile endpoint accesses publicly available LinkedIn profile data only — the parts of a profile anyone can view without logging in. There is no login, password, cookie, or credential in the flow, and no access to private or connection-gated fields.
That said, "public" is not the same as "unrestricted". Whether your specific use is permitted depends on LinkedIn's terms, your jurisdiction, and — especially for personal data — privacy law like GDPR or CCPA. Handling people's information carries obligations that handling company data does not. Treat compliance as your own decision, get advice for anything at scale, and do not read this article as a blanket permission to collect or store personal profiles. The API only ever touches public data and never authenticates as a user; you remain responsible for lawful use.
Get public LinkedIn profile data as clean JSON
One GET request returns a person's public card — name, headline, current role, location, photo and summary. Best-effort coverage, honest pricing, no login. Basic profile from $0.50/1K, dropping to $0.025/1K at Scale, pay-as-you-go with no subscription.
Get Your Free API KeyExplore: LinkedIn API · Social Media APIs · Pricing
FAQ
What data does the LinkedIn profile API return?
The basic profile endpoint returns the public "card" for a person: full name (and first/last), headline, current role or occupation, location, a profile photo URL, the summary text when present, and the stable public identifier and profile URL. It is the publicly visible top of a LinkedIn profile as structured JSON — not a full résumé export.
How complete is the LinkedIn profile data?
Basic profile data is best-effort. In a real July 2026 test of five well-known public profiles, three returned clean, complete basics and two returned a sparse or empty record on that call. Coverage varies by profile and can differ between calls, so treat it as an enrichment that usually succeeds rather than a guarantee, and always write code that handles missing fields. Company data is the most complete and consistent LinkedIn dataset if you need reliability.
Can I get work history, education, and skills from the profile API?
Not from the basic profile endpoint, which returns the public headline card — name, headline, current role, location, photo, and summary. Richer fields such as detailed experience and education are handled by a separate premium profile endpoint. For most enrichment jobs the basic card plus company firmographics is enough; reach for the premium endpoint only when you specifically need the deeper fields.
How much does the LinkedIn profile API cost?
Basic profile data is $0.50 per 1,000 requests on Default. A single $100 deposit unlocks Growth at 10× off ($0.05/1,000) and a single $500 deposit unlocks Scale at 20× off ($0.025/1,000). It is pay-as-you-go with no subscription, and new accounts include free calls to test.
Do I need a LinkedIn login to use the profile API?
No. You send a public profile URL or vanity username and your Serpent API key in an X-API-Key header. The endpoint accesses publicly available LinkedIn profile data only — there is no LinkedIn login, cookie, or OAuth flow on your side, and no access to private or connection-gated fields. You remain responsible for using the data lawfully and within LinkedIn's terms.



