LinkedIn Profile Scraper API

Get job, company and education details from LinkedIn profile URLs, from your AI assistant, no-code workflow or own code.

From $0.02 per Profile
No LinkedIn Login Needed
10,000 Profiles per Task
Your list
LinkedIn profile URL
linkedin.com/in/maya-lindqvist
linkedin.com/in/tom-okafor
linkedin.com/in/lea-moreau
What you get back
Name
Current job
Location
Maya Lindqvist
Head of Sales at Brightwave Analytics
Stockholm
Tom Okafor
Operations Lead at Northpeak Logistics
Austin
Léa Moreau
Founder at Juniper & Vale Studio
Lyon
Trusted by 38,000+ users at startups and Fortune 500 teams
Amazon Airbus Uber FedEx SAP
Datadog
Zendesk
Works with any tool that can send HTTP requests
Claude ChatGPT Cursor Make n8n Zapier Your own code
Get Started

Pick Your Way In

Let an AI assistant or your automation tool do the setup, or call the REST API from your own code.

1

Paste the setup prompt

Copy the prompt for Claude, ChatGPT or Cursor, or for Make, n8n or Zapier, and paste it in. The AI creates a Datablist folder on your computer and sets everything up.

2

Paste your API key

When the AI asks, copy your API key from the Datablist app and paste it into the .env file it opened. Never paste it into the chat.

Get your API key
3

Get your results

Send your list of LinkedIn profile URLs and get one row back per profile: name, headline, location, current job and company, ready for your sheet or CRM.

See a sample result
Using Make, n8n or Zapier? Here is every field for the HTTP request

Use the HTTP request module or node your tool offers. You need three steps: send the list, wait, then read the results.

1. Send your list (HTTP request)

