LinkedIn Jobs Scraper (no login, no cookies)
Pricing
from $0.60 / 1,000 jobs
LinkedIn Jobs Scraper (no login, no cookies)
Scrape LinkedIn job postings without an account or cookies. Search keywords × locations with LinkedIn filters; get title, company, location, country, posted date, salary, seniority, applicants, Easy Apply and full description. Deduped, resumable.
Pricing
from $0.60 / 1,000 jobs
Rating
0.0
(0)
Developer
Carina Hatton
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Security
Limited permissionsShare
Get job postings from LinkedIn's public job search: the pages anyone can see without signing in. You type keywords and locations like you would on LinkedIn. You get a clean table of jobs with company, location, posted date, applicant count, seniority, employment type, salary (when LinkedIn shows it) and the full description.
No LinkedIn account, no cookies and no browser are needed. Your own LinkedIn profile is never involved.
What it does
- Searches like LinkedIn does. Keywords × locations, plus LinkedIn's own filters: date posted, job type, experience level, on-site/remote/hybrid, sort order and distance.
- Runs many searches at once. Every keyword is searched in every location (2 keywords × 3 locations = 6 searches). The same job is saved only once, even if several searches find it.
- Opens each job's detail page (optional) to add seniority, employment type, industries, applicant count, Easy Apply flag and the description.
- Resumes after interruptions. Progress is saved in the run's key-value store, so a migrated or restarted run picks up where it stopped instead of starting over or saving duplicates.
- Writes one row per job in a format that matches other job-board and ATS scrapers. It's easy to merge, dedupe on
jobIdand load into a spreadsheet, CRM or database.
Use cases
- Recruiters and sourcers. Track who is hiring for a role in a region, how fresh each posting is and how many people have applied.
- Job boards and aggregators. Fill a niche board (e.g. "remote data jobs") with fresh postings, then link out to the original posting.
- Sales and market-signal tools. Use hiring activity as a buying signal: companies hiring "Salesforce admin" or "data engineer" this week, by country and industry.
- Labour-market research. Compare demand, seniority mix and posted salary ranges across cities or titles over time.
Quick start
Open the Actor, keep the pre-filled input (data analyst · United States · past week · 25 jobs) and click Start. Then:
- Change Keywords and Locations. Use one entry per line, e.g.
product manager,Berlin, Germany. - Optionally narrow the search with the Filters.
- Set Max jobs. Leave Open each job's detail page on for full records, or turn it off for a fast list from the search cards only.
Input examples
One role, nationwide, last 7 days:
{"keywords": ["data analyst"],"locations": ["United States"],"datePosted": "pastWeek","maxItems": 25}
Several roles × several cities, remote only, newest first, card fields only:
{"keywords": ["data engineer", "analytics engineer"],"locations": ["Austin, TX", "Denver, CO", "Toronto, Ontario, Canada"],"datePosted": "past24h","workplaceType": ["remote"],"sortBy": "recent","includeDetails": false,"maxItems": 300,"maxItemsPerSearch": 50}
Exact location using LinkedIn's geoId (103644278 = United States):
{ "keywords": ["python developer"], "geoId": "103644278", "maxItems": 100 }
Output example
This is one real item from a test run on 30 Oct 2026. Descriptions are shortened here.
{"platform": "linkedin","jobId": "4485262266","title": "Senior Data Analyst","company": "Marathon Petroleum Corporation","companySlug": "marathon-petroleum-company","companyUrl": "https://www.linkedin.com/company/marathon-petroleum-company","location": "Findlay, OH","locations": ["Findlay, OH"],"country": "US","workplaceType": null,"remote": null,"employmentType": "FULL_TIME","employmentTypeRaw": "Full-time","seniority": "Not Applicable","industries": "Oil and Gas","salary": null,"postedAt": "2026-10-29T00:00:00+00:00","postedAtText": "1 day ago","applicantCount": 87,"applicantCountText": "87 applicants","applicantCountIsLowerBound": false,"applicantCountIsUpperBound": false,"easyApply": false,"jobUrl": "https://www.linkedin.com/jobs/view/4485262266/","applyUrl": "https://www.linkedin.com/jobs/view/4485262266/","applyUrlIsExternal": false,"descriptionText": "An exciting career awaits you\n\nAt MPC, we’re committed to being a great place to work – one that welcomes new ideas, enc…","descriptionSnippet": "An exciting career awaits you …","searchQuery": { "keywords": "data analyst", "location": "United States" },"sourceUrl": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=data%20analyst&location=United%20States&f_TPR=r86400&sortBy=R&start=0","scrapedAt": "2026-10-31T00:20:16+00:00"}
Output fields
| Field | What it is | Source |
|---|---|---|
jobId | LinkedIn job ID (unique key; duplicates across searches are skipped) | card |
title, company, companyUrl, companySlug | Job title and the company's LinkedIn page | card |
location, locations | Location exactly as LinkedIn shows it | card |
country | ISO country code (e.g. US, CA, GB), worked out from the location text. Falls back to the search location for metro areas like "New York City Metropolitan Area". null if it can't be determined | derived |
workplaceType, remote | remote / hybrid / onsite when LinkedIn shows it on the card (e.g. "(Remote)") or in the job title, or when you filter by exactly one workplace type. Otherwise null | card / filter |
postedAt, postedAtText | Posted date (date only; LinkedIn gives no time of day) and LinkedIn's relative text, e.g. "2 hours ago" | card |
salary | {min, max, currency, interval, text}. Only present when LinkedIn shows a salary | card / detail |
seniority, employmentType, employmentTypeRaw, industries | From the job's criteria box | detail |
applicantCount, applicantCountText | Number of applicants and LinkedIn's wording | detail |
applicantCountIsLowerBound | true for "Over 200 applicants" (real number is higher) | detail |
applicantCountIsUpperBound | true for "Be among the first 25 applicants" (real number is lower) | detail |
easyApply | true = apply on LinkedIn, false = apply on the employer's site | detail |
applyUrl, applyUrlIsExternal | Employer's apply URL when LinkedIn exposes it to signed-out visitors (applyUrlIsExternal: true); otherwise the LinkedIn job URL | detail |
descriptionHtml, descriptionText, descriptionSnippet | Full description (HTML and plain text) and the first 300 characters | detail |
jobUrl, sourceUrl, searchQuery, scrapedAt | Job page, the search page it came from, which keyword × location found it, and when | run |
department, team, updatedAt, jobFunction | Kept for compatibility with other job datasets. LinkedIn's public pages currently don't show these, so expect null | – |
The run also saves a RUN_SUMMARY record with pages, cards, saved jobs and duplicates for each search, plus request and block counts.
How many jobs per search?
LinkedIn's public search returns at most about 1,000 jobs per keyword × location. For more, split the search: use more specific locations, narrower date ranges or extra keywords. Results from all searches are deduplicated.
FAQ
Do I need a LinkedIn account or cookies? No. The Actor only reads pages that are public to signed-out visitors.
Why use a residential proxy? LinkedIn rate-limits data-centre IPs quickly. The default is Apify's residential proxy. Requests are sent one at a time with a pause in between (3 s by default, plus a random 0–2 s). A proxy IP is swapped when LinkedIn answers with a rate-limit or block page.
Why is applyUrl usually the LinkedIn URL? For jobs that apply on the employer's site, LinkedIn currently shows the employer's link only to signed-in members. Whenever the public page does include it, the Actor saves it and sets applyUrlIsExternal: true. easyApply still tells you whether the application happens on LinkedIn or off-site.
Why are some fields empty? Salary appears only when the employer published one. In a 75-job US test run, 6 jobs had a salary. workplaceType is filled only when LinkedIn labels it on the card, in the title, or through your filter. Turning off detail pages leaves the detail-only fields empty.
Can I run it on a schedule? Yes. Use Apify Schedules, e.g. daily with datePosted: past24h, and dedupe on jobId downstream.
Can I get results through the API or in Google Sheets, Zapier or Make? Yes, like any Apify Actor: through the API, webhooks or the standard integrations.
Limits (honest version)
- Only data that LinkedIn shows to signed-out visitors is collected. There are no recruiter names, no contact details and no member profiles.
- There's a cap of about 1,000 results per search (LinkedIn's own limit).
- LinkedIn changes its pages from time to time, which can break parsing until the Actor is updated. The RUN_SUMMARY shows pages, cards and saved jobs per search, so a search that suddenly returns 0 cards is easy to spot.
- Without a proxy (or on a busy IP) LinkedIn answers with HTTP 429 quickly. The Actor backs off and retries, but the default residential proxy is strongly recommended.
- Large runs can still be rate-limited. Very aggressive settings (a short interval, many searches) increase blocks.
Responsible use
This Actor reads publicly available pages. You are responsible for how you use it and the data it collects. That includes complying with LinkedIn's User Agreement and with privacy and data-protection laws that apply to you (e.g. GDPR or CCPA). Use the data for legitimate purposes and don't use it to spam people.
Support
Found a bug or need a field? Open an issue on the Actor's Issues tab with the run ID, and it will be looked at.