LinkedIn Profile Scraper - Bulk Public Data, No Login avatar

LinkedIn Profile Scraper - Bulk Public Data, No Login

Pricing

$4.00 / 1,000 linkedin profiles

Go to Apify Store
LinkedIn Profile Scraper - Bulk Public Data, No Login

LinkedIn Profile Scraper - Bulk Public Data, No Login

Scrape public LinkedIn profiles in bulk - name, headline, location, experience, education, skills, connections & followers. No login or cookies. Bulk linkedin.com/in/ URLs to clean JSON. Works in Claude, ChatGPT & any MCP agent for B2B lead enrichment.

Pricing

$4.00 / 1,000 linkedin profiles

Rating

0.0

(0)

Developer

The Mine Works

The Mine Works

Maintained by Community

Actor stats

0

Bookmarked

9

Total users

7

Monthly active users

7 hours ago

Last modified

Share

LinkedIn Profile Scraper — Name, Headline, Experience & Skills (No Login)

Scrape public LinkedIn profiles in bulk. Give the actor a list of linkedin.com/in/ URLs and get back structured data for each profile: name, headline, location, about section, full work experience, education history, skills, connection count, and follower count.

No login. No cookies. No LinkedIn account required.


What It Does

LinkedIn makes public profiles visible to anyone on the web — no account needed. This actor uses a real Chromium browser (Playwright) routed through Apify's residential proxy network to load each profile page just like a real visitor would, then extracts every visible field into a clean JSON record.

LinkedIn's public pages are served as fully-rendered server-side HTML, so all the content is present without JavaScript execution tricks. The actor scrolls each page to trigger lazy-loaded sections (experience, education, skills) before extracting.


Example Output

{
"profile_url": "https://www.linkedin.com/in/satyanadella",
"name": "Satya Nadella",
"headline": "Chairman and CEO at Microsoft",
"location": "Redmond, Washington, United States",
"about": "Hit Refresh is about the quest to find one's soul...",
"experience": [
{
"title": "Chairman and Chief Executive Officer",
"company": "Microsoft",
"duration": "Feb 2014 - Present",
"description": null
}
],
"education": [
{
"school": "University of Chicago Booth School of Business",
"degree": "Master of Business Administration",
"field": "MBA",
"dates": "1994 - 1997"
}
],
"skills": ["Cloud Computing", "SaaS", "Enterprise Software", "Leadership"],
"connections": "500+ connections",
"followers": "12,000,000 followers",
"scraped_at": "2026-06-23T10:00:00.000Z"
}

Input Fields

FieldTypeDescription
profileUrlsarray of stringsLinkedIn profile URLs to scrape. Use the format https://www.linkedin.com/in/username. Supports up to 500 URLs per run.
maxResultsintegerMaximum number of profiles to return (default: 10, max: 500). Use a small number like 1–3 for quick tests.
proxyproxy configResidential proxy configuration. Leave as default — datacenter IPs are blocked by LinkedIn.

Why a Real Browser Is Required

LinkedIn detects headless and bare HTTP clients via browser fingerprinting and immediately redirects them to /authwall (the login page). A real Chromium browser with residential proxies is the only reliable way to consistently access public profile pages without an account.

The actor uses crawlee's PlaywrightCrawler with fingerprinting enabled (Chrome on Windows/macOS) and the --disable-blink-features=AutomationControlled flag to prevent navigator.webdriver detection. Each profile uses a fresh proxy session to avoid IP-level rate-limiting.


Pricing

First 25 profiles per Apify account are free — forever. After the free allowance is used up, the actor charges $0.005 per successfully scraped profile via Apify's Pay-Per-Event model.

  • Blocked profiles (authwall hits) are never charged
  • Not-found / private profiles are never charged
  • Only profiles with a name successfully extracted are charged

The free allowance is tracked per Apify account across all of your runs, not per individual run. So you can run the actor multiple times and you'll only use your 25 free profiles once.


How Profiles Are Extracted

The actor uses multiple CSS selector fallbacks for every field so that changes to LinkedIn's class names degrade gracefully (missing one field) rather than crashing the entire run. The extraction hierarchy for each field:

  • Nameh1.text-heading-xlarge and fallback h1 selectors
  • Headline.text-body-medium.break-words and professional headline variants
  • Location.text-body-small.inline.t-black--light.break-words and data-field attributes
  • About#about anchor then sibling content, including the .visually-hidden expanded-text span
  • Experience#experience anchor then ul > li items in the section
  • Education#education anchor then ul > li items in the section
  • Skills#skills anchor then t-bold span text items
  • Connections / Followers — text-based regex scan of the visible page body + stat element fallbacks

Handling Blocked and Private Profiles

The actor handles all failure cases gracefully — it never crashes the run and never charges for failed profiles:

  • Authwall (status: "blocked") — LinkedIn redirected to the login page. Usually means the exit IP was flagged. Retried up to 2 times with fresh proxy sessions automatically.
  • Not found (status: "not_found") — Profile URL returned a 404 or "Page Not Found" title. The profile was deleted or the URL is wrong.
  • No name (status: "no_name") — Page loaded but no name was found. Can indicate a private profile or a partially-loaded page.
  • Summary item — The last item in every dataset is { "_type": "summary", "scraped": N, "blocked": N, ... } giving run statistics.

Rate Limiting and Proxy

LinkedIn rate-limits by IP. The actor uses one profile per browser context with a randomized 3–6 second delay between requests and a fresh residential proxy session for each profile. This is the same cadence a human user would achieve. Running at maxConcurrency: 1 (sequential) is intentional — parallel browser sessions on the same account get flagged faster.

The RESIDENTIAL proxy group on Apify routes through real home/mobile IP addresses from the residential pool, which LinkedIn cannot distinguish from organic traffic.


FAQ

Can I scrape profiles without a LinkedIn account? Yes. Public LinkedIn profiles are accessible to anyone. This actor does not require you to supply your LinkedIn credentials or session cookies.

Why do some profiles return "blocked"? A small percentage of residential IPs are pre-flagged by LinkedIn's bot detection. The actor automatically retries with up to 2 different IP sessions. If all retries fail, the profile is recorded as blocked and not charged. Success rates on residential proxy are typically 80–95%.

What's the maximum throughput? With the default 1 concurrent browser and 3–6s per profile, expect roughly 10–15 profiles per minute. For 500 profiles, allow around 40–50 minutes.

Does this work for private profiles? No. Private profiles require authentication and cannot be scraped without login. The actor will return a not_found or no_name status for private profiles.

Can I integrate this with other actors? Yes. Pair it with the linkedin-employees actor: use linkedin-employees to find employee profile URLs for a company, then pass those URLs to this actor to get detailed data for each person.


Built by The Mine Works

Production-grade web scrapers and data APIs. Pay only for results delivered. themineworks.com

Use in Claude, ChatGPT & any MCP agent

This actor is also a Model Context Protocol (MCP) server tool — call it directly from Claude, ChatGPT, Cursor, Windsurf, or any MCP-compatible AI agent. The agent only pays for results delivered (same pay-per-result model).

  • Per-actor MCP endpoint: https://mcp.apify.com/?tools=themineworks/linkedin-profile-scraper
  • Full Mine Works MCP server (all tools): https://the-mine-works-mcp.hatchable.site/api/mcp
// Call this actor as a tool via apify-client (Node)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('themineworks/linkedin-profile-scraper').call({ /* input from the table above */ });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);