DEV Community

Cover image for How to Scrape LinkedIn Profiles Without Logging In (Python, 2026 Guide)
Azzam
Azzam

Posted on

How to Scrape LinkedIn Profiles Without Logging In (Python, 2026 Guide)

How to Scrape LinkedIn Profiles Without Logging In (Python, 2026 Guide)

Building a lead list or a candidate shortlist on LinkedIn by hand works for 20 people and falls apart at 500. This guide shows how to scrape LinkedIn profiles from Python by job title, company, location, school or name, without a LinkedIn account or Sales Navigator. You get one row per person with the name, headline, company, location and profile link.

Here's the whole LinkedIn scraper in Python. Install the client with pip install apify-client, paste your Apify token, and run:

from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("automly/linkedin-people-search-scraper").call(run_input={
    "jobTitles": ["Product Manager"],
    "companies": ["Stripe"],
    "locations": ["San Francisco"],
    "maxResults": 50,
})

for person in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(person["name"], "|", person["headline"], "|", person["linkedinUrl"])
Enter fullscreen mode Exit fullscreen mode

Below I go through the inputs, the output, the limits and the price.

Why not the official API?

LinkedIn does have APIs, but none that an ordinary developer can sign up for lets you search for people. I checked the official docs in October 2026:

Option Access needed Cost What you get
Sign In with LinkedIn (OpenID Connect) Self-serve app, and each person must sign in to it No fee at present (API Terms, 8.2) The signed-in member's own name, photo and email
Profile API Developers approved by LinkedIn No fee at present (same API Terms) Another member's profile only if you already have their Person ID, which comes from other limited-access APIs, and you may never store it
Sales Navigator Application Platform (SNAP) Approved SNAP partner Not published Sales Navigator data, such as matched public profile info, inside a partner's app
This scraper An Apify account $1.50 per 1,000 profiles People search by title, company, place, school or name

According to LinkedIn's Getting Access page, the only permissions open to every developer are sign-in (profile, email) and posting on the member's behalf. Everything else goes through a partner program that LinkedIn has to approve. And nothing in that permissions list lets you find other members by job title or company.

Step 1: Get your Apify token

Create a free Apify account, then copy your API token from your Apify Console settings. Every account gets $5 of free usage each month, which is plenty for testing.

Step 2: Choose your filters

The actor reads these input fields:

Field What it does
jobTitles List of titles, e.g. ["Product Manager", "Head of Sales"]
companies Company names or LinkedIn company links
locations Cities, regions or countries
schools Universities or schools
searchQuery Any other words the profile should mention, e.g. "fintech"
firstName, lastName Find a person by name
maxResults Stop after this many profiles in the whole run (default 100)
maxResultsPerSearch Cap each search, e.g. 50 per city
fullProfiles Also read each profile page for more fields (default off)

Every combination of one title, one company, one location and one school counts as one search. Two titles and three cities give you six searches, and a person found by more than one of them is saved once.

To find one person by name:

run_input = {"firstName": "Jane", "lastName": "Doe", "companies": ["Stripe"]}
Enter fullscreen mode Exit fullscreen mode

The locations filter is strict. People whose profile shows another place, or no place at all, are left out. Add the country ("Berlin, Germany") to also keep people who list only their country.

Step 3: Read the results

Each row from the search looks like this (name and link anonymized):

{
  "linkedinUrl": "https://www.linkedin.com/in/jane-doe-123",
  "publicIdentifier": "jane-doe-123",
  "name": "Jane D.",
  "headline": "Product Manager @ Stripe",
  "company": "Stripe",
  "school": "University of Michigan",
  "location": "San Francisco Bay Area",
  "connections": "500+",
  "query": "\"Product Manager\" \"Stripe\" \"San Francisco\""
}
Enter fullscreen mode Exit fullscreen mode

query tells you which search found the person, which helps when one run covers many cities or titles.

Step 4: Add profile details

