LinkedIn Profile Scraper: Experience, Skills & Education avatar

LinkedIn Profile Scraper: Experience, Skills & Education

Pricing

from $5.20 / 1,000 profile scrapeds

Go to Apify Store
LinkedIn Profile Scraper: Experience, Skills & Education

LinkedIn Profile Scraper: Experience, Skills & Education

Scrape public LinkedIn profiles by URL, with no login or cookies: name, headline, location, about, full work experience, education, skills, languages, certifications, volunteering, projects, publications and follower count. Failed profiles are not charged.

Pricing

from $5.20 / 1,000 profile scrapeds

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

3

Bookmarked

692

Total users

53

Monthly active users

2 hours ago

Last modified

Features

Limited permissionsMulti-tenantServer interface

Share

LinkedIn Profile Scraper

Scrape LinkedIn public profiles at scale โ€” no login, no user-provided cookies, no browser. Extract structured data from any LinkedIn profile URL using fast HTTP requests and residential proxies.

What does LinkedIn Profile Scraper do?

LinkedIn Profile Scraper extracts structured data from public LinkedIn profile pages. It works entirely through HTTP requests with residential proxies โ€” no LinkedIn account, login credentials, or user-provided cookies required.

For each profile, the scraper returns:

  • A machine-readable success flag and nullable error reason on every row
  • Full name, headline, and location
  • About/summary section
  • Follower and connection counts
  • Profile image URL
  • Full work experience: title, company, company URL, location, start and end dates, duration, and description
  • Current positions (the ongoing roles from that history)
  • Education history with institution, degree, years, and school URL
  • Skills, languages with proficiency, and licenses & certifications
  • Volunteering, projects, publications, and honors & awards
  • Cover image and personal websites exposed by the public profile
  • Timestamp of when the data was scraped

The actor reads the public profile page that LinkedIn shows to logged-out visitors: its JSON-LD data and its visible sections. Fields LinkedIn hides from logged-out visitors (it masks them with ****) are returned as null, never as placeholder text. A section the person did not fill in, or that LinkedIn does not show publicly, is an empty list. It processes profiles sequentially to reduce blocking and automatically retries failed requests across up to 4 fresh proxy sessions.

Use for engagement-lead enrichment

After collecting LinkedIn profile URLs from engagement workflows, run them through this actor to add headline, location, about text, current positions, education, follower count, websites, and canonical URLs. Use those fields to score fit and personalize outreach before sending sales outreach messages.

Who is it for?

๐Ÿ” Recruiters and talent sourcers โ€” Build candidate pipelines by scraping profiles in bulk. Export to your ATS or spreadsheet for easy filtering by headline, location, and experience.

๐Ÿ“Š Sales and business development teams โ€” Enrich your prospect lists with up-to-date LinkedIn data. Get headlines, company info, and follower counts to prioritize outreach.

๐Ÿงช Market researchers โ€” Analyze workforce trends, job title distributions, and career trajectories across industries at scale.

๐Ÿค– Data engineers and developers โ€” Feed structured LinkedIn data into your pipelines, CRMs, or machine learning models via API or webhooks.

๐Ÿ“ˆ Growth hackers and marketers โ€” Identify influencers and thought leaders by follower count, build targeted audience segments, and track competitor teams.

Why use LinkedIn Profile Scraper?

๐Ÿšซ No login required โ€” Unlike most LinkedIn scrapers, this one works without any LinkedIn account. No risk of account bans or credential management.

โšก Fast HTTP-based scraping โ€” No headless browser overhead. Profiles are fetched via got-scraping with Cheerio parsing, making it significantly faster and cheaper than browser-based alternatives.

๐Ÿ”„ Automatic retries โ€” LinkedIn occasionally returns 999 status codes as an anti-bot measure. The scraper automatically makes up to 4 attempts per profile with different proxy sessions.

๐Ÿ’ฐ Pay per useful result โ€” The profile event is charged only after a usable profile name and canonical LinkedIn URL are validated. Blocked, login, missing, and unparseable pages produce explicit success: false rows without a profile event charge.

