LinkedIn Jobs Scraper — From $0.25/1k · No Cookies, No Login
Pricing
from $0.25 / 1,000 job results
LinkedIn Jobs Scraper — From $0.25/1k · No Cookies, No Login
LinkedIn Jobs scraper — no login or cookies. Search by keyword, URL, or job IDs with expiry monitoring. Free title/employer filters, 1K-cap bypass, recruiter contacts, optional company enrichment. Salary, description, apply URL per job. From $0.25/1k. JSON or CSV.
Pricing
from $0.25 / 1,000 job results
Rating
0.0
(0)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
2
Monthly active users
3 days ago
Last modified
Share
LinkedIn Jobs Scraper
The fastest way to turn LinkedIn Jobs into structured, spreadsheet-ready data — without a LinkedIn account, cookies, or login. Start from a search URL, a keyword + location, a single job URL, or a plain list of job IDs, and get clean job rows with title, company, salary, full description, apply URL, and recruiter contacts (best-effort) — as JSON or CSV.
From $0.25 per 1,000 jobs on higher plans ($0.69/1k on the free plan) — pay only for the jobs that land in your dataset. Filtered, duplicate, and previously-seen jobs cost nothing.
Why Use This Scraper?
- ✅ No login, no cookies, no account risk — reads only LinkedIn's public Jobs surface
- ✅ Cheapest per-job price in its class — $0.69/1k free plan → $0.25/1k Gold and above
- ✅ Recruiter & hiring-team contacts (best-effort) — name, title, profile URL of the job poster
- ✅ Bypass LinkedIn's ~1,000-results-per-search cap — split by city or experience level automatically
- ✅ Job monitoring built in — paste job IDs, get back
isExpired/verifiedAt/verificationStatusper listing - ✅ Free result filters — title include/exclude and employer blocklist run before billing
- ✅ Cross-run dedup —
onlyNewJobsremembers what it already sent you, ideal for daily schedules - ✅ Optional company firmographics — website, size, employees, HQ, industry, follower count
Overview
The LinkedIn Jobs Scraper is built for recruiters, lead-gen teams, job-market analysts, and job-board builders who need structured job-posting data from LinkedIn without maintaining a logged-in session.
The output is always job-shaped rows. Whether you start from a search URL, keyword filters, a single job URL, or a list of job IDs, every dataset item is one job posting with the same ~40-field schema — so your downstream pipeline never has to branch on input type.
Cookie-based LinkedIn scrapers require you to hand over a logged-in session (which gets accounts flagged) or buy session cookies from third parties. This actor reads the same public Jobs pages any anonymous browser can see, so no account is required and none is at risk. The trade-off is honest: a few fields LinkedIn reserves for logged-in viewers (some recruiter cards, some salary ranges) are best-effort.
Supported Inputs
URL types
| URL type | Pattern | What it returns |
|---|---|---|
| Search URL | linkedin.com/jobs/search?keywords=…&location=… | Paginated job listings, filters read from the URL |
| Single-job URL | linkedin.com/jobs/view/4410745146/ | One enriched row per URL, no search phase |
| Slug job URL | linkedin.com/jobs/view/data-engineer-at-netflix-4350364210 | Same as above |
Copy-pasteable startUrls
{"startUrls": [{ "url": "https://www.linkedin.com/jobs/search?keywords=Software%20Engineer&location=United%20States&geoId=103644278" },{ "url": "https://www.linkedin.com/jobs/view/4410745146/" }]}
Job IDs mode — scrape or re-verify exact listings
Paste raw job IDs, view URLs, or any LinkedIn URL carrying currentJobId= into the jobIds field. Each entry goes straight to the job detail page. Re-run the same list on a schedule to monitor listings — every row includes isExpired, verifiedAt, and verificationStatus (active / closed / removed), so dead listings are flagged instead of silently missing.
{"jobIds": ["4410745146", "https://www.linkedin.com/jobs/view/4406118990/"]}
Keyword / filter mode
Leave URLs empty and let the actor build the search: keywords × locations × time range × workplace type × experience level × contract type × company names.
{"keywords": ["Data Engineer"],"location": "United States","timeRange": "r604800","remote": ["2"],"experienceLevels": ["4", "5"]}
Unsupported inputs
- ❌ URLs behind the LinkedIn login wall (Sales Navigator, Recruiter seats, private postings)
- ❌ LinkedIn profile / company-page URLs (see the dedicated actors in Explore More Scrapers)
- ❌ Shortened or redirect URLs (
lnkd.in/…)
Use Cases
| Audience | Use case |
|---|---|
| Recruiters & sourcing teams | Pull hiring-manager contacts from open roles and reach out before the inbox floods |
| B2B lead-gen / HR-tech vendors | Companies actively hiring for X are in-market for your product — build the list daily |
| Job boards & aggregators | Backfill listings at $0.25–0.69/1k with cross-run dedup so you only ingest new postings |
| Market & salary analysts | Track demand by title, region, seniority, and published salary bands |
| Sales intelligence teams | A competitor's job posts reveal their stack, roadmap, and the decision-makers to pitch |
| Agencies | Deliver client-ready hiring datasets on a schedule without writing scrapers |
How It Works

