LinkedIn Jobs Scraper | Experience Filters & Company Data
Pricing
from $0.25 / 1,000 results
LinkedIn Jobs Scraper | Experience Filters & Company Data
Scrape LinkedIn job listings worldwide by keyword and place or from search URLs, no login. Experience-level and job-type filters that really work, company website, size, industry, followers and HQ address, parsed pay range, applicant count, Easy Apply, plus incremental alerts.
Pricing
from $0.25 / 1,000 results
Rating
0.0
(0)
Developer
Corvuslab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
What does LinkedIn Jobs Scraper do?
LinkedIn Jobs Scraper extracts public job listings from linkedin.com/jobs in 137 countries. Its headline is experience-level and job-type filters that actually work: LinkedIn's public search quietly ignores both, so this Actor checks each posting's own seniority and employment type, and jobs that don't match are skipped and cost nothing. Pay, company size, industry, keyword and agency filters work the same way. Each job comes with up to 70 fields: full description, seniority, job type, applicants, Easy Apply or external, matched skills, a one-line AI summary, pay when the employer lists it, and an optional company profile (website, industry, size, followers, HQ address) at no extra cost.
Search by keyword and place, a whole country, a region group like DACH or the EU-27, or a company name, or paste LinkedIn search and job URLs. With no input at all you get the newest US jobs. Incremental mode returns and charges only new and changed jobs, with alerts to Telegram, Slack, Discord, WhatsApp or a webhook. Export to JSON, CSV or Excel, use the API, or feed an AI agent. No LinkedIn login or cookies needed from you.
New to Apify? Sign up free and use the included monthly platform credit to try this Actor. No credit card needed.
Why this scraper
- 🎯 Filters you can trust: experience level and job type are checked on each posting, so "Entry level, Full-time" means exactly that.
- 🏢 Company data included: website, size, industry, followers and HQ address at the same per-job price.
- 💰 Pay you can filter on: employer-stated ranges parsed into numbers, currency and period, plus a yearly figure for comparing and filtering.
- ♻️ Cheap to monitor: incremental mode skips unchanged jobs before their posting is read, and skipped jobs cost nothing.
What data can you extract from LinkedIn?
Every record carries up to 70 fields, grouped like this:
| Group | What you get |
|---|---|
| Job | title, url, id, location, country, countryCode, postedDate, postedAgo, listingBadge (e.g. "Actively Hiring"), isClosed |
| Job criteria & skills | seniorityLevel, employmentType, industries, applyType (EASY_APPLY / EXTERNAL), skills (matched from the description), language (e.g. en, de), isAgency (posted by a staffing or recruiting firm) |
| Pay (when the employer lists it) | salaryText, salaryMin, salaryMax, salaryCurrency (ISO code), salaryPeriod (YEAR, MONTH, HOUR…), salarySource, plus salaryYearlyMin / salaryYearlyMax |
| Demand & hiring team | applicantsCount as a number, applicantsText, plus jobPosterName, jobPosterTitle and jobPosterProfileUrl when LinkedIn shows the hiring team |
| Description, summary & contacts | description as plain text, descriptionHtml, descriptionMarkdown, aiSummary (one line for AI agents and ATS imports), plus extractedEmails, extractedPhones, extractedUrls and socialProfiles when the employer writes them into the posting |
| Company | company, companyUrl, companySlug, companyLogo, and with company details on: companyId, companyWebsite, companyIndustry, companySize, companyEmployeesOnLinkedIn, companyFollowers, companyHeadquarters, companyStreetAddress, companyPostalCode, companyCountryCode, companyType, companySpecialties, companySlogan, companyDescription |
| Monitoring | changeType, firstSeenAt, lastSeenAt, previousSeenAt, expiredAt, isRepost, repostOfId, repostDetectedAt, contentHash, plus searchKeyword / searchLocation showing which search found the job |
Key features
- 🎯 Experience-level and job-type filters that actually work: LinkedIn's public search ignores both and returns every level and type. This Actor reads each posting's own seniority (Internship to Executive) and employment type (Full-time, Contract…) and keeps only the matches. Non-matching jobs are not charged.
- 🏢 Company profiles in the same price: website, industry, size band, employees on LinkedIn, followers, HQ street address, postal and country code, type and specialties. No add-on event; each company is read once per run.
- 💰 Pay as numbers, and a pay filter:
CA$55,000.00/yr - CA$60,000.00/yrbecomes min 55000, max 60000, CAD, YEAR, plus yearly equivalents for hourly, daily, weekly and monthly pay. Filter by a yearly minimum or maximum in 15 currencies. - 🌍 Countries and region groups: 137 countries, or one click for DACH, Nordics, Benelux, UK & Ireland, EU-27, GCC, MENA, ASEAN, Latin America or the Anglosphere. Each country is its own search with LinkedIn's full 1,000-job view.
- 🏢 Companies by name: type "Google" or paste a company URL; it's matched to the right LinkedIn company and searched exactly.
- 🚫 Skip staffing agencies: one switch drops staffing, recruiting and headhunting firms, by the employer's LinkedIn industry and name. Every record carries
isAgency. - 🎚️ More filters, none charged when they drop a job: description must contain (e.g. "visa sponsorship"), exclude keywords, industry, company size, hiring team shown, title words, excluded companies, known job IDs. Plus LinkedIn's Easy Apply, under 10 applicants and a custom last N hours window.
- 🧠 Skills, language and an AI summary:
skillsare matched against a curated skill list (most postings get at least one),languageis the description's language, andaiSummaryputs the whole job in one line. - ♻️ Incremental monitoring: schedule it and get only NEW / UPDATED / REAPPEARED / EXPIRED jobs. Unchanged jobs are never charged; re-posts can be flagged or skipped.
- 🔔 Notifications: Telegram, Slack, Discord, WhatsApp or any webhook (n8n / Make / Zapier).
🚀 How to scrape LinkedIn jobs
- Enter one or more keywords (e.g.
data analyst) and places likeLondon, England, United Kingdom, or pick countries or a region group. Or paste a LinkedIn job-search URL. - Pick your filters: experience level, job type, posted within, pay, company size, industry, description words, agencies.
- Set Max results and decide whether to add company details.
- (Optional) Turn on incremental mode and a notification channel, then Schedule it.
- Click Start and download the results as JSON, CSV or Excel, or pull them from the API.
No LinkedIn account, no login, no cookies: it runs out of the box.
Quick-start example input
{"searchTerms": ["data analyst"],"locations": ["London, England, United Kingdom"],"experienceLevels": ["entryLevel", "associate"],"employmentTypes": ["fullTime"],"postedWithin": "pastWeek","includeCompanyDetails": true,"maxResults": 100}
This returns up to 100 full-time, entry-level or associate data analyst jobs posted in London in the past week. Each one really carries that seniority and job type, plus the full description, applicants and the hiring company's profile.
Input
Use the visual editor or pass JSON via the API. 58 inputs, grouped as in the editor.
🔎 Search
| Field | Type | What it does |
|---|---|---|
searchTerms | array | Job titles or skills, as typed on LinkedIn; each keyword is its own search in every place. Empty = newest jobs. |
locations | array | Countries, regions or cities ("Berlin") or a LinkedIn geoId. Empty = United States. |
countries | array (select) | 137 countries, one search each. |
regionPresets | array (select) | dach, nordics, benelux, ukIreland, eu27, gcc, mena, asean, latam, anglosphere; one search per member country. |
distance | string (select) | Radius around a city: 5 to 100 miles. |
startUrls | array | LinkedIn job-search URLs (filters kept) or job URLs; replaces the search form. |
maxResults | integer | Maximum jobs across all searches (default 25, 0 = no limit). |
maxResultsPerSearch | integer | Cap each keyword × place search (up to 1,000). |
🎚️ Filters
| Field | Type | What it does |
|---|---|---|
postedWithin | enum | Any time, past24Hours, pastWeek or pastMonth. |
postedWithinHours | integer | Custom window in hours (1–720), e.g. 1 or 6 for frequent schedules. Overrides postedWithin. |
experienceLevels | array (enum) | internship, entryLevel, associate, midSenior, director, executive, notApplicable, checked on each posting. |
employmentTypes | array (enum) | fullTime, partTime, contract, temporary, internship, volunteer, other, checked on each posting. |
easyApplyOnly | boolean | Only jobs you can apply to directly on LinkedIn. |
under10Applicants | boolean | Only jobs fewer than 10 people have applied to so far. |
companies | array | Only jobs at these companies, by name ("Google") or LinkedIn company URL. |
companyIds | array | The same by LinkedIn company ID (the number after f_C= in a company's job-search URL, e.g. 1441). |
titleIncludes / titleExcludes | array | Title must / must not contain these words. |
excludeCompanies | array | Drop jobs from companies whose name contains any of these. |
excludeAgencies | boolean | Drop jobs from staffing, recruitment and headhunting firms. |
excludeKeywords | array | Drop jobs whose title or description mentions any of these, e.g. "commission only". |
descriptionIncludes | array | Keep only jobs whose description mentions one of these, e.g. "visa sponsorship". |
industryIncludes | array | Keep only jobs whose LinkedIn industry contains one of these, e.g. "Software Development". |
requireSalary | boolean | Keep only jobs where the employer lists pay. |
salaryMin / salaryMax | integer | Yearly pay bounds (hourly × 2080, daily × 260, weekly × 52, monthly × 12). |
salaryCurrency | enum | Currency of the bounds: USD (default), EUR, GBP, CAD, AUD, INR, CHF and 8 more. |
includeUnknownSalary | boolean | Also keep jobs without comparable pay. |
requireJobPoster | boolean | Keep only jobs that show the hiring team. |
companySizeMin / companySizeMax | integer | Company size band bounds, e.g. 51 to 200 (reads company details automatically). |
skipJobIds | array | Job IDs or URLs you already have. |
Every filter from experienceLevels down is checked by the Actor itself, and a job it drops is never charged.
📦 Output
| Field | Type | What it does |
|---|---|---|
includeDetails | boolean | Read the full posting (default on). Off = a faster, card-only run. |
includeCompanyDetails | boolean | Add the hiring company's profile. |
descriptionFormat | enum | all, text, html or markdown. |
descriptionMaxLength | integer | Cut descriptions to this many characters (0 = full length). |
compact | boolean | Core fields only, for AI agents and MCP clients. |
excludeEmptyFields | boolean | Drop null, empty-string and empty-list fields. |
♻️ Incremental monitoring
| Field | Type | What it does |
|---|---|---|
incrementalMode | boolean | Tag jobs NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED; unchanged ones aren't charged. |
stateKey | string | Stable name for the tracked search (auto-derived from your settings if blank). |
emitUnchanged | boolean | Also return jobs that haven't changed. |
emitExpired | boolean | Return jobs that were listed last run but are gone now. |
skipReposts | boolean | Leave out jobs re-posted under a new ID. |
🔔 Notifications
Channels are off unless filled in. Credentials are encrypted, masked and never logged.
| Field | Type | What it does |
|---|---|---|
telegramToken + telegramChatId | string | Telegram bot token (from @BotFather) + chat or channel ID. |
slackWebhookUrl / discordWebhookUrl | string | Incoming webhook URL. |
whatsappAccessToken + whatsappPhoneNumberId + whatsappTo | string / array | WhatsApp Cloud API token, your business phone-number ID and recipient numbers. |
webhookUrl + webhookHeaders | string / object | POST every matched job (up to 1,000 per run) as JSON. |
notificationLimit | integer | Jobs listed per chat message (1–20, default 5). |
notifyOnlyChanges | boolean | In incremental mode, alert only on new, updated and reappeared jobs. |
⚙️ Advanced
| Field | Type | What it does |
|---|---|---|
proxyConfiguration | object | Connection settings. Keep the default for reliable runs. |
detailConcurrency | integer | How many postings to read at the same time (1–16, default 10). |
ignoreUrlFailures | boolean | Skip unreadable start URLs instead of failing. |
maxRequestRetries | integer | Retries for a failed request (0–10, default 6). |
More example inputs
Paste a LinkedIn search URL (its filters are kept) and a single job URL:
{"startUrls": [{ "url": "https://www.linkedin.com/jobs/search?keywords=product%20manager&location=Germany&f_TPR=r86400" },{ "url": "https://www.linkedin.com/jobs/view/4480525670" }],"includeCompanyDetails": true}
Watch two searches in two cities every few hours, skip agencies and get a Telegram alert for each new job:
{"searchTerms": ["python developer", "backend engineer"],"locations": ["Berlin", "Munich"],"postedWithinHours": 6,"excludeAgencies": true,"incrementalMode": true,"notifyOnlyChanges": true,"telegramToken": "<your bot token>","telegramChatId": "@yourchannel","maxResults": 0}
Data engineering jobs across the Nordics that state at least 60,000 a year in euros, at companies of 51+ people:
{"searchTerms": ["data engineer"],"regionPresets": ["nordics"],"salaryMin": 60000,"salaryCurrency": "EUR","companySizeMin": 51,"maxResultsPerSearch": 200}
Senior roles at named companies that still have few applicants:
{"companies": ["Google", "https://www.linkedin.com/company/microsoft"],"countries": ["US", "GB"],"titleIncludes": ["senior", "staff"],"under10Applicants": true}
Output
Each dataset item is one LinkedIn job. A real record (descriptions shortened here):
{"id": "4480525670","url": "https://www.linkedin.com/jobs/view/4480525670","title": "Junior Accountant","company": "Peak Associates Limited","companyUrl": "https://ca.linkedin.com/company/peak-associates-limited","location": "North York, Ontario, Canada","country": "Canada","countryCode": "CA","postedDate": "2026-10-16","postedAgo": "6 days ago","listingBadge": "Actively Hiring","salaryText": "CA$55,000.00/yr - CA$60,000.00/yr","salaryMin": 55000.0,"salaryMax": 60000.0,"salaryCurrency": "CAD","salaryPeriod": "YEAR","salarySource": "EMPLOYER","salaryYearlyMin": 55000.0,"salaryYearlyMax": 60000.0,"applicantsCount": 200,"applicantsText": "Over 200 applicants","seniorityLevel": "Associate","employmentType": "Full-time","industries": "Staffing and Recruiting","applyType": "EASY_APPLY","isAgency": true,"isClosed": false,"skills": ["Excel", "Accounting", "GAAP", "Accounts Payable", "Accounts Receivable", "CPA", "Time Management"],"language": "en","aiSummary": "Junior Accountant at Peak Associates Limited (North York, Ontario, Canada) · Full-time · Associate · pay CA$55,000.00/yr - CA$60,000.00/yr · Easy Apply · Over 200 applicants · posted 2026-10-16 · industry: Staffing and Recruiting · skills: Excel, Accounting, GAAP, Accounts Payable, Accounts Receivable, CPA, Time Management","description": "Our client is seeking a Junior Accountant reporting to the Director of Accounting to join their team in Toronto. …","companyWebsite": "http://www.peakassociates.com","companyIndustry": "Staffing and Recruiting","companySize": "11-50 employees","companyEmployeesOnLinkedIn": 10,"companyFollowers": 58622,"companyHeadquarters": "Toronto, ON","companyStreetAddress": "2345 Yonge Street, Suite 505","companyPostalCode": "M4P 2E5","companyCountryCode": "CA","companyType": "Privately Held","companySpecialties": ["Recruitment", "Temporary Staffing Services", "Talent Acquisition", "Executive Search"],"source": "linkedin.com","searchKeyword": "accountant","searchLocation": "Toronto","scrapedAt": "2026-10-23T12:34:26.021163+00:00","detailFetched": true}
Descriptions also come as descriptionHtml and descriptionMarkdown. This posting comes from a recruitment firm, so it has isAgency: true, and Exclude staffing & recruiting agencies would have dropped it at no cost. In incremental mode each record carries a changeType (NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED) with firstSeenAt / lastSeenAt, and EXPIRED jobs get expiredAt. A job read by its URL after it stopped taking applications comes back with isClosed: true.
Data fields
Card fields are always there; Fetch the full job posting adds description, criteria, skills, language, AI summary, agency flag, applicants, apply type, pay and hiring team; Add company details adds the company profile including companyId.
Every field is present in standard mode (missing values are null); compact mode returns the core fields only, for lean AI/MCP payloads; excludeEmptyFields drops empties entirely. The Output tab ships two ready-made views: Overview (one row per job) and Companies (website, industry, size, HQ per open role).
♻️ How to monitor LinkedIn jobs with incremental mode
Schedule the Actor and turn on incremental mode: each run compares against the last and returns only NEW / UPDATED / REAPPEARED / EXPIRED jobs. Unchanged jobs are recognised from the search results before their posting is read, so you skip both the work and the cost.
| First run (baseline) | Next run (nothing changed) | |
|---|---|---|
| Jobs found in the search | all | all |
| Postings read | all | none |
| Jobs returned & charged | all | none |
Your cost after the baseline scales with how much the search changes, not with how much you watch:
| Daily churn | of 1,000 tracked | billable jobs | you save |
|---|---|---|---|
| 5 % | 1,000 | 50 | 95 % |
| 15 % | 1,000 | 150 | 85 % |
| 30 % | 1,000 | 300 | 70 % |
Re-posts under a new ID are flagged with isRepost / repostOfId, or left out with Skip re-posted jobs. EXPIRED needs a run that reads the whole search: Max results 0, and each search under 1,000 jobs.
Setting up scheduled monitoring
- Configure your search and filters; a last N hours window matching your schedule keeps runs small.
- Turn on Incremental mode.
- Run it once to seed the baseline.
- Open the Schedules tab and set a recurring run (e.g. every hour or every morning).
- Add a notification channel with Alert only on changes on.
🔔 How to set up LinkedIn job alerts
Fill in only the channels you want:
| Channel | What to configure |
|---|---|
| ✈️ Telegram | telegramToken (from @BotFather) + telegramChatId |
| 💬 Slack | slackWebhookUrl (Incoming Webhook URL) |
| 🎮 Discord | discordWebhookUrl (channel webhook URL) |
whatsappAccessToken + whatsappPhoneNumberId (WhatsApp Cloud API) + whatsappTo numbers | |
| 🪝 Webhook | webhookUrl receives every matched job as structured JSON, ideal for n8n / Make / Zapier |
Each message lists the title, company, place, pay and link for up to notificationLimit jobs. A broken channel can't stop the scrape or the others. WhatsApp follows Meta's 24-hour rule: a free-form message only reaches a number that has written to your business number in the last 24 hours, so have each recipient message it first. Pair incremental mode with Alert only on changes to hear only about genuinely new jobs.
💡 What can you do with LinkedIn data?
Get job alerts that match your level
Set your level, Full-time and a 1-hour window, schedule it hourly and get a ping for every fresh posting. Add fewer than 10 applicants to apply early.
Recruiting and sales lead generation
Every company posting a job is hiring. Get its website, size, industry and HQ with each job, filter by size, and drop agencies for a clean list of direct employers.
Salary benchmarking
Collect employer-stated pay ranges with currency and period, and compare roles, levels and countries on the yearly figures. Turn on Only jobs with a stated pay range to skip the rest at no cost.
Labour-market and competitor research
Track how many roles a competitor opens, where, at which levels and with which skills, week by week. Region groups cover a whole market in one run.
Feed AI agents and LLM pipelines
aiSummary gives an agent or ATS the whole job in one line, and skills is ready for CV matching. Compact mode and excludeEmptyFields keep token costs low.
💰 How much does it cost to scrape LinkedIn?
This Actor uses Apify's pay-per-event model: a tiny fee when a run starts, plus one fee for each job you receive. See the Pricing tab for the live numbers.
The full posting and the company profile are part of that one price: there is no separate charge for company data. Three things cut your bill further:
- Filters that skip before charging: jobs that fail the experience-level, job-type, pay, company-size, industry, keyword, agency or title filters are dropped and never charged.
- Incremental mode: after the baseline you pay only for what changed (the table above).
🔌 Integrations & export
Export to JSON, CSV, Excel or an HTML table, or pull from the REST API and the JavaScript / Python clients. Runs on a schedule, connects to Google Sheets, Slack, Make, Zapier and n8n, and works as an MCP tool for AI agents. Compact mode keeps token usage small.
Also covering jobs and employers: our XING Jobs Scraper (DACH), Glassdoor Job Scraper and Greenhouse, Lever & Ashby Jobs Scraper.
🔗 Using the API
Run this Actor from your own code. Example with the Apify Python client:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run_input = {"searchTerms": ["data engineer"],"locations": ["Canada"],"experienceLevels": ["midSenior"],"postedWithin": "pastWeek","includeCompanyDetails": True,"maxResults": 50,}run = client.actor("corvuslab/linkedin-jobs-scraper").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["company"], item["salaryText"])
It also works with the JavaScript/TypeScript client, the Apify CLI and the REST API.
❓ FAQ
Do I need a LinkedIn account, login or cookies? No. It reads LinkedIn's public job listings, the ones anyone can open without signing in.
Why do the experience-level and job-type filters work differently here? LinkedIn's public search ignores both, so the Actor reads each posting and keeps only those whose own seniority and employment type match. Jobs that don't match are not charged. These filters always read the full posting, even with Fetch the full job posting off. Filters that keep only a sliver of jobs stop the run early; the log suggests a keyword instead.
How many jobs can I get from one search? LinkedIn shows at most 1,000 jobs per search. Go further with more places (cities, or a region group) or more keywords: each keyword × place is its own search with its own 1,000-job view, de-duplicated.
Why is the pay range empty on most jobs? LinkedIn shows pay only when the employer states it, a minority of postings that varies by country. Otherwise the pay fields are null; pay is never guessed. So a pay filter returns fewer jobs: jobs without stated pay, or in another currency, are left out unless you turn on Keep jobs without comparable pay.
Do I get the external apply link? No. LinkedIn doesn't show the employer's own application link to signed-out visitors. Every posting carries applyType instead: EASY_APPLY (apply on LinkedIn) or EXTERNAL (apply on the employer's site).
Can I filter remote or hybrid jobs? Not reliably. Public postings don't say whether a role is remote, hybrid or on-site, and "Remote" as a place doesn't filter for it. Title must contain remote keeps jobs whose title says so.
Why is the hiring team empty on most jobs? jobPosterName, jobPosterTitle and jobPosterProfileUrl are filled only when LinkedIn shows a "Meet the hiring team" box, which is a small share of jobs. Only jobs that show the hiring team keeps just those.
How do I scrape all jobs from one company? Type its name or paste its LinkedIn company URL into Companies, or use its numeric ID in Company IDs. Leave keywords empty for all its roles in your places. The log shows which company each name matched; if none can be matched, the run searches nothing, so you're never charged for unrelated jobs.
How are skills found? By matching the title and description against a curated list of skills and tools (Excel, Python, GAAP, Kubernetes…). A skill appears only when the posting names it.
⚖️ Is it legal to scrape LinkedIn?
This Actor collects only publicly available job listings: the postings and company pages LinkedIn shows to anyone signed out. It does not scrape member profiles; the only personal data is what a posting displays, such as a hiring-team contact's name and title. You're responsible for how you use the data, especially personal information, and for complying with LinkedIn's terms and applicable law (including the GDPR/LGPD). Not affiliated with, endorsed by or sponsored by LinkedIn Corporation.
Keywords: linkedin jobs scraper · linkedin job scraper · linkedin scraper · linkedin jobs api · scrape linkedin jobs · linkedin job postings · linkedin job listings export · linkedin jobs without login · linkedin company data · linkedin salary data · linkedin jobs by country · job market research · recruitment lead generation · job monitoring · linkedin job alerts · export to CSV · export to Excel · no-code scraper · MCP tool for AI agents