๐Ÿ“ฆ Clean structured output โ€” Every profile is returned as a flat JSON object ready for import into databases, spreadsheets, or APIs.

๐Ÿ”— Flexible input โ€” Pass full LinkedIn URLs or just profile slugs (e.g., williamhgates). A leading @ on a handle or URL slug is removed without changing the remaining identifier.

Data extraction table

FieldTypeDescription
successBooleantrue only when a usable public profile identity was extracted
errorString or nullFailure reason for unsuccessful rows; null on success
nameString or nullFull name from the profile
linkedinUrlStringCanonical LinkedIn profile URL
headlineString or nullProfessional headline; null when LinkedIn does not show it publicly
locationStringLocation as displayed on the profile
aboutStringAbout/summary section text
followerCountNumberTotal follower count
connectionCountStringConnection count (may show "500+")
profileImageUrlStringURL to the profile photo
backgroundImageUrlString or nullProfile cover image URL
currentPositionsArrayCurrent job positions with title, company, startDate
experienceArrayFull work history: title, company, companyUrl, location, startDate, endDate, duration, isCurrent, description
educationArrayEducation entries with institution, degree, startYear, endYear, schoolUrl, description
skillsArraySkill names from the public Skills section
languagesArrayLanguage names
languageProficienciesArrayLanguages with proficiency, e.g. { "name": "French", "proficiency": "Elementary proficiency" }
certificationsArrayLicenses & certifications: name, issuer, issuedDate, credentialUrl
volunteeringArrayVolunteer roles: role, organization, startDate, endDate, isCurrent, description
projectsArrayProjects: title, startDate, endDate, description
publicationsArrayPublications: title, publisher, date, description
honorsAndAwardsArrayHonors & awards: title, issuer, date, description
websitesArrayWebsites linked on the profile
scrapedAtStringISO 8601 timestamp of when the profile was scraped

How much does it cost to scrape LinkedIn profiles?

LinkedIn Profile Scraper uses Apify's pay-per-event pricing model. A tiered run-start event is charged once, and you pay a tiered profile event only for profiles that pass the useful-profile validation.

Apify planRun startPer validated profile
Free$0.01$0.008
Bronze$0.0095$0.0072
Silver$0.0085$0.0064
Gold$0.0075$0.0052
Platinum$0.006$0.004
Diamond$0.005$0.0032

Computed actor-charge example: 100 validated profiles cost about $0.81 on Free or $0.7295 on Bronze (run-start charge + 100 profile events). Error rows do not incur the profile event.

From 26 November 2026 the price will be: a flat $0.005 run start on every plan, and per validated profile $0.0072 on Free and Bronze, $0.00648 on Silver, and $0.00576 on Gold, Platinum and Diamond. 100 validated profiles will then cost about $0.725 on Free or Bronze.

Residential proxy costs are included in these actor charges โ€” no separate proxy fee.

How to scrape LinkedIn profiles

  1. ๐Ÿ“ Go to the actor page โ€” Navigate to LinkedIn Profile Scraper on Apify Store.
  2. โ–ถ๏ธ Click "Start" โ€” Open the input configuration panel.
  3. ๐Ÿ”— Add profile URLs โ€” Paste LinkedIn profile URLs or slugs into the profileUrls field. One URL per line, for example: https://www.linkedin.com/in/williamhgates/.
  4. ๐Ÿ”ข Set max profiles โ€” Optionally adjust maxProfiles to limit how many profiles to scrape (default: 100).
  5. ๐Ÿš€ Run the scraper โ€” Click "Start" and wait for results. Each profile takes a few seconds.
  6. ๐Ÿ“ฅ Download results โ€” Export your data as JSON, CSV, Excel, or connect it to your workflow via API or webhooks.

Input parameters

Only LinkedIn /in/ profile URLs and profile slugs/handles are targets. Absolute company, showcase, posts, and non-LinkedIn URLs are ignored before the profile limit; they are not converted into profile slugs.

Runs honor the caller's actual platform deadline. When there is not enough time for another bounded request attempt, completed results are retained and remaining profiles are not fetched. The default key-value store contains RUN_DIAGNOSTIC with code: "deadline_reached" and useful, error, and unprocessed counts. A partly attempted profile can return an honest uncharged error row; unprocessed profiles are not result rows. Increase the run timeout or split large batches to finish remaining work.

