Person lookup
POST /v1/person returns a short profile summary for a LinkedIn profile URL or name.
POST https://api.happyfetch.net/v1/person
A person's profile summary: their name, location, the start of their About text, employers, schools and follower count.
Request#
| Field | Type | Required | Meaning |
|---|---|---|---|
url |
string | yes | The person's LinkedIn profile, in any of the forms below. |
max_age |
integer, seconds | no | The oldest cached answer you accept. 0 forces a fresh lookup. Defaults to 24 hours. See Caching. |
Every form of the same profile is the same lookup and the same cache entry:
| You send | Read as |
|---|---|
https://www.linkedin.com/in/jane-example |
the name jane-example. Any LinkedIn host, with or without the scheme, and the query is ignored. |
in/jane-example or jane-example |
the name jane-example |
j%C3%BCrgen-m%C3%BCller |
jürgen-müller: percent-encoded names are decoded |
Anything else is rejected with invalid_person_reference and isn't
charged. That includes company pages (the error points you to POST /v1/company) and member
ids (ACoAA…), which aren't accepted.
Example#
curl https://api.happyfetch.net/v1/person --max-time 120 \
-H "Authorization: Bearer $HAPPYFETCH_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.linkedin.com/in/jane-example"}'const res = await fetch("https://api.happyfetch.net/v1/person", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HAPPYFETCH_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(), // send the same key when you retry this call
},
body: JSON.stringify({
"url": "https://www.linkedin.com/in/jane-example"
}),
signal: AbortSignal.timeout(120_000),
});
const { data, meta, error } = await res.json();
if (!res.ok) throw new Error(`${error.code}: ${error.message}`);
console.log(meta.request_id, meta.cache.status, data);import os, uuid, requests
res = requests.post(
"https://api.happyfetch.net/v1/person",
headers={
"Authorization": f"Bearer {os.environ['HAPPYFETCH_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()), # send the same key when you retry this call
},
json={
"url": "https://www.linkedin.com/in/jane-example"
},
timeout=120,
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["meta"]["request_id"], body["meta"]["cache"]["status"])Response#
The complete response for a test profile, exactly as the API returns it:
{
"data": {
"vanityName": "jane-example",
"url": "https://www.linkedin.com/in/jane-example",
"name": "Jane Example",
"location": {
"locality": "Amsterdam",
"country": "NL"
},
"about": "Building the web at Vercel",
"currentEmployer": {
"name": "Vercel",
"slug": "vercel",
"linkedInUrl": "https://www.linkedin.com/company/vercel"
},
"employers": [
{
"name": "Vercel",
"slug": "vercel",
"linkedInUrl": "https://www.linkedin.com/company/vercel"
},
{
"name": "Stripe",
"slug": "stripe",
"linkedInUrl": "https://www.linkedin.com/company/stripe"
}
],
"employerCount": 3,
"education": [
{
"name": "Example University",
"slug": "example-university",
"linkedInUrl": "https://nl.linkedin.com/school/example-university/",
"startYear": 2012,
"endYear": 2016
}
],
"schoolCount": 2,
"followers": 1234
},
"meta": {
"request_id": "b7e2c915-0f4a-4d38-9a6e-3c81d5f02e94",
"endpoint": "person",
"credits_charged": 1,
"credits_remaining": 199,
"cache": {
"status": "miss",
"age_seconds": 0,
"fetched_at": "2026-09-25T10:04:18.000Z",
"max_age_seconds": 86400
},
"content_hash": "sha256:3f9a1c7e5b2d8046e1a9c3b7d5f2e8a4c6b1d9e3f7a5c2b8d4e6f1a3c9b7d5e2"
}
}| Field | Meaning |
|---|---|
vanityName, url |
The profile's name and its canonical URL. |
name |
The person's name. |
location |
locality and country, or null. |
about |
The start of the About text, or null. The headline isn't included. |
currentEmployer |
The first listed employer: the current job, or the latest one when none is current. null when there's none, or when the profile doesn't show it. |
employers |
The employers the profile shows, in its order, each with name, slug and linkedInUrl (null without a LinkedIn page). |
employerCount |
How many employers the profile lists, hidden ones included. |
education |
The schools the profile shows, each with its page and startYear and endYear when given. |
schoolCount |
How many schools the profile lists, hidden ones included. |
followers |
The follower count, or null. |
Job titles and dates aren't included, and some employers and schools may be missing. The counts tell you how many there are.
The content hash#
meta.content_hash covers data, so two answers with the same hash carry the same profile.
Caching#
A person is cached for 24 hours. A name without a profile is remembered too, and asking again within that time is answered from the cache for free. People are personal data, so we keep them only for a limited time after the last lookup, and delete them on request.
Price#
A person lookup costs 1 credit fetched now and 1 credit from cache. An answer that there's no profile at that name costs 1 credit, and nothing when it comes from the cache. Lookups that fail on our side are refunded automatically, and input that isn't a profile is never charged. See Credits, billing and refunds.