LinkedIn Profiles Scraper
Get public LinkedIn profile data from URLs you supply. You get name, headline, description, image link and public identifier. $0.90 per 1,000 profiles.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
profileUrls,maxProfiles,requestTimeoutSecs(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.0009 per successful public profile = $0.9 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Successful public profile | A matching public LinkedIn profile parsed from the supplied URL. | $0.0009 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-04, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
profileUrls | Public URLs in the form https://www.linkedin.com/in/public-identifier/. Empty input returns one clearly labeled, uncharged sample row. | array |
maxProfiles | Maximum valid public profile URLs to request. Invalid or blocked URLs return free diagnostic rows. | integer |
requestTimeoutSecs | Timeout for one public profile page request. | integer |
What you get
A structured dataset — each result includes fields like:
fullNameheadlineprofileUrlprofileImageUrltransportExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in B2B Leads & Contact Data
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
LinkedIn Companies Scraper
Get public LinkedIn company data from company URLs. You get name, description, followers, employee count, HQ, website and logo. $0.90 per 1,000, flat rate.
YouTube Channel Email Scraper
Find the business emails creators publish in their YouTube channel description, plus their linked site's contact pages. $1.50 per 1,000 channels.
Domain Inspector
Check many domains at once. Get DNS, WHOIS registrar and expiry, TLS dates, redirects, security headers, robots and tech. $1.50 per 1,000.
Google Maps Scraper
Scrape Google Maps places and reviews. Business name, category, address, rating, GPS coordinates and place ID. $0.27 per 1,000 rows.
Contact Details Scraper
Get emails, phones and addresses from any list of websites. Also contact forms and 10 social profiles. $1.50 per 1,000 sites, flat rate.
Email Verifier
Verify emails in bulk: syntax, MX records, disposable domains, role accounts, optional SMTP check. No mail is sent. No API key, no login.
Where this tool sits
- Categories
- B2B Leads & Contact Data
- Platforms
LinkedIn Profiles Scraper: public profile data from URLs you already have
Paste a list of linkedin.com/in/... URLs and get back what LinkedIn publishes on each of those pages: full name, headline, the long "about" text, a link to the photo and whatever outbound links the person lists. No account, no cookie, nothing to paste in and nothing that expires on you.
What it reads is the public version of the page, the one LinkedIn writes for search engines to index. A profile that is private or has opted out of public visibility comes back empty, and there is no keyless way around that.
| Input | Public /in/ profile URLs |
| Output | One row per URL |
| Ceiling | 100 profiles per run |
| Account needed | None |
| Price | $0.90 per 1,000 profiles, flat on every plan |
👤 What LinkedIn Profiles Scraper does
You already have the URLs. This fills in the person behind each one.
A public profile page carries a block of structured data that LinkedIn puts there for search engines: the name, the headline, the "about" text, the photo and the links the person chose to list. That block is what this reads, one page per URL, in the order you gave them.
Two checks happen before a row is written. The page's own canonical URL has to match the URL you asked for, and the structured data has to describe that same profile. Vanity URLs redirect more often than you would think, and without those checks you would get somebody else's details filed under your URL. When the match fails you get a row saying so instead of a confident wrong answer.
📥 What you give it
{
"profileUrls": [
"https://www.linkedin.com/in/reidhoffman/",
"https://www.linkedin.com/in/williamhgates/"
],
"maxProfiles": 10
}
| Field | Default | What it is |
|---|---|---|
profileUrls | empty | Up to 100 public /in/ URLs. Tracking parameters and country subdomains are cleaned off, and the same profile is fetched only once however many times you list it. Leave it empty and you get one labelled sample row, free. |
maxProfiles | 10 | 1 to 100. The number of URLs the run will actually fetch. |
requestTimeoutSecs | 20 | 5 to 60 seconds. How long to wait for one page before giving up on it. |
The cap bites quietly, so set it. maxProfiles starts at 10. Paste 40 URLs and leave it there and you get 10 rows and nothing at all for the other 30, not even a row explaining why. Set it to the number of profiles you want.
Long lists need a longer run. Pages are fetched one after another, and the run ends when it reaches the timeout on the actor's Settings tab, 180 seconds unless you change it. A hundred URLs with a 60-second page timeout can outlast that. Raise the run timeout or split the list.
📤 What you get back
A real row from a recent run. The headline, the about text and the image link are long, so they are cut short here with ...:
{
"ok": true,
"_sample": false,
"sourceType": "public_linkedin_profile",
"profileUrl": "https://www.linkedin.com/in/reidhoffman",
"publicIdentifier": "reidhoffman",
"fullName": "Reid Hoffman",
"headline": "Co-Founder, Executive Board Chair | Co-Founder, Board Member | Partner | Chair | ...",
"description": "My current priority is investing in and building with AI to benefit humanity. Recently, I've co-founded Inflection.AI and ManasAI.co. <br><br>I am active in all facets of the consumer internet ...",
"profileImageUrl": "https://media.licdn.com/dms/image/v2/D5603AQHW7wKzPb3DAg/profile-displayphoto-shrink_200_200/...",
"sameAs": [],
"transport": "direct_http",
"retrievedAt": "2026-09-14T05:45:41.433Z"
}
| Field | What it is |
|---|---|
publicIdentifier | The slug after /in/. The stable key to join on across runs. |
fullName | The name as the page publishes it. |
headline | The line under the name. Long ones read as a pipe-separated list because that is how the page itself publishes them. |
description | The "about" text, exactly as published, <br> tags included. Strip them yourself if you want clean text. |
profileImageUrl | A direct link to the hosted photo, or null when the profile has none. |
sameAs | The outbound links the profile lists. An empty list on most profiles, because most people list none. |
Nothing is guessed or padded. A field the page does not publish comes back null or empty rather than filled in from somewhere else.
🧾 Reading the output
Three kinds of row, and only real profiles cost anything.
| Row | How to spot it | Charged |
|---|---|---|
| A profile | sourceType: "public_linkedin_profile" | yes |
| The sample row | _sample: true, and it only appears when you run with empty input | no |
| A diagnostic | ok: false and _diagnostic: true | no |
There is no charged field on these rows. sourceType is what tells a real profile apart from a sample or a diagnostic, so filter on that and you have your people.
A diagnostic row carries an errorCode:
| Code | What it means |
|---|---|
BAD_INPUT | Not a /in/ URL, or a slug written with characters this actor will not accept. Nothing was requested for it. |
NO_RESULTS | The page loaded but carried no profile data matching the URL you asked for. Usually a vanity URL that now redirects to somebody else. |
BLOCKED | LinkedIn answered with a challenge page instead of the profile. A URL for a profile that no longer exists lands here too, because LinkedIn answers both the same way. |
RATE_LIMITED | Too many pages too close together. Space your runs out. |
SERVER_ERROR, NETWORK | LinkedIn errored, or the page did not arrive inside requestTimeoutSecs. Worth re-running that URL on its own. |
Neither a sample nor a diagnostic row fails the run.
▶️ How to run it
1. Open LinkedIn Profiles Scraper and click Try for free. 2. Paste your URLs into Public LinkedIn profile URLs, one per line. 3. Set Maximum profiles to at least the number of URLs you pasted. 4. Click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$0.90 per 1,000 profiles. Flat on every Apify plan, no volume tiers.
One charge per profile row. Sample rows and diagnostic rows are never charged, a URL you listed twice is fetched and billed once, and a run where nothing comes back costs you nothing for results.
💡 What people use it for
- Putting names, headlines and photos against a column of profile URLs exported from a CRM.
- Checking an old list is still good before a campaign. Dead and redirected URLs show up as
diagnostic rows instead of quietly going missing.
- Reading how a set of people describe their own work, in their own words, before writing to them.
- Collecting photo links and headlines for a speaker page or an internal directory.
🚧 What it does not do
- No email addresses and no phone numbers. They are not on the public page, so they are not
here.
- No work history, education, location, skills or connection count. The published block does
not carry them. Name, headline, about text, photo and listed links is the whole of it.
- No search. It cannot turn a name or a company into a URL. You bring the URLs.
- Private and unindexed profiles are invisible, however the URL is written.
- Slugs with accents, underscores or percent-encoded characters are refused as
BAD_INPUT,
even when the profile is perfectly real.
- A profile that does not exist reads as
BLOCKED, not as "not found". LinkedIn gives the same
answer for a deleted profile and a refused request, so the two cannot be told apart from outside.
- URLs past
maxProfilesget no row at all. They are dropped, silently. - No retries. A URL that fails, fails for that run. Re-run it.
🧭 Which LinkedIn scraper do you need?
| If you want | Use |
|---|---|
| Profiles when you already have the URLs | This one |
| To find the profiles in the first place, by title, company or school | LinkedIn Profile Search Scraper |
| Everyone who works at one company | LinkedIn Company Employees Scraper |
| What a person has been posting | LinkedIn Profile Posts Scraper |
| Company pages | LinkedIn Companies Scraper |
❓ Questions people ask
Do I need a LinkedIn account? No, and there is no cookie field either. Nothing to paste and nothing to renew.
Will my own account get restricted? Yours is never used, so there is nothing to restrict.
Can I give it a name or a company instead of a URL? Not here. Use the search actor above to find profiles, then feed the URLs it returns into this one.
Why did some of my URLs come back with no data? Read the errorCode on the row. Most of the time it is a vanity URL that has been changed since your list was made.
What happens if I run it with nothing in the input? You get one sample row, clearly labelled, and you are not charged for it.
Is scraping LinkedIn legal? This reads only pages LinkedIn publishes to the open web for search engines. Rows still contain personal data, which GDPR and similar laws cover, so have a lawful reason for collecting it. Apify's write-up on scraping and the law is a reasonable starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID and one of the URLs that went wrong. The errorCode on the diagnostic row usually says what happened on its own.