Null, blank, nonstring, and empty @ handle entries from API integrations are ignored before applying maxProfiles, so they cannot discard valid profiles in the same batch. If no usable targets remain (including an omitted or empty list), the Actor finishes with zero dataset rows and no charges. The default key-value store contains INPUT_DIAGNOSTIC with code: "invalid_input" and a corrective message. This is a caller-configuration outcome, not a scraped result; API and schedule callers should fix their upstream profile mappings. Real extraction/access errors retain the existing explicit error-row behavior.

ParameterTypeRequiredDefaultDescription
profileUrlsArrayYesโ€”List of LinkedIn profile URLs or slugs to scrape. Accepts full URLs like https://www.linkedin.com/in/williamhgates/ or just the slug williamhgates.
maxProfilesIntegerNo100Maximum number of profiles to process from the input list.

Example input:

{
"profileUrls": [
"https://www.linkedin.com/in/williamhgates/",
"https://www.linkedin.com/in/satyanadella",
"jeffweiner08"
],
"maxProfiles": 50
}

Output example

Each scraped profile produces a JSON object with the following structure:

{
"success": true,
"error": null,
"name": "Bill Gates",
"linkedinUrl": "https://www.linkedin.com/in/williamhgates/",
"headline": "Chair, Gates Foundation and Founder, Breakthrough Energy",
"location": "Seattle, Washington, United States",
"about": "Chair of the Gates Foundation. Founder of Breakthrough Energy. Co-founder of Microsoft.",
"followerCount": 40063481,
"connectionCount": "8",
"profileImageUrl": "https://media.licdn.com/dms/image/...",
"backgroundImageUrl": "https://media.licdn.com/dms/image/...",
"currentPositions": [
{ "title": "Co-chair", "company": "Gates Foundation", "startDate": "2000" },
{ "title": "Founder", "company": "Breakthrough Energy", "startDate": "2015" }
],
"experience": [
{
"title": "Co-chair",
"company": "Gates Foundation",
"companyUrl": "https://www.linkedin.com/company/gates-foundation",
"location": null,
"startDate": "2000",
"endDate": null,
"duration": "26 years",
"isCurrent": true,
"description": null
}
],
"education": [
{
"institution": "Harvard University",
"degree": null,
"startYear": 1973,
"endYear": 1975,
"schoolUrl": "https://www.linkedin.com/school/harvard-university/",
"description": null
}
],
"skills": [],
"languages": [],
"languageProficiencies": [],
"certifications": [],
"volunteering": [],
"projects": [],
"publications": [],
"honorsAndAwards": [],
"websites": [],
"scrapedAt": "2026-03-21T23:03:09.634Z"
}

Results are stored in the default dataset and can be exported in JSON, CSV, XML, Excel, or accessed via the Apify API.

Tips and best practices

๐Ÿ’ก Use full URLs when possible โ€” While the scraper accepts bare slugs, full URLs reduce ambiguity and ensure correct profile resolution.

๐Ÿ’ก Batch your requests โ€” Running one actor call with 500 profiles is cheaper than 500 individual runs, because you pay the plan-specific start fee only once.

๐Ÿ’ก Expect failures on less visible profiles โ€” LinkedIn answers some requests with a 999 status code (its anti-bot block). The scraper retries each profile up to 4 times on fresh proxy sessions. Well-known and fully public profiles usually succeed. Many ordinary profiles that LinkedIn does not show to logged-out visitors still fail, and the failure rate can be high on such lists. Failed profiles come back as success: false rows and are not charged, and the run's status message says how many profiles were delivered.

๐Ÿ’ก Deduplicate your input โ€” Remove duplicate URLs before running to avoid paying for the same profile twice.

๐Ÿ’ก Schedule regular runs โ€” Use Apify's built-in scheduler to keep your LinkedIn data fresh. Weekly or monthly scrapes work well for most use cases.

๐Ÿ’ก Filter and retry failures โ€” Filter dataset rows with success: false, inspect their error value, and re-run only those URLs. These rows do not incur a profile-scraped event.