Set "fullProfiles": True and each row gets extra fields: about, countryCode, photo, followers, badges, currentCompany, currentPositions, pastCompanies, education, recentPostUrls and profileVisibility. A typical row looks like this (trimmed, anonymized):

{
  "name": "John Smith",
  "headline": "Data Scientist at Shopify",
  "location": "Toronto, Ontario, Canada",
  "countryCode": "CA",
  "followers": 410,
  "connections": "500+",
  "currentCompany": "Shopify",
  "education": [{"name": "University of Waterloo", "startDate": "2012", "endDate": "2016"}],
  "experience": [],
  "profileVisibility": "limited"
}
Enter fullscreen mode Exit fullscreen mode

See the empty experience? That's normal for most people, which brings me to the limits.

Step 5: Know what a logged-out profile hides

LinkedIn decides how much a visitor who isn't logged in can see, and the scraper can only return that. Plan around it:

  • Most profiles are limited. profileVisibility is full, limited or hidden. Work history (experience) and jobTitles only come back for full profiles, which are mostly creators, founders and executives. In the two detail runs I checked, 22 of 35 people were limited, 13 were hidden and none were full. On limited profiles, about was filled in on only 9 of 22.
  • Hidden profiles keep only the search data. You still get the name, headline and, when listed, company, location, school and connections.
  • Some last names are cut to an initial. About 1 in 10 rows in my runs had a name like "Jane D." LinkedIn shows those members that way to logged-out visitors, and that's all the scraper receives.
  • There are no emails or phone numbers.
  • Filters match words on the profile, not LinkedIn's internal fields, so someone who mentions Stripe as a past client can show up. In the runs I checked, 170 of 173 rows had the searched company in the headline or company field. Filter the company column if you need exact matches.
  • Seniority, function and company-size filters need an account. Put words like "Senior" or "Director" into the job title instead.

Step 6: Save to CSV

import csv

items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
fields = ["name", "headline", "company", "location", "school",
          "connections", "linkedinUrl", "query"]

with open("linkedin_profiles.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
    writer.writeheader()
    writer.writerows(items)
Enter fullscreen mode Exit fullscreen mode

extrasaction="ignore" drops any fields you didn't list. With pandas, pd.DataFrame(items).to_csv("linkedin_profiles.csv", index=False) works too.

What else can you scrape?

The same code works for my other LinkedIn scrapers. Change the actor name and the input:

Scaling

One search returns up to about 1,000 profiles. To get more, split it: add more cities, titles or schools, since each combination is its own search. Use maxResultsPerSearch when you want an even spread, for example 100 per city. The run report shows how many profiles each search found, and a search that stops near 1,000 has more to give if you split it further.

In my tests a run with several searches returned about 1,500 profiles per minute, and a single search about 500.

No code? Use the Apify Console

Open the actor page, click Try for free, type the titles, companies and cities one per line, and click Start. Results download as Excel, CSV, JSON, HTML or XML, or go straight to Google Sheets. Save the input as a task and put it on a schedule if you want the same search every week.

Cost

You pay per profile saved: $1.50 per 1,000 profiles from the search, and $2.50 per 1,000 with profile details. Limited and hidden profiles are charged at the lower price even when details are on. Each run also has a start fee of a fraction of a cent. The price is the same on every Apify plan.

The $5 of free monthly usage covers about 3,300 search profiles, or at least 2,000 with details. Check the Pricing tab on the actor page before a big run, since prices can change.

Responsible use

This is public data that LinkedIn shows to logged-out visitors, but a profile is still personal data. Under the GDPR and CCPA you need a lawful reason to collect it, should keep only what you need, and have to honor deletion requests. LinkedIn's User Agreement also restricts scraping, so read it and talk to a lawyer before you build a product or an outreach campaign on this data.

Links

If you want a LinkedIn profile scraper you can call from Python without logging in, try LinkedIn People Search Scraper on Apify. Your first runs fit in the free $5.

Top comments (0)