LinkedIn Profile Search Scraper - $0.50/1k, No Login
Pricing
from $0.50 / 1,000 profile founds
LinkedIn Profile Search Scraper - $0.50/1k, No Login
Search public LinkedIn profiles by keywords, location, job title, company or school and get name, headline, location, current role and profile URL. No login, no cookies, no LinkedIn account needed. The cheapest LinkedIn people search on the market at $0.50 per 1,000 profiles.
Pricing
from $0.50 / 1,000 profile founds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
LinkedIn Profile Search Scraper — public people search, no login
Type a job title, a skill or a name, add a city or a company if you want to narrow it down, and get back a list of public LinkedIn profiles: full name, headline, location, current role, current company, education, connection count and the profile URL.
No LinkedIn account. No cookies. No session token to paste in. Nothing to install. You run it, you get rows.
Price: $0.50 per 1,000 profiles, plus a $0.001 run start fee. That is the lowest price for a LinkedIn people search on the Apify Store. Sample rows and error rows are never billed.
What it actually does
LinkedIn's own people search sits behind the login wall — you cannot open
linkedin.com/search/results/people/ logged out and you cannot script it without an account.
What is public is the profile pages themselves. LinkedIn publishes every /in/<name> page to the
open web so search engines can index it, complete with the member's name and headline in the page
title and a description that spells out their experience, education and location. That published
version is what this Actor searches. It builds a query from your keywords and filters, runs it
against the public web index, and turns the matching profile pages into structured rows.
That has two consequences worth knowing up front:
- It is genuinely account-free. There is no login step that can break, no cookie that expires, and no risk to a LinkedIn account of yours, because none is used.
- It sees what the public web sees. A profile that has opted out of public visibility, or one that has never been indexed, will not appear. See the limits section below.
Input
Everything is optional. Give it a searchQuery, or filters, or both.
| Field | Type | What it does |
|---|---|---|
searchQuery | string | Free-text people search: "software engineer", "head of growth fintech", "Sarah Chen". |
locations | string[] | Keep profiles whose public page mentions one of these places. Several values are searched as OR. |
currentJobTitles | string[] | Keep profiles mentioning one of these titles. |
currentCompanies | string[] | Company name or a full LinkedIn company URL — both work. |
schools | string[] | School or university name. |
maxItems | integer | How many profiles to return, 1–120. Default 20. |
A real input, exactly as you would paste it into the API:
{"searchQuery": "software engineer","locations": ["San Francisco"],"maxItems": 12}
A wider one, using several values on a filter to reach a bigger list:
{"searchQuery": "product manager","locations": ["London", "Berlin", "Amsterdam"],"maxItems": 60}
That second run finished in 10 seconds and returned 60 profiles.
If you start a run with completely empty input, you get one clearly labelled free sample row telling you what to fill in. The run still succeeds, and you are not charged for any profiles — that is deliberate, so a forgotten field never costs you a failed, billed run.
Output
One row per profile. Here is a genuine row from a real run, copied out of the dataset unedited:
{"ok": true,"_sample": false,"charged": true,"recordType": "profile","profileUrl": "https://www.linkedin.com/in/swong415","publicIdentifier": "swong415","fullName": "Sharon Wong","firstName": "Sharon","lastName": "Wong","headline": "Software Engineer","location": "San Francisco","currentPosition": "Software Engineer","currentCompany": "Dropbox","education": null,"connections": "475","snippet": "Software Engineer · Experience: Dropbox · Location: San Francisco · 475 connections on LinkedIn.","searchQuery": "site:linkedin.com/in software engineer \"San Francisco\"","foundVia": "secondary-index","scrapedAt": "2026-08-15T13:32:07.862Z"}
Field reference
| Field | Notes |
|---|---|
profileUrl | Canonical public profile URL. Country subdomains (uk.linkedin.com, ug.linkedin.com) are preserved because that is where the page actually lives. |
publicIdentifier | The slug after /in/. Handy as a primary key when you de-duplicate across runs. |
fullName, firstName, lastName | Name as published. lastName is null for single-word names. |
headline | The member's own headline line, when the indexed title carries one. |
location | From the published profile description first, the title second. |
currentPosition, currentCompany | Split out of the headline on at / @, or taken from the published "Experience:" line. A headline written as a keyword list (Engineer | FinTech | AI/ML) is not guessed at — you get null rather than "FinTech" invented as an employer. |
education | From the published "Education:" line when present. |
connections | As a string, because LinkedIn publishes "500+" as often as a number. |
snippet | The raw indexed description, so you can see what the match was based on. |
searchQuery | The exact query the row came from — useful when you widen a search and want to know which variant found whom. |
recordType | profile, sample or diagnostic. |
charged | true only on rows you actually paid for. |
Every field that could not be read is null. Nothing is inferred, padded or filled with a
placeholder.
Rows that are not profiles
- Sample row (
recordType: "sample",charged: false) — returned when you run with empty input. - Diagnostic row (
recordType: "diagnostic",charged: false) — returned when a search found nothing, or when the public indexes refused the run. It tells you which of the two happened and what to change:
{"ok": false,"charged": false,"recordType": "diagnostic","code": "NO_RESULTS","requestsMade": 3,"droppedOffTarget": 40,"details": "The indexes answered, but all 40 profile(s) they returned failed your own filters, so none were kept or charged. Loosen a filter."}
Neither of those is ever billed as a profile, and neither makes the run fail. A failed run still costs you the start fee, so this Actor exits successfully and explains itself instead.
Pricing
| Event | Price |
|---|---|
| Run start | $0.001 |
profile-found — one matching public profile saved | $0.0005 |
That is $0.50 per 1,000 profiles, and it is the cheapest LinkedIn people search on the market.
What that means in practice:
- 20 profiles in one run → $0.011
- 120 profiles in one run (the per-run maximum) → $0.061
- 1,000 profiles → $0.50 of profile charges, plus one $0.001 start fee per run. A run tops out at 120 profiles, so that is 9 runs and $0.509 in total.
You are charged once per profile row, right after it is written to the dataset. You are not charged for:
- the sample row on an empty run,
- diagnostic rows,
- listings that came back from the index but failed your own filters (they are dropped before anything is billed — a real run dropped 15 off-target listings and charged for none of them),
- duplicate profiles across queries inside a run — the de-duplication happens before the charge.
There is no monthly fee and no minimum.
How many profiles can I actually get?
Be realistic about this, because a lot of listings are not.
Up to 120 per run, and that is a hard cap in the input box on purpose. Measured on the cloud on 2026-08-17 on the build that is live right now, straight from the run logs:
| Search | maxItems | Profiles delivered | Time |
|---|---|---|---|
"marketing manager" + London | 120 | 120 / 120 distinct | 18 s |
"software engineer" + San Francisco | 20 | 20 / 20 distinct | 5 s |
This used to top out around 40 per search whatever you asked for. That cap is gone: it was never LinkedIn's limit, it was one slice of the public index. The search now also walks LinkedIn's international public-profile hostnames, which are indexed separately and hold genuinely different people, and it still widens across your own multi-value filters on top of that (three cities means three searches, run automatically).
The box stops at 120 rather than at some rounder, larger number because 120 is the figure that has actually been delivered in full. An attempt at 200 came back with 169 and spent more than twice the requests getting there, so 200 is not a number this listing is willing to print next to a price.
Three honest caveats before you set maxItems: 120:
- A narrow search returns what exists and then stops. If only 40 public profiles anywhere match your terms, you get 40 and the run ends early. You are charged for the profiles actually delivered — never for the number you asked for. Asking for 120 and getting 40 costs you 40.
- Going deep trades some relevance for volume. The first results come from the main index slice
and are the closest matches. The deeper ones come from LinkedIn's international profile pages,
where the index has verified your terms appear on the page but the person may not live in the
city you typed — a Toronto or Milan profile that mentions London will show up in a London search.
This has always been how the location filter works (it is a text match, not a geo radius), but at
maxItems: 120you will see much more of it than at 20. If precision matters more than volume, ask for fewer and add a job-title filter. - Large runs back to back will return less than a large run on its own. The public index rate-limits by network address, and a 120-profile search reads far more of it than a 20-profile one. Several maximum-size runs fired within a few minutes of each other will start seeing refusals, and a run that is refused everywhere writes a free diagnostic row and charges you nothing for results. If you need volume, space the big runs out; if you need it now, prefer several smaller runs over one after another at 120.
What this does not do
An honest list, because these are the things people ask after they buy:
- No email addresses or phone numbers. They are not on the public profile page, so they are not here. This is a people search, not a contact-enrichment tool.
- No full work history, skills, certifications or recommendations. You get the current role and headline as published, not the whole CV.
- No profile photos.
- No connection-degree, no "who viewed you", no InMail — all of that requires an account.
- Private and unindexed profiles are invisible. Members who turned off public profile visibility do not appear anywhere in the public web index, and there is no keyless way around that.
- Filters match the whole published page, not just the snippet you see. If you search for
"Product Manager" in "London", a returned profile does contain both — but the short description in
the
snippetfield may not repeat them. That is why the row is kept: the index verified the match against the full page. - Location is a text match, not a geo radius.
"San Francisco"will not automatically pull in Oakland, and"Greater London Metropolitan Area"matches far less than plain"London". Prefer the shorter, more common form of a place name. - Fields can be
null. Roughly a third of profiles publish a headline with no company in it, socurrentCompanyis often empty. Nothing is invented to fill the gap. - Result ordering is relevance from the public index, not recency, and not a ranking you can control. Within a run the closest matches come first and the widened, less precise ones come last — so if you only want the best matches, ask for fewer.
- Nobody can guarantee a fixed number of profiles, and this listing does not. A run returns what the public index holds for your terms on the day. What is guaranteed is the billing: one charge per profile row actually delivered to your dataset, and nothing at all for a run that finds none.
Reliability
The public indexes rate-limit hard per address, so every request goes out through a different rotating datacenter address with a real browser TLS fingerprint. Two independent indexes are read in parallel and merged, so one of them being slow or unhappy does not empty your run.
If everything is refused at once — it happens, usually for a few minutes — you get a diagnostic row saying so, the run succeeds, and no profiles are billed. Run it again shortly after.
Every request is capped at 8 seconds and the whole search at 90, so a stalled network turns into a short run and an honest diagnostic, never a long expensive one.
FAQ
Do I need a LinkedIn account or cookies? No. Nothing is logged in, nothing is stored, and no cookie or session token is ever asked for. The Actor reads the versions of LinkedIn profile pages that are published to the open web.
Is this legal? It reads only publicly published pages, the same ones a search engine indexes and anyone can open in a browser without logging in. No login wall is bypassed and no private data is touched. You are responsible for how you use the results — if you are in the EU or UK and processing personal data, GDPR applies to you regardless of where the data came from.
How do I search for a specific person by name?
Put the name in searchQuery, for example
{"searchQuery": "Sarah Chen", "currentCompanies": ["Stripe"]}Can I filter by company using a LinkedIn company URL?
Yes. "currentCompanies": ["https://www.linkedin.com/company/airbnb/"] works exactly like
"currentCompanies": ["Airbnb"].
Why did I get fewer profiles than maxItems?
Because that many public profiles matched. maxItems is a ceiling, not a target, and you are only
charged for what you actually receive. Widen the search by adding more values to a filter.
Why is currentCompany sometimes null?
Because the member's published headline does not name an employer. It is left empty rather than
guessed at from a keyword list.
Do I pay for a run that finds nothing? Only the $0.001 start fee. Zero profiles means zero profile charges, and the run still ends successfully with a row explaining why.
Does it work outside the US?
Yes. Country subdomains come back as they are — uk.linkedin.com, ug.linkedin.com,
in.linkedin.com — and non-English profiles are parsed the same way.
How fresh is the data?
It reflects the public index, which lags a profile edit by days to weeks. scrapedAt records when
the row was collected. For a live read of one specific person, this is the wrong tool; for building
a list, it is the cheap one.
Can I run it on a schedule?
Yes, like any Actor — schedule it, use publicIdentifier as the key, and diff against your last
run.
How do I call it from code? It is a standard Apify Actor, so the Apify API, the JavaScript and Python clients, the MCP server and the integrations all work with it. Start a run with the JSON input above and read the default dataset.