LinkedIn Jobs Scraper — Filter-Based, No Login avatar

LinkedIn Jobs Scraper — Filter-Based, No Login

Pricing

$5.00 / 1,000 job results

Go to Apify Store
LinkedIn Jobs Scraper — Filter-Based, No Login

LinkedIn Jobs Scraper — Filter-Based, No Login

Scrape LinkedIn jobs from public guest pages with friendly filters — no URL building, no login. Complete public job + company data, dedup + repost detection, a 1000-result-cap workaround, and an incremental "new jobs since last run" monitor. Excludes recruiter personal data by design.

Pricing

$5.00 / 1,000 job results

Rating

0.0

(0)

Developer

Scrape Sage

Scrape Sage

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 hours ago

Last modified

Share

LinkedIn Jobs Scraper — Postings, Salaries & Company Data (No Login)

Extract complete public job data from LinkedIn Jobs — across any keyword, location, seniority, job type, workplace type, salary band and date range. Get the fields that actually matter: job title, company, location, on-site/remote/hybrid, full job description (text + HTML), parsed salary range, applicants count, posting date, seniority, employment type, job function and industries — plus optional company size, industry, follower count, website and HQ on every result.

No login, no cookies, no browser automation — fast direct-from-guest-page extraction with the richest job dataset in the category, and zero recruiter / poster personal data by design.

Why this LinkedIn jobs scraper?

Most LinkedIn job scrapers return a thin row — title, company, a URL — and either leave the rest empty or scrape recruiter personal data that gets the dataset (and you) delisted. This actor pulls LinkedIn's public guest job pages and ships every business field on the posting, deduped and repost-aware, while a hard guard keeps named-individual data out:

DataTypical scrapersThis actor
Title, company, location
On-site / remote / hybridpartial
Full job description (text and HTML)partial
Parsed salary range (min/max/currency/period)
Applicants count
Seniority, employment type, job function, industriespartial✅ all
Posting date (ISO + epoch)partial
Easy-Apply / promoted / repost flags
Cross-search de-duplicationpartial
Company size, industry, followers, website, HQ✅ (optional)
1,000-result-cap workaround (auto-split)
Incremental "new jobs since last run" monitor
Recruiter / job-poster personal data⚠️ often scraped — delisting & legal riskexcluded by design

Use cases

  • Talent sourcing & recruiting intelligence — see who's hiring, for which roles, where, and at what seniority. Filter by keyword, location, experience level or specific companies and build a live map of open roles — without touching any individual's personal data.
  • Job-market & salary intelligence — track asking salaries, demand by role/location/industry, and the remote-vs-on-site mix. The parsed salaryRange turns free-text pay into structured min/max you can chart.
  • Hiring-intent signals for B2B sales — a company opening roles is a growth/budget signal. Pull postings by companyIds, enrich with company size and industry, and prioritize accounts that are expanding. Account-level signal only — no contacts harvested.
  • Job boards, aggregators & ATS tools — feed clean, structured, deduped postings (with full descriptions) straight into your own search app, alerting product or pricing model.
  • Competitor & market monitoring — watch a competitor's open roles, headcount range and follower growth over time to read expansion, freezes and new-market entry.

How to use

  1. Sign up for Apify — the free plan is enough to try this actor.
  2. Open the LinkedIn Jobs Scraper, enter a keyword + location (or paste a LinkedIn jobs search URL), set any filters you want, and click Start.
  3. Watch results stream into the dataset table as each job is parsed.
  4. Export as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the Apify API.

Tip: any LinkedIn jobs search URL works

Open LinkedIn Jobs, set any filters in the UI — keywords, location, date posted, experience level, job type, remote, salary, and so on — then copy the URL from your browser and paste it into searchUrls. The scraper reproduces that exact search and paginates through every page. No need to learn parameters or build URLs by hand.

Input

You can drive the actor two ways: the friendly filter builder (keywords + location + filters) or by pasting LinkedIn search URLs. Mix and match as many searches as you like.

{
"keywords": "software engineer",
"location": "United States",
"datePosted": "pastWeek",
"workplaceType": ["remote", "hybrid"],
"experienceLevel": ["midsenior", "director"],
"salaryBucket": "120k",
"sortBy": "date",
"maxJobs": 500,
"scrapeJobDetails": true,
"scrapeCompanyDetails": true,
"splitByLocation": false,
"incrementalMode": false
}

