LinkedIn Jobs Scraper
Pricing
from $0.60 / 1,000 job delivereds
LinkedIn Jobs Scraper
Export LinkedIn jobs with company enrichment, CV keyword matching, applicant counts and annualised salary. No login, no cookie, no proxy needed.
Pricing
from $0.60 / 1,000 job delivereds
Rating
0.0
(0)
Developer
丂卩ㄖㄖҜㄚ
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
Export LinkedIn job listings with company enrichment, CV keyword matching, applicant counts and salary parsing. No login, no session cookie, no proxy required.
🔍 What does LinkedIn Jobs Scraper do?
It runs a job search on LinkedIn and returns every listing it finds as a clean row of data, ready for a spreadsheet, a database or your own product.
No login, no session cookie, no proxy required. This reads LinkedIn's public guest endpoints, the ones that serve logged out job browsing, so there is no session to expire and no account of yours at risk.
On top of the listing itself you can add company details, filter on applicant counts and score every job against your own CV keywords.
📊 What data can I extract from LinkedIn?
One row per job:
| Field | Notes |
|---|---|
jobId, title, company, companyUrl, location | The listing and who posted it |
postedAt, url | Posting date and a direct link |
applicants, applicantsBasis, isEarlyApplicant | How many have applied, and how firm that number is |
applyType, seniority, employmentType | How to apply and at what level |
jobFunction, industries | LinkedIn's own categorisation |
description, descriptionLength | Full job description |
salaryFrom, salaryTo, salaryCurrency, salaryPeriod, salaryRaw, hasSalary | Pay as published |
listingSalary | Salary exactly as written on the listing, before any parsing |
salaryAnnualisedFrom, salaryAnnualisedTo | Annual equivalent so hourly, daily and annual roles compare in one column |
payBand, payScheme | NHS style pay bands, kept as facts rather than converted |
keywordMatchScore, matchedKeywords, unmatchedKeywords | CV match, when resumeKeywords is set |
companyName, companyEmployees, companyFollowers, companyIndustry, companyWebsite, companyDescription, companyCity, companyCountry | Added by enrichCompanyData |
searchKeywords, searchLocation, retrievedAt | The search that produced the row, and when |
💡 Why scrape LinkedIn jobs?
Jobseekers. Filter to early applicant roles matching your CV, at direct employers rather than agencies.
Recruiters. Track competitor hiring by company, size and industry.
Salary benchmarking. Annualised pay by title and region, with NHS bands handled properly.
Market research. Hiring volume by sector, company size and location over time.
🚀 How do I use LinkedIn Jobs Scraper?
- Click Try for free.
- Enter what you are searching for and where, for example
software engineerinLondon. - Add any filters you want, such as date posted, workplace type or company size.
- Cap the run with
maxResults, then click Start. - Download the results as JSON, CSV or Excel, or pull them from the API.
⬇️ Input
{"keywords": "software engineer","location": "London","maxResults": 100}
Set at least one of keywords or location.
| Field | Type | Default | What it does |
|---|---|---|---|
keywords | string | Job title or keywords | |
location | string | City, region or country | |
datePosted | string | any | Any time, past 24 hours, past week or past month |
workplaceType | string | any | On site, remote or hybrid |
jobType | string | any | Full time, part time, contract, temporary, internship or volunteer |
experienceLevel | string | any | Internship through executive |
sortBy | string | relevance | Relevance or most recent |
requireSalaryInfo | boolean | false | Only jobs that state pay or an NHS band |
maxResults | integer | 100 | Hard cap on billable results |
Many more filters are available including company size, industry, applicant count and CV keyword matching, see the input schema in the Console.
Company filters
| Field | Description |
|---|---|
companyInclude | Only these employers. Suffixes like Ltd and PLC are ignored when matching |
companyExclude | Drop these employers |
excludeRecruitingAgencies | Drop agency listings and keep direct employers |
enrichCompanyData | Add employee count, followers, industry, website and location |
companySizeMin / companySizeMax | Filter by employee count |
companyFollowersMin / companyFollowersMax | Filter by LinkedIn following |
Company pages are fetched once per company and cached within a run, so a hundred jobs at one employer costs one extra request, not a hundred.
Job filters
| Field | Description |
|---|---|
excludeJobTitles | Drop titles containing any of these words |
underTenApplicants | LinkedIn's own low competition filter, applied server side |
maxApplicants | Only jobs with an exact count at or below this |
easyApplyOnly | Apply without leaving LinkedIn, applied server side |
requireSalaryInfo | Only jobs that state pay or an NHS band |
CV matching
Paste your skills into resumeKeywords and every job is scored on how many appear in the title and description. You get keywordMatchScore as a percentage plus matchedKeywords and unmatchedKeywords, so you can see exactly why a job scored what it did. Set minKeywordScore to drop anything below a threshold.
⬆️ Output
Table view
Results arrive as a table you can sort and filter in the Console. There is a second view, Salary detail, that lines up the parsed and annualised pay figures for comparing listings against each other.
Every run also writes a RUN_SUMMARY to the key value store showing how many jobs were scanned, how many were kept, and exactly which filter rejected the rest. If a run returns nothing you can see why rather than guessing.
JSON
A typical row:
{"title": "Product Manager","company": "Example Group","location": "Reading, England, United Kingdom","postedAt": "2026-08-07T00:00:00.000Z","url": "https://uk.linkedin.com/jobs/view/product-manager-4448545238","jobId": "4448545238","companyUrl": "https://uk.linkedin.com/company/examplegroup"}
Download it from the run as JSON, CSV or Excel, or read it straight from the API.
Two things this does that others do not
Salary you can actually compare. Pay is published as hourly, daily or annual with no consistency. Every job gets salaryPeriod plus salaryAnnualisedFrom and salaryAnnualisedTo, so one column sorts correctly across the whole result set.
UK healthcare pay bands. NHS roles state pay as "Band 5" rather than a number, so generic scrapers report no salary at all. On a sample of 20 UK nursing jobs, numeric salary extraction found pay on 1. Adding band detection took that to 9. You get payBand and payScheme as facts. The actor deliberately does not convert bands into salary figures, because published Agenda for Change tables disagree with each other materially and inventing a number would be worse than leaving it out.
Honest limits
1,000 results per search. LinkedIn's own ceiling, not a bug. Verified: offset 975 returns jobs, offset 1000 returns an error. Narrow the search with filters or date ranges to get past it.
Applicant counts are bucketed below 25. LinkedIn will filter to low competition jobs server side via underTenApplicants, but its guest view still reports "be among the first 25 applicants" rather than the exact figure. So you can select those jobs, you just cannot see the true number. The applicantsBasis field marks every count as exact, upper-bound or minimum so you always know which you are looking at.
Salary is often absent. LinkedIn does not require employers to publish pay, and most do not. requireSalaryInfo filters to those that do.
Empty results are not a failure
If nothing passes your filters the run finishes successfully with an empty
dataset, and RUN_SUMMARY holds the rejection breakdown, so you can see which
filter ate everything.
An earlier version threw an error here. That recorded a failed run against the actor's success rate for what was a filter choice, and it discarded the diagnostic you needed.
When a filter cannot be evaluated
If a detail page fails to load, the job's function, industry and applicant count
are unknown. By default those jobs are kept, so a network problem is never
mistaken for a filter decision. detailFailures in RUN_SUMMARY tells you how
often it happened.
Set strictFilters to reject them instead.
Speed
concurrency controls how many detail and company pages are read at once,
default 6, maximum 10. It does not change how many requests are made, only how
long you wait. Ten detail pages take under a second at the default, against
roughly eight seconds one at a time.
Salary
Salary is read from the listing's own pay field, or from a labelled pay section
on the detail page. It is never extracted from the body of a job description: a
project budget or a revenue figure in the copy would otherwise become the
salary and then feed salaryMin filtering. Where there is no pay information,
hasSalary is false rather than a number being guessed.
💰 How much does it cost?
Three events, because the cost of a run is not proportional to how many jobs survive your filters.
| Event | Charged when |
|---|---|
job-detail-fetched | A job detail page is read |
company-enriched | A company page is read, once per company |
job-result | A job passes every filter and is delivered |
Deep filtering asks this actor to read a thousand jobs to find fourteen. Under a single per-result charge, the better your filters the worse the economics, which is the wrong incentive on the one feature that sets this apart. Splitting the events means you pay for the reading you asked for and the results you got, and both are visible before you run.
Cheap filters, company name, title exclusions and agency exclusion, are applied before any detail request, so they never cost you a fetch.
What a run actually costs
The listing shows the result price. That is the cheap end, and deep filtering costs more, so here are both plainly:
| Run | Cost |
|---|---|
| 100 jobs, no detail filters | about $0.10 |
| 1,000 scanned, 14 delivered after salary, applicant and keyword filters | about $2.01 |
The second run reads a thousand detail pages to find fourteen jobs. That reading
is the work you asked for and it is charged at job-detail-fetched, not hidden
in the result price. Filters that need no detail page, company name, title
exclusions and agency exclusion, are applied first and cost nothing.
If you want the cheap end, leave the detail filters off.
🔌 Integrations
Send results straight to Google Sheets, Slack, Airtable, Zapier, Make or your own webhook using Apify integrations. You can also trigger a run whenever something happens in another tool.
🔗 Using LinkedIn Jobs Scraper with the Apify API
curl -X POST "https://api.apify.com/v2/acts/spookyweb~linkedin-jobs/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"keywords": "software engineer", "location": "London", "maxResults": 100}'
Or with the Apify client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('spookyweb/linkedin-jobs').call({keywords: 'software engineer',location: 'London',maxResults: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Full detail is in the Apify API reference, and every run is also callable from the Python and JavaScript clients.
❓ FAQ
Do I need a LinkedIn account or a session cookie?
No, and that is the point. This reads the public guest job pages, so there is no login step, no cookie to paste and no session of yours to expire or get flagged. You also do not need a proxy.
How many jobs can I get from one search?
Up to 1,000, which is LinkedIn's own ceiling rather than a limit set here. Past that the guest endpoint returns a 400, which the run treats as a normal end and finishes successfully with what it has. To cover more of a market, split the search by location, by job title or by date range.
What is CV keyword matching?
Put your skills into resumeKeywords and every job is scored on how many of them appear in its title and description. The row carries keywordMatchScore as a percentage plus matchedKeywords and unmatchedKeywords, so the score is auditable. minKeywordScore drops anything below a threshold.
Does it get applicant counts?
Yes, in applicants, with applicantsBasis saying whether the figure is exact, an upper-bound or a minimum. Below 25 applicants LinkedIn's guest view reports a bucket rather than a number, so you can still select those jobs with underTenApplicants, you just cannot see the true count.
What does enrichCompanyData add?
Employee count, followers, industry, website, description and location for the hiring company. Company pages are read once per company and cached within the run, so a hundred jobs at one employer costs one extra request rather than a hundred.
Why is a job kept when a lookup fails?
Because a network problem is not a filter decision. If a detail page will not load, the job's function, industry and applicant count are unknown, and dropping it would quietly turn an outage into a filtered result. Those jobs are kept by default and counted in detailFailures. Set strictFilters to reject them instead.
⚖️ Is it legal to scrape LinkedIn?
This reads LinkedIn's public guest job pages, the ones anyone can see without an account. It never logs in, it never uses a cookie, and it never touches anything behind authentication. Job adverts are business information published by employers to be seen.
Scraping public data is lawful in the UK, the EU and the US, and the hiQ v LinkedIn line of cases went to public data specifically. If you go on to combine this data with personal data, that is on you to handle under GDPR. Apify's ethical scraping guide covers the wider picture.
👍 Your feedback
Found a bug, or want a field that is not here yet? Open an issue on the Actor's Issues tab. Requests that make the data more useful get built, and problems get fixed quickly.
🔎 You might also like
| Actor | What it does |
|---|---|
| Indeed Jobs Scraper | Indeed listings with parsed salary figures, past the 15 job sign in wall |
| Reed Jobs Scraper | UK jobs from Reed with applicant counts and annualised salaries |
| Totaljobs Scraper | UK jobs from Totaljobs with duplicate agency repostings removed |