Integrations

LinkedIn Profile Scraper connects with your existing tools through Apify's integration ecosystem:

๐Ÿ“Š Google Sheets โ€” Automatically push scraped profiles to a Google Sheet. Great for recruiters maintaining candidate trackers.

๐Ÿ—„๏ธ Webhooks โ€” Trigger your backend API whenever a run completes. Process new profile data in real time.

๐Ÿ’พ Amazon S3 / Google Cloud Storage โ€” Export datasets directly to cloud storage for data lake ingestion.

๐Ÿ“ง Zapier / Make โ€” Connect to 5,000+ apps. For example, scrape a profile and automatically create a HubSpot contact.

๐Ÿ”„ Slack notifications โ€” Get notified in Slack when a scraping batch completes with result counts.

๐Ÿ—ƒ๏ธ Apify Dataset API โ€” Programmatically fetch results in JSON, CSV, or Excel format from any language or platform.

API usage

Call LinkedIn Profile Scraper programmatically using the Apify API. Here are examples in popular languages.

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('automation-lab/linkedin-profile-scraper').call({
profileUrls: [
'https://www.linkedin.com/in/williamhgates/',
'https://www.linkedin.com/in/satyanadella',
],
maxProfiles: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((profile) => {
console.log(`${profile.name} โ€” ${profile.headline}`);
});

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("automation-lab/linkedin-profile-scraper").call(run_input={
"profileUrls": [
"https://www.linkedin.com/in/williamhgates/",
"https://www.linkedin.com/in/satyanadella",
],
"maxProfiles": 100,
})
dataset = client.dataset(run["defaultDatasetId"]).list_items().items
for profile in dataset:
print(f"{profile['name']} โ€” {profile['headline']}")

cURL

# Start the actor run
curl -X POST "https://api.apify.com/v2/acts/automation-lab~linkedin-profile-scraper/runs?token=YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"profileUrls": ["https://www.linkedin.com/in/williamhgates/"],
"maxProfiles": 10
}'
# Fetch results (replace RUN_ID with the actual run ID from the response)
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"

Use with Claude AI (MCP)

This actor is available as a tool in Claude AI through the Model Context Protocol (MCP). Add it to Claude Desktop, Cursor, Windsurf, or any MCP-compatible client.

Setup for Claude Code

$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/linkedin-profile-scraper"

Setup for Claude Desktop, Cursor, or VS Code

Add this to your MCP config file:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/linkedin-profile-scraper"
}
}
}

Example prompts

  • "Scrape the LinkedIn profile for Bill Gates and give me a summary of his current roles and background."
  • "Get LinkedIn data for these 10 profile URLs and create a comparison table of their headlines and locations."
  • "Pull LinkedIn profiles for the leadership team at OpenAI and tell me about their education backgrounds."

Learn more in the Apify MCP documentation.

Data handling, AI, and support

This Actor does not use AI models or send inputs/results to an AI provider. It requests only the public LinkedIn profile URLs supplied by the user and stores results in the run's Apify dataset; it has no external result database or Actor-side cache. Dataset and log retention follow the user's Apify account storage settings, and users can delete runs and datasets with Apify's storage controls. Do not submit credentials, private profile data, or sensitive personal data as input.

LinkedIn is a third-party source and may change or block its public pages. This Actor is independently operated and is not affiliated with, endorsed by, or sponsored by LinkedIn. For Actor support, use the issue/support channel on the Actor's Apify Store page and include the run ID plus a sanitized example URL.

Legality

Failed operations send sanitized diagnostic input, exceptions, and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL query strings are removed; reports are retained for 30 days.

Scraping publicly available data is generally considered legal based on the 2022 US Ninth Circuit ruling in hiQ Labs v. LinkedIn, which confirmed that scraping public profiles does not violate the Computer Fraud and Abuse Act (CFAA).

This actor only accesses publicly visible LinkedIn profile pages โ€” the same data any visitor can see without logging in. It does not bypass any authentication, use stolen credentials, or access private data.