Core fields:

  • keywords — the job search terms (e.g. software engineer, product manager). Optional if you supply searchUrls.
  • location — free-text place (United States, London, Toronto, ON). Pair with distanceMiles to widen the radius, or set geoId for an exact LinkedIn location.
  • searchUrls — one or more LinkedIn jobs search/listing pages with whatever filters you want, used instead of (or alongside) the builder.
  • datePostedany, pastHour, past24h, pastWeek, pastMonth.
  • workplaceType — any of onsite, remote, hybrid.
  • jobType — any of fulltime, parttime, contract, temporary, internship, volunteer, other.
  • experienceLevel — any of internship, entry, associate, midsenior, director, executive.
  • salaryBucket — minimum-pay floor: any, 40k, 60k, 80k, 100k, 120k, 140k, 160k, 180k, 200k.
  • companyIds — restrict to specific companies by their numeric LinkedIn company IDs.
  • sortByrelevance (default) or date (newest first — best for monitoring).
  • scrapeJobDetails (default true) — open each posting for the full description, salary, applicants, seniority and more. Turn off for a faster, card-only pull.
  • scrapeCompanyDetails (default false) — also fetch each company's size, industry, followers, website and HQ. Adds the eight company* detail fields.
  • maxJobs (prefilled 100) — overall cap across all searches. Clear it (or raise it) for a full pull; the prefill just keeps the example run fast.
  • maxJobsPerSearch — per-search cap, useful when splitting.
  • splitByLocation / splitCountry, splitByDateWindow — the 1,000-cap workarounds (see below).
  • incrementalMode / monitorKey / firstRunLookback — the "only new jobs" monitor (see below).
  • searchConcurrency (default 4) — how many searches run in parallel, each on its own residential IP.
  • proxyConfiguration (default Apify Residential) — required; LinkedIn guest pages block datacenter IPs. Keep the default.

Output

One record per job posting:

{
"id": "4416101000",
"jobId": "4416101000",
"url": "https://www.linkedin.com/jobs/view/4416101000",
"title": "Senior Software Engineer, Backend",
"companyName": "Acme Cloud",
"companyLinkedinUrl": "https://www.linkedin.com/company/acme-cloud",
"companyLogo": "https://media.licdn.com/dms/image/v2/abc123/company-logo_200_200/0/...",
"location": "New York, NY",
"workplaceType": "hybrid",
"employmentType": "Full-time",
"seniorityLevel": "Mid-Senior level",
"experienceLevel": "Mid-Senior level",
"jobFunctions": ["Engineering", "Information Technology"],
"industries": ["Software Development"],
"salary": "$160,000/yr - $210,000/yr",
"salaryRange": { "min": 160000, "max": 210000, "currency": "USD", "period": "year" },
"applicantsCount": 47,
"easyApply": false,
"isPromoted": false,
"isReposted": false,
"postedAt": "2026-06-12T00:00:00.000Z",
"postedAtTimestamp": 1749686400000,
"applyMethod": "offsite",
"jobUrl": "https://www.linkedin.com/jobs/view/4416101000",
"descriptionText": "We're hiring a Senior Backend Engineer to design and scale our event pipeline. You'll own services end to end…",
"descriptionHtml": "<p>We're hiring a <strong>Senior Backend Engineer</strong> to design and scale our event pipeline…</p>",
"companyWebsite": "https://www.acmecloud.com",
"companyDescription": "Acme Cloud builds real-time data infrastructure for modern applications…",
"companySlogan": "Ship data faster.",
"companyEmployeesCount": 1280,
"companyEmployeeCountRange": "1,001-5,000 employees",
"companyIndustries": ["Software Development"],
"companyFollowerCount": 84211,
"companyAddress": { "country": "US", "locality": "New York", "region": "NY", "postalCode": "10001", "street": "100 Example Ave" },
"sourceType": "search",
"sourceQuery": "\"software engineer\" in New York, NY",
"status": "ok",
"statusReason": "",
"scrapedAt": "2026-06-14T01:30:00.000Z"
}

The eight company detail fields (companyWebsite through companyAddress) are included only when scrapeCompanyDetails is on — a default run omits them entirely rather than padding empty columns. Every run also appends one run-summary row (recordType: run-summary) with totals; rows that legitimately have no job carry a plain-English status explaining why, so an empty search reads as a clean result, not a failure.

No personal data. Recruiter, job-poster and hiring-team fields — and any LinkedIn member-profile (/in/) URL, even inside description HTML — are stripped at the single output chokepoint by construction and a defensive guard. The dataset is business and posting data only.