Method
POST
URL
https://api.datablist.com/v1/enrichments/tasks
Headers
X-API-Key = your API key
Content-Type = application/json
Body (JSON)
{
  "enrichmentId": "linkedin-profile-scraper",
  "uniqueId": "linkedin-profile-scraper-import-1",
  "settings": {
    "experiencesNb": "3",
    "educationsNb": "1"
  },
  "inputs": [
    {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
    {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
    {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
  ]
}
Keep
The @id from the response. That is your task ID.

2. Wait until it is done

Add a short wait or delay, then a GET request to https://api.datablist.com/v1/enrichments/tasks/TASK_ID with the same X-API-Key header. Repeat until status is completed.

3. Read the results

GET https://api.datablist.com/v1/enrichments/tasks/TASK_ID/results?limit=50. Map outputs to your columns. If nextCursor is not empty, call again with &cursor= plus that value.

Create a task with one request. The full script with polling and results is in the developer section.

Create a task
curl --request POST 'https://api.datablist.com/v1/enrichments/tasks' \
  --header 'X-API-Key: YOUR_PERSONAL_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "enrichmentId": "linkedin-profile-scraper",
    "uniqueId": "linkedin-profile-scraper-import-1",
    "settings": {
      "experiencesNb": "3",
      "educationsNb": "1"
    },
    "inputs": [
      {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
      {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
      {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
    ]
  }'
import requests

response = requests.post(
    "https://api.datablist.com/v1/enrichments/tasks",
    headers={"X-API-Key": "YOUR_PERSONAL_API_KEY"},
    json={
      "enrichmentId": "linkedin-profile-scraper",
      "uniqueId": "linkedin-profile-scraper-import-1",
      "settings": {
        "experiencesNb": "3",
        "educationsNb": "1"
      },
      "inputs": [
        {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
        {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
        {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
      ]
    },
)
task = response.json()
print(task["@id"], task["status"])
const response = await fetch("https://api.datablist.com/v1/enrichments/tasks", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_PERSONAL_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "enrichmentId": "linkedin-profile-scraper",
    "uniqueId": "linkedin-profile-scraper-import-1",
    "settings": {
      "experiencesNb": "3",
      "educationsNb": "1"
    },
    "inputs": [
      {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
      {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
      {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
    ]
  }),
});
const task = await response.json();
console.log(task["@id"], task.status);
Overview

At a Glance

Fresh public profile data from a LinkedIn URL: who the person is, where they work and what they studied. No Datablist workspace, collection or import needed.

What you give it
  • LinkedIn profile URLs: Standard profile links or Sales Navigator lead links
  • How much history (optional): 3, 5 or 10 past jobs and 1, 3 or 5 schools
  • Cached profiles (optional): Accept a recent saved copy to pay less
What it costs
  • Fresh profile: 25 credits per profile
  • Cached profile: 20 credits when you accept a saved copy
  • 1,000 credits = $1: Shared with the Datablist app
Use Cases

What Teams Build With It

Put LinkedIn Profile Scraper wherever your data already flows.

Sales and SDRs
Research leads before outreach
LinkedIn URL from a lead listScrape the profileTitle, company, location
Pull the current role and company for every lead, so your sequence starts with the right person and a relevant first line.
Recruiting
Build candidate profiles
Candidate LinkedIn URLScrape the profileJobs and education in your ATS
Get past jobs and education for every candidate and keep your ATS or sheet up to date without copy and paste.
RevOps
Spot job changes
Contacts in the CRMScrape the profileNew company flagged
Re-run your contacts and compare the current company with the CRM to catch champions who moved to a new account.
Pricing

What Will It Cost You?

Pay per lookup with credits. API access starts on the Growth plan.

Calculator

How much will it cost you?

Tell us how many LinkedIn profiles you need and we'll show you the cheapest way to get them.

= 25,000 credits
Fresh or cached?
Recommended planGrowth: $50/mo
Credit top-up-
Credits you'll have20,000
Total this month $50
Same credits as the Datablist app • View pricing
How credits work
1,000 credits = $1, so each credit costs a tenth of a cent. A fresh profile costs 25 credits and a cached profile 20 credits. A profile that cannot be found may still cost credits, because the lookup work was done. Every result returns creditsUsed, so you can track the real cost per row. Plan credits renew monthly and reset if unused. Top-up credits never expire.
For Developers

Build It Into Your Code

Everything you need to call the REST API directly: code, responses, endpoints, fields, authentication and limits.

datablist/linkedin-profile-scraper-api
Official examples: cURL, Python with Requests or async HTTPX, and TypeScript. Put your key in DATABLIST_API_KEY and run.
Open repository ↗

Copy, Paste, Run

A complete script that creates a task, waits for it and prints every result. Replace YOUR_PERSONAL_API_KEY with your key.

# 1. Create the task (returns 202 Accepted and the task "@id")
curl --request POST 'https://api.datablist.com/v1/enrichments/tasks' \
  --header 'X-API-Key: YOUR_PERSONAL_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "enrichmentId": "linkedin-profile-scraper",
    "uniqueId": "linkedin-profile-scraper-import-1",
    "settings": {
      "experiencesNb": "3",
      "educationsNb": "1"
    },
    "inputs": [
      {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
      {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
      {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
    ]
  }'

# 2. Poll every few seconds until status is completed, failed or stopped
curl 'https://api.datablist.com/v1/enrichments/tasks/TASK_ID' \
  --header 'X-API-Key: YOUR_PERSONAL_API_KEY'

# 3. Read the results, then follow nextCursor until it is null
curl 'https://api.datablist.com/v1/enrichments/tasks/TASK_ID/results?limit=50' \
  --header 'X-API-Key: YOUR_PERSONAL_API_KEY'
import time
import requests

BASE = "https://api.datablist.com/v1/enrichments"
HEADERS = {"X-API-Key": "YOUR_PERSONAL_API_KEY"}

# 1. Create the task
response = requests.post(f"{BASE}/tasks", headers=HEADERS, json={
  "enrichmentId": "linkedin-profile-scraper",
  "uniqueId": "linkedin-profile-scraper-import-1",
  "settings": {
    "experiencesNb": "3",
    "educationsNb": "1"
  },
  "inputs": [
    {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
    {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
    {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
  ]
})
response.raise_for_status()
task_id = response.json()["@id"]

# 2. Poll until the task finishes
while True:
    task = requests.get(f"{BASE}/tasks/{task_id}", headers=HEADERS).json()
    if task["status"] in ("completed", "failed", "stopped"):
        break
    time.sleep(5)

# 3. Read every result page
params = {"limit": 50}
while True:
    page = requests.get(f"{BASE}/tasks/{task_id}/results", headers=HEADERS, params=params).json()
    for result in page["results"]:
        print(result["inputId"], result["status"], result["outputs"])
    if not page["nextCursor"]:
        break
    params["cursor"] = page["nextCursor"]
// Node.js 18+ or any runtime with fetch. Keep your key on the server.
const BASE = "https://api.datablist.com/v1/enrichments";
const HEADERS = { "X-API-Key": "YOUR_PERSONAL_API_KEY" };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

// 1. Create the task
const created = await fetch(`${BASE}/tasks`, {
  method: "POST",
  headers: { ...HEADERS, "Content-Type": "application/json" },
  body: JSON.stringify({
    "enrichmentId": "linkedin-profile-scraper",
    "uniqueId": "linkedin-profile-scraper-import-1",
    "settings": {
      "experiencesNb": "3",
      "educationsNb": "1"
    },
    "inputs": [
      {"inputId": "row-1", "data": {"profileUrl": "https://www.linkedin.com/in/maya-lindqvist/"}},
      {"inputId": "row-2", "data": {"profileUrl": "https://www.linkedin.com/in/tom-okafor/"}},
      {"inputId": "row-3", "data": {"profileUrl": "https://www.linkedin.com/in/lea-moreau/"}}
    ]
  }),
});
if (!created.ok) throw new Error(`Create failed: ${created.status}`);
const taskId = (await created.json())["@id"];

// 2. Poll until the task finishes
let task;
do {
  await sleep(5000);
  task = await (await fetch(`${BASE}/tasks/${taskId}`, { headers: HEADERS })).json();
} while (!["completed", "failed", "stopped"].includes(task.status));

// 3. Read every result page
let cursor = null;
do {
  const url = new URL(`${BASE}/tasks/${taskId}/results`);
  url.searchParams.set("limit", "50");
  if (cursor) url.searchParams.set("cursor", cursor);
  const page = await (await fetch(url, { headers: HEADERS })).json();
  for (const result of page.results) {
    console.log(result.inputId, result.status, result.outputs);
  }
  cursor = page.nextCursor;
} while (cursor);

What the API Returns

One result per input, with your inputId, a status, the outputs and the credits used. Sample data.

{
  "taskId": "00000000000040008000000000000001",
  "results": [
    {
      "inputId": "row-1",
      "status": "success",
      "outputs": {
        "profileUrl": "https://www.linkedin.com/in/maya-lindqvist/",
        "firstName": "Maya",
        "lastName": "Lindqvist",
        "fullName": "Maya Lindqvist",
        "linkedInHeadline": "Head of Sales at Brightwave Analytics",
        "linkedInCity": "Stockholm",
        "linkedInCountryCode": "SE",
        "linkedInLocation": "Stockholm, Sweden",
        "linkedInlastExpTitle": "Head of Sales",
        "linkedInlastExpStartsAt": "2023-02-01",
        "linkedInlastExpCompany": "Brightwave Analytics",
        "linkedInlastExpCompanyWebsite": "https://www.brightwaveanalytics.com",
        "linkedInlastExpCompanyIndustry": "Software Development",
        "linkedInlastExpCompanyRange": "51-200",
        "linkedInlastEduSchool": "Example University",
        "linkedInLanguages": "English, Swedish",
        "linkedInConnections": "500"
      },
      "creditsUsed": "25",
      "error": null
    }
  ],
  "nextCursor": null
}

Endpoints and Fields

All paths are relative to https://api.datablist.com. Field definitions come from GET /v1/enrichments/linkedin-profile-scraper (docs updated Oct 21, 2026).

GET/v1/enrichments/linkedin-profile-scraperRead the schema, no key needed
POST/v1/enrichments/tasksCreate a task
GET/v1/enrichments/tasks/{taskId}Poll status and progress
GET/v1/enrichments/tasks/{taskId}/resultsRead results, 1 to 100 per page
POST/v1/enrichments/tasks/{taskId}/stopCancel a running task
GET/v1/enrichments/tasksTask history, newest first
Schema Reference
Send settings once per task and one data object per input. Results can include extra fields as the enrichment evolves, so keep unknown keys when you parse outputs.
Show all settings, inputs and outputs
Settings
experiencesNbExperiences Text Number of work experiences to return, sent as a string. One of: "3" (default), "5", "10".
educationsNbEducations Text Number of education entries to return, sent as a string. One of: "1" (default), "3", "5".
acceptCachedProfilesAccept cached profiles Boolean Use a cached profile when available, at 20 credits instead of 25. Applies when includeUrn and includePictures are false.
includeUrnInclude URN Boolean Include the LinkedIn internal identifier (URN), which you can use to build Sales Navigator URLs. Applies when acceptCachedProfiles is false.
includePicturesInclude pictures Boolean Include the profile picture and company logo URLs. These URLs expire fast, so download the images. Applies when acceptCachedProfiles is false.
Inputs (data)
profileUrlrequiredLinkedIn Profile Text Standard profile URL (https://linkedin.com/in/xxx) or Sales Navigator URL (https://www.linkedin.com/sales/lead/xxx).
Outputs
profileUrlProfile URL URL The clean public profile URL, in the format https://www.linkedin.com/in/xxx.
firstNameFirst Name Text First name of the profile.
lastNameLast Name Text Last name of the profile.
fullNameFull Name Text Full name of the profile.
linkedInHeadlineHeadline Text The tagline on the profile.
linkedInSummarySummary Text The longer blurb written by the person.
linkedInCityCity Text City of the profile.
linkedInStateState Text State of the profile.
linkedInCountryCodeCountry Code Text ISO 3166-1 alpha-2 country code.
linkedInCountryNameCountry Text Country of residence, in English.
linkedInLocationLocation Text Full location text.
linkedInlastExpTitleCurrent Job Title Text Title of the current (or last) experience. Also linkedInlastExpEmploymentType, linkedInlastExpDescription, linkedInlastExpStartsAt, linkedInlastExpEndsAt and linkedInlastExpLocation.
linkedInlastExpCompanyCurrent Company Text Company of the current (or last) experience. Also linkedInlastExpCompanyPage, linkedInlastExpCompanyWebsite, linkedInlastExpCompanyDescription, linkedInlastExpCompanyIndustry and linkedInlastExpCompanyRange (size, like 11-50).
linkedIn2ExpTitlePrevious Jobs Text Second most recent experience, with EmploymentType, Description, StartsAt, EndsAt and CompanyName. linkedIn3Exp... and beyond follow when you ask for more experiences.
linkedInlastEduSchoolSchool Text School of the current (or last) education. Also linkedInlastEduDegree, linkedInlastEduField, linkedInlastEduStartsAt and linkedInlastEduEndsAt.
linkedInLanguagesLanguages Text Comma-separated list of spoken languages.
linkedInConnectionsConnections Text Number of connections.
linkedInInternalIdentifierURN Text LinkedIn internal identifier. Applies when includeUrn is true.
linkedInProfilePictureProfile Picture Text Picture URL, plus linkedInlastExpCompanyLogo, linkedIn2ExpLogo and linkedInlastEduLogo. These URLs expire fast. Applies when includePictures is true.

One Header, Clear Limits

Create a Personal API Key in your Datablist account and send it on every authenticated request.

Authentication

Send your key in the X-API-Key header. Datablist exchanges and renews access tokens for you.

  • Header: X-API-Key: YOUR_PERSONAL_API_KEY
  • Optional: manage tokens yourself with Authorization: Bearer from POST /v1/account/token
  • One or the other: sending both headers returns 400 AmbiguousCredentials
  • Server side only: keep keys out of URLs, browser code and logs

Limits

  • Inputs per task: 1 to 10,000
  • Size: 16 KiB per input, 10 MiB per request
  • Run time: up to 24 hours per task
  • Task creation: 10 requests per 60 seconds per account
  • Polling and results: 120 requests per 60 seconds per operation
  • Active tasks: about 20 at once per account
  • Retention: tasks and results are kept for 90 days

Prefer No Code at All?
Run LinkedIn Profile Scraper in the App

Upload a CSV or Excel file, pick a column and run the same enrichment in a few clicks. 38,000+ users are already on Datablist.

See the no-code version
Guides

Related Tutorials

Learn the newest workflows with detailed step-by-step guides.

FAQ

Frequently Asked Questions

Everything you or your AI coding agent need to integrate the LinkedIn Profile Scraper API: auth, request, polling, results, limits and retries.

Send your Personal API Key in the X-API-Key header on every request. Create the key at https://app.datablist.com/account/api; API access starts on the Growth plan. Keep it server side, for example in a DATABLIST_API_KEY environment variable or a .env file, and never put it in URLs, browser code or shared chats.
The API is asynchronous. POST /v1/enrichments/tasks returns 202 Accepted with the task @id. Poll GET /v1/enrichments/tasks/{taskId} every few seconds until the status is completed, failed or stopped, then read GET /v1/enrichments/tasks/{taskId}/results.
A JSON object with enrichmentId set to "linkedin-profile-scraper", your own uniqueId, a settings object sent once per task and an inputs array. Each input has an inputId and a data object, here with profileUrl. GET /v1/enrichments/linkedin-profile-scraper returns the full schema of settings, inputs and outputs.
Request up to 100 results per page with the limit parameter and follow nextCursor until it is null. Each result carries your inputId, a status, the outputs, creditsUsed and an error field. Match rows by inputId and ignore output keys you do not know, since new fields can be added. Results are kept for 90 days.
1 to 10,000 inputs per task, 16 KiB per input and 10 MiB per request. Task creation allows 10 requests per 60 seconds per account, polling and results 120 requests per 60 seconds per operation, and about 20 tasks can be active at once.
Do not send the same POST again blindly, the task may already be running. Look up your uniqueId in GET /v1/enrichments/tasks first; reusing the uniqueId of an active task returns 409. POST /v1/enrichments/tasks/{taskId}/stop cancels a task you no longer need.
Yes. Click Set up with AI and paste the prompt into Claude, ChatGPT or Cursor. The prompt is one line with a link to the Datablist setup skill on GitHub, the same for every Datablist API. The assistant follows the skill, creates a Datablist folder and a .env file, asks you to paste your API key into it, then asks which enrichment to run. In Make, n8n or Zapier you add an HTTP request step with the fields listed on this page.
No. Datablist fetches the public profile data for you. You never share a LinkedIn login, cookie or session, so your own account is never at risk.
Fresh profiles are fetched live and cost 25 credits. Set acceptCachedProfiles to true to use a recent saved copy when one exists, at 20 credits. Cached profiles cannot return the URN or pictures.
Yes. Send a standard profile URL or a Sales Navigator lead URL in profileUrl. The result always returns the clean public profile URL in profileUrl.
Keep Building

Related APIs, Enrichments and Free Tools

Chain LinkedIn Profile Scraper with other enrichments, in your code, in the Datablist app or for free.