However, scraping may still violate LinkedIn's Terms of Service. Users are responsible for ensuring their use of scraped data complies with applicable laws including GDPR, CCPA, and other data protection regulations.

For more details, see Apify's guide on the legality of web scraping.

FAQ โ€” Frequently asked questions

Q: Do I need a LinkedIn account to use this scraper?

No. LinkedIn Profile Scraper works entirely without login credentials. It accesses public profile pages through residential proxies, so no LinkedIn account is needed.

Q: Why did some profiles return no data?

LinkedIn's anti-bot system sometimes returns a 999 status code, a login page, or a challenge page. The scraper makes up to 4 attempts with different proxy sessions. If it still cannot validate a usable profile identity, it returns success: false with an error reason and does not charge the profile event. Try re-running only those failed URLs.

Q: Can I scrape private profiles or profiles behind a login wall?

No. This scraper only extracts data from publicly visible profiles. If a profile requires signing in to view, it cannot be scraped by this actor.

Q: How fast is the scraping?

A profile that loads on the first attempt takes about 3-10 seconds. A blocked profile can take up to about a minute, because of retries. Profiles are processed one at a time to avoid triggering LinkedIn's rate limits.

Q: What format can I export the data in?

Results can be exported as JSON, CSV, XML, Excel (XLSX), or accessed directly through the Apify API. You can also push data to Google Sheets, webhooks, or cloud storage.

Q: Why does connectionCount show as a string?

LinkedIn displays connection counts differently depending on the profile. Some show exact numbers, others show "500+". The field is kept as a string to preserve this original formatting.

If you find LinkedIn Profile Scraper useful, check out these related actors from automation-lab:

๐Ÿข LinkedIn Company Scraper โ€” Scrape company pages for description, employee count, industry, and specialties.

๐Ÿ’ผ LinkedIn Jobs Scraper โ€” Search and extract LinkedIn job listings with title, company, location, and description.

๐Ÿฆ Twitter Scraper โ€” Scrape tweets, user profiles, and search results from Twitter/X.

๐Ÿ’™ Bluesky Scraper โ€” Extract posts and profiles from Bluesky social network.

๐ŸŽต TikTok Scraper โ€” Scrape TikTok videos, user profiles, and hashtag content.

Server API: get one LinkedIn profile over HTTP

LinkedIn Profile Scraper is also a Server Actor. Besides normal runs, it answers short HTTP requests directly, without starting a run for each lookup. Copy the server URL from the Actor's Server tab (do not build it from the Actor name) and authenticate with your Apify token. Use normal Actor runs for lists of profiles.

curl -sS "$SERVER_URL/profile?url=https://www.linkedin.com/in/williamhgates/" -H "Authorization: Bearer $APIFY_TOKEN"
curl -sS "$SERVER_URL/profile?url=satyanadella" -H "Authorization: Bearer $APIFY_TOKEN"
Method and pathInputOutput and charge
GET /Noneready: true, the routes and limits; no scraping or charge
GET /profileQuery url: a LinkedIn profile URL (linkedin.com/in/<handle>; regional hosts such as de.linkedin.com work) or a handle such as williamhgates{ok,count,results} with one profile record, the same as a normal run's dataset item for a found profile; one Profile scraped event (profile-scraped); no start fee

Only a page whose profile identity is proven is returned. A missing profile, a blocked or unreadable page (login or challenge pages; private profiles never show) return an error and are free. Each request has a 60-second deadline and a 256 KiB response cap, and one server works on at most eight requests at once. Nothing is cached. Errors use { "ok": false, "error": { "code": "...", "message": "...", "retryable": false } }: 400 INVALID_URL or INVALID_INPUT; 402 spending limit; 404 PROFILE_NOT_FOUND or unknown route; 405 wrong method; 413 RESPONSE_TOO_LARGE; 502 BLOCKED, PROFILE_UNREADABLE, LINKEDIN_UNAVAILABLE, UPSTREAM_ERROR or charging failure; 503 server busy or stopping; 504 TIMEOUT. Failed requests are free. Retry only when retryable is true. The Server tab shows the full OpenAPI description.

⌂ ๆข็ฝ‘ๅ€