Monitoring — get only new jobs

Turn on incrementalMode and the actor remembers which postings it has already returned for each search (in a persistent key-value store) and, on the next run, outputs only jobs that are new since last time.

This is a pure result filter — the actor still runs once and exits, so it works with, not against, the Apify scheduler:

  1. Set incrementalMode: true, a stable monitorKey (e.g. frontend-remote-us), and sortBy: date.
  2. Use firstRunLookback (past24h / pastWeek / pastMonth) to bound how far back the very first run reaches.
  3. Create an Apify Schedule (e.g. hourly) for the actor.
  4. Add a webhook or Zapier step to push each new posting into your ATS, Slack or a spreadsheet.

A run that finds nothing new finishes as a clean success with zero duplicates — you get a live feed of just-posted roles and nothing you've already seen.

Automate & schedule

Run this actor on autopilot and pull results into your own stack:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });
const run = await client.actor('scrapesage/linkedin-jobs-scraper').call({
keywords: 'software engineer',
location: 'United States',
datePosted: 'pastWeek',
maxJobs: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} job postings`);

Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

  • Make — multi-step automation scenarios.
  • Zapier — push new postings straight into your ATS or CRM.
  • Slack — get notified when a monitored search finds new roles.
  • Google Drive / Sheets — auto-export every run to a spreadsheet.
  • Airbyte — pipe results into your data warehouse.
  • GitHub — trigger runs from commits or releases.

Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. You can call this actor from Claude, ChatGPT, or any agent framework through the Apify MCP server — ask your assistant to "find remote senior software engineer roles posted in the last week in the US and summarize the salary ranges" and let it run this scraper for you.

More scrapers from scrapesage

Build a complete market-intelligence and lead-gen data stack:

Tips

  • Exhaust a big search: LinkedIn caps guest search at ~1,000 results. To pull a large market fully, turn on splitByLocation (with splitCountry) to fan a country out into cities, or splitByDateWindow to slice by time — each sub-search paginates independently and runs in parallel on its own IP, multiplying what you can reach.
  • Cheapest, freshest feed: combine sortBy: date + incrementalMode + an hourly Schedule so each run scrapes only the handful of brand-new postings.
  • Keep the residential proxy: LinkedIn guest pages block datacenter IPs; the default Apify Residential proxy is required.
  • Structured pay: read salaryRange (min/max/currency/period) for analysis and keep the raw salary string for display — the parser recovers ranges from free-text descriptions and corrects misread hourly/annual values.
  • Skip the detail fetch for a quick inventory: set scrapeJobDetails: false to list cards fast, then re-run with details on the slice you care about.

FAQ

Which jobs does it cover? Any public LinkedIn job search — every keyword, location, seniority, job type, workplace type, salary band and date range, via either the filter builder or a pasted search URL.

Do I need to learn URL parameters? No. Apply filters on LinkedIn normally and paste the resulting URL into searchUrls, or just use the keyword/location/filter inputs. The scraper mirrors your search exactly.

Does it scrape recruiter or applicant personal data? No — and it can't. Job-poster, recruiter and hiring-team fields, plus any member-profile (/in/) URL, are removed at the only point where records are built, with a defensive guard as backstop. You get business and posting data only, which keeps the dataset compliant and delisting-safe.

Where does the salary come from? From the posting itself. When LinkedIn shows pay, the actor keeps the raw text in salary and parses a structured salaryRange; when a posting omits pay, both are null.

How do I get only new jobs? Turn on incrementalMode with a stable monitorKey and sort by date, then schedule the actor. Each run outputs only postings not seen on previous runs — no duplicates.

Can I export to Google Sheets, CSV, or Excel? Yes — one click in the dataset view, or automatically on every run via the Google Drive integration.

Is scraping LinkedIn legal? This actor collects publicly available job-posting data only and excludes personal data by design. You are responsible for using the data in compliance with applicable laws and LinkedIn's terms.

A field is null — why? Some postings genuinely omit a value (no listed salary, no applicants count, a company that hides its size). Fields are null only when the data isn't published, never because the scraper skipped them. Company detail fields are absent (not null) unless scrapeCompanyDetails is on.

A search returned fewer than I expected. LinkedIn's ~1,000-result guest cap is per search — split by location or date window to go deeper. Any empty or capped run still finishes as a success with a status explaining exactly what happened.

Need help?

Open an issue on the actor's Issues tab, or visit the Apify help center. Feature requests are welcome — this actor is actively maintained.