- Input — paste search URLs, job URLs, job IDs, or set keyword + location filters
- Route — search inputs paginate the public Jobs listing; job IDs and view URLs skip straight to the detail page
- Filter (free) — title include/exclude and employer blocklist drop unwanted jobs before they're collected or billed
- Collect & enrich — every kept job gets the full ~40-field row; optional company firmographics per unique employer
- Output — JSON or CSV dataset, plus a
RUN_SUMMARYrecord explaining exactly how the run ended
Input Configuration
Input fields
| Field | Type | Required | Notes |
|---|---|---|---|
startUrls | array<{url}> | one input mode | Mix of search URLs and single-job view URLs |
jobIds | array<string> | one input mode | Raw IDs, view URLs, or currentJobId= URLs — direct to detail page |
keywords | array<string> | one input mode | Used when no URLs are given |
location / locations | string / array | optional | Broad location, or several locations searched in one run |
geoId, placeIds | string, array | optional | LinkedIn geo precision (geoId, f_PP city-level filters) |
timeRange | enum | optional | any time, last 24h (r86400), week (r604800), month (r2592000) |
remote / jobTypes | array enum | optional | On-site 1 / Remote 2 / Hybrid 3 |
experienceLevels | array enum | optional | 1 intern → 6 director |
contractType | array enum | optional | F/P/C/T/I/V/O |
companyNames | array<string> | optional | Only include these employers (query-injected + name-matched) |
titleMustInclude | array<string> | optional | Keep only titles containing at least one term — free, pre-billing |
titleExclude | array<string> | optional | Drop titles containing any term — free, pre-billing |
excludeCompanies | array<string> | optional | Drop these employers — free, pre-billing |
scrapeCompanyDetails | boolean | optional | Company firmographics; billed per unique company |
onlyNewJobs | boolean | optional | Cross-run dedup — only jobs not returned in previous runs |
autoSplit | boolean | optional | Bypass ~1K cap by splitting the search across experience levels |
splitByLocation + splitCountry | boolean + enum | optional | Bypass ~1K cap by fanning out across a country's major cities |
maxItems | integer | optional | Hard cap on charged dataset rows |
minDelay/maxDelay, minConcurrency/maxConcurrency, maxRequestRetries | integer | optional | Crawl pacing |
proxy | object | optional | Residential recommended |
Common scenarios
1. Daily new-jobs monitor (schedule this)
{"keywords": ["DevOps Engineer"],"location": "Germany","timeRange": "r86400","onlyNewJobs": true,"titleExclude": ["senior", "principal"],"maxItems": 200}
2. Re-verify a list of tracked listings
{"jobIds": ["4410745146", "4406118990", "4350364210"]}
3. Break the 1,000-result cap for a whole country
{"keywords": ["Nurse"],"splitByLocation": true,"splitCountry": "GB","maxItems": 5000}
Output Overview
Each dataset item is one job posting containing:
- Core fields —
id,title,company,location,postedAt,jobUrl, fulldescription(+descriptionHtml) - Compensation & criteria — parsed
salary(minAmount/maxAmount/currency/period),seniorityLevel,employmentType,jobFunction,industries,benefits - Application —
applyUrl(external careers site when exposed),easyApply,numberOfApplicants/applicantsCount - People —
hiringTeam[]and flatjobPosterName/jobPosterTitle/jobPosterProfileUrl(best-effort; empty means LinkedIn hid it from anonymous viewers) - Company —
companyLinkedinUrlalways; withscrapeCompanyDetailsalso website, industry, size, employee count, HQ, logo, follower count - Verification —
isExpired,verifiedAt,verificationStatus(active/closed/removed) on every row - Provenance —
scrapedFrom(search-results/job-view-url/job-id-input),sourceUrl
Every run also writes a RUN_SUMMARY record to the key-value store: requested vs saved counts, pages parsed, jobs dropped per filter, expired jobs found, and a stopReason — so "why did I get 400 instead of 1000?" is answered by the run itself.
Output Samples
Search start (trimmed real row)
{"id": "4350364210","title": "Data Engineer (L5)","company": "Netflix","companyLinkedinUrl": "https://www.linkedin.com/company/netflix","location": "United States","seniorityLevel": "Not Applicable","employmentType": "Full-time","industries": ["Entertainment Providers"],"postedAt": "2026-07-02","postedTimeAgo": "5 days ago","numberOfApplicants": "Over 200 applicants","applicantsCount": 200,"easyApply": false,"description": "At Netflix, our mission is to entertain the world. Together, we are writing the next episode…","isExpired": false,"verifiedAt": "2026-07-08T03:58:41.120Z","verificationStatus": "active","jobUrl": "https://www.linkedin.com/jobs/view/data-engineer-l5-at-netflix-4350364210","scrapedFrom": "search-results"/* …plus salary, applyUrl, hiringTeam, jobPoster*, company* fields… */}
Job-ID start — removed listing (monitoring)
{"id": "3000000001","title": null,"company": null,"jobUrl": "https://www.linkedin.com/jobs/view/3000000001/","isExpired": true,"verifiedAt": "2026-07-08T03:57:33.319Z","verificationStatus": "removed","scrapedFrom": "job-id-input"}
Key Output Fields
Job core
id,title,company,location,postedAt,postedTimeAgo,jobUrl,sourceUrl
Description & criteria
description,descriptionHtml,criteria[],seniorityLevel,employmentType,jobFunction,industries[],benefits[],workplaceType
Compensation & application
salary.raw,salary.minAmount,salary.maxAmount,salary.currency,salary.periodapplyUrl,easyApply,numberOfApplicants,applicantsCount
Recruiter / hiring team (best-effort)
hiringTeam[].name,hiringTeam[].title,hiringTeam[].linkedinUrl,hiringTeam[].photojobPosterName,jobPosterTitle,jobPosterProfileUrl,jobPosterPhoto
Company (flat fields filled by scrapeCompanyDetails)
companyLinkedinUrl,companyLinkedinSlug,companyWebsite,companyIndustry,companySize,companyEmployeesCount,companyHeadquarters,companyFollowerCount,companyLogo,companyDetails
Verification & provenance
isExpired,verifiedAt,verificationStatus,scrapedFrom
FAQ
Do I need a LinkedIn account or cookies?
No. The actor reads only the public Jobs surface that any anonymous browser can access. No login, no cookies, no account at risk.
Why did I get fewer jobs than maxItems?
Check the RUN_SUMMARY record in the run's key-value store — it reports pages parsed, candidates seen, how many jobs each filter dropped, and the stopReason. The most common causes: the search genuinely has fewer results, LinkedIn's ~1,000-per-search ceiling (enable autoSplit or splitByLocation), or your title/company filters doing their job.
Are the title and company filters really free?
Yes. titleMustInclude, titleExclude, and excludeCompanies run before a job is collected, so filtered jobs are never charged and never consume detail-page requests.
Are recruiter contacts always available?
No — best-effort. LinkedIn shows the hiring-team card to anonymous viewers on some jobs and hides it on others. hiringTeam: [] means LinkedIn hid it, not that the parser failed. Same honesty applies to salary and applyUrl: they're populated when the employer published them.
How do I monitor jobs for expiry?
Put the job IDs (or view URLs) in jobIds and run on a schedule. Live listings return full rows with verificationStatus: "active"; closed listings are flagged "closed"; listings deleted from LinkedIn come back as sparse rows with "removed" and isExpired: true.
How do I get more than 1,000 jobs per search?
LinkedIn caps every guest search at ~1,000 results. Enable splitByLocation (fans the search out across a country's major cities) or autoSplit (splits across the six experience levels). Results are deduplicated automatically.
What does onlyNewJobs do?
It remembers the job IDs from your previous runs and skips them, so a scheduled run only returns postings it has never sent you before.
Can I scrape private or logged-in-only postings?
No. Anything behind the LinkedIn login wall (Sales Navigator, Recruiter, private postings) is out of scope.
Support
Found a bug or have a feature request? Open an issue on the actor's Issues tab or email me at muhameddidovic@gmail.com.
Additional Services
Need a custom export shape, an extra field, or a managed daily feed delivered to your database? I do tailored work — drop me a line at muhameddidovic@gmail.com.
Explore More Scrapers
If you found this useful, you might also like:
- LinkedIn Posts Scraper — posts from profiles and company pages, no cookies
- LinkedIn Company Employees Scraper — people behind any company page
- LinkedIn Ads Scraper — ad library search and details
- LinkedIn Profile Scraper — public profile data at $1/1k
Full list at apify.com/memo23.
⚠️ Disclaimer
This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.
The scraper accesses only publicly available LinkedIn Jobs pages — no authenticated endpoints, paid features, or content behind the linkedin.com login wall. Users are responsible for ensuring their use complies with LinkedIn's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.
SEO Keywords
linkedin jobs scraper, scrape linkedin jobs, linkedin job scraper, linkedin jobs API, linkedin job postings scraper, Apify linkedin jobs, job listings scraper, job board scraper, hiring data scraper, recruiter contact scraper, job monitoring tool, job posting verification, linkedin jobs without login, no-cookie linkedin scraper, job market analysis data, salary benchmark data, recruitment lead generation, hiring manager contacts, employment data extraction, HR tech data, talent sourcing data