LinkedIn Search Jobs Scraper With Advanced Search Filters avatar

LinkedIn Search Jobs Scraper With Advanced Search Filters

Pricing

from $2.99 / 1,000 results

Go to Apify Store
LinkedIn Search Jobs Scraper With Advanced Search Filters

LinkedIn Search Jobs Scraper With Advanced Search Filters

LinkedIn Search Jobs Scraper retrieves job listings from LinkedIn based on keywords, location, filters, and seniority. It extracts titles, companies, descriptions, employment types, and posting dates, delivering clean, structured data for recruiting, research, and market analysis

Pricing

from $2.99 / 1,000 results

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

6

Total users

2

Monthly active users

4 days ago

Last modified

Share

LinkedIn Jobs Scraper — Salary, Location and Advanced Filters

This LinkedIn jobs scraper returns structured job listings from LinkedIn's public job search — job title, company, location, posted time, applicant count, full description, and LinkedIn's own criteria tags (seniority, employment type, job function, industries) — as clean JSON, ready for a dataset export. Search by keyword and location, by a company profile URL, or by a direct job link, then narrow results with LinkedIn's native workplace-type, experience-level, employment-type, date-posted and minimum-salary facets. Built for recruiters, sales teams tracking hiring signals, and labour-market researchers who need a filtered job feed instead of a raw, unfiltered results page.

What is LinkedIn Jobs Scraper — Salary, Location and Advanced Filters?

It is a LinkedIn job search scraper that reads LinkedIn's public, no-login job search and job-detail pages and returns each job listing as a structured JSON record. No LinkedIn account or login is required — every page it reads is served to logged-out visitors.

  • Discovers listings by free-text keyword + location, by pasting a full LinkedIn job-search URL, by a company profile URL, or by a direct job URL/ID
  • Returns the core identifying fields for every listing — title, company, location, and both a company link and a job link
  • Pulls LinkedIn's own job-criteria tags (seniority level, employment type, job function, industries) plus posted time and applicant count
  • Narrows results with five of LinkedIn's own native search facets: workplace type, experience level, employment type, date posted, and minimum salary band
  • Resolves company profile URLs to LinkedIn's real numeric organization ID before filtering, instead of passing the URL slug straight through
  • Exports everything as a structured Apify dataset (JSON, CSV, Excel, XML, or via the Apify API)

What data can I extract with LinkedIn Jobs Scraper?

Every field below is written by the actor's job-scraping function (scrape_single_job in src/main.py) into each dataset row.

FieldExample valueUse case
id"3812456789"Unique LinkedIn job ID, used for de-duplication
title"Senior Backend Engineer"Role matching, keyword filtering
company"Notion"Employer identification
location"San Francisco, CA"Geographic filtering downstream
postedTimeAgo"3 days ago"Freshness / recency sorting
numberOfApplicants"200 applicants"Competition signal for the role
description"We're looking for a Senior Backend Engineer to..."Full-text search, requirement extraction
criteria[{"title":"Seniority level","value":"Mid-Senior level"},{"title":"Employment type","value":"Full-time"}]LinkedIn's own published job-criteria tags
appliedFilters{"workplaceType":["remote"],"experienceLevel":null,"employmentType":["full_time"],"datePosted":"past_week","minSalaryBand":"$120000+"}Echoes which native facets this run applied
companyOrgId"1234567"Resolved numeric LinkedIn organization ID, if the input was a company URL
resolvedGeoId"103644278"Resolved LinkedIn geoId, if a location was supplied
link"https://www.linkedin.com/company/notion"Company profile link
job{"id":"3812456789","link":"https://www.linkedin.com/jobs/view/senior-backend-engineer-at-notion-3812456789","title":"Senior Backend Engineer","company":"Notion","location":"San Francisco, CA"}Nested copy of the job with a slugged permalink
scrapedAt"2026-08-04T12:00:00.000Z"Run auditing, freshness checks

Decision-driving data: criteria, applicants and posting age

The criteria array carries the same tags LinkedIn itself displays on the job page — typically seniority level, employment type, job function and industries — so you can segment results without re-parsing the description. Combine numberOfApplicants with postedTimeAgo to spot roles that are both fresh and low-competition, a common recruiter and job-seeker workflow. appliedFilters is a record-keeping echo of the facets your run actually applied, not a field parsed from the listing — useful when auditing which rows came from which filter combination in a bulk run.

Targeting data: location, company ID and native facet codes

location is the free-text location LinkedIn shows on the listing; resolvedGeoId is the internal numeric ID the actor resolved for it, useful for matching against other LinkedIn geoId-based datasets. companyOrgId is the numeric organization ID resolved from a company profile URL — the field that makes company-scoped search actually work. Together with the five facet inputs (workplace type, experience level, employment type, date posted, minimum salary band), these are the fields you filter and segment on.

Why not build this yourself?

LinkedIn's job search has no public, self-serve API for arbitrary keyword or company queries — LinkedIn's Talent Solutions APIs require a partner agreement, not a signup form. Building this by hand means solving the same problems this actor already handles: paginating LinkedIn's guest search endpoint page by page, encoding five different native facet parameters (f_WT, f_E, f_JT, f_TPR, f_SB2) into the right comma-joined codes, warming up a session before the very first request (LinkedIn's anti-bot layer scrutinizes a cold session's first hit more than later ones), retrying on 429/999 responses with backoff, and resolving a company URL slug to LinkedIn's real numeric organization ID by scraping the company's own profile page for its urn:li:organization:<id> string.

Build it yourself if you need a single one-off search you can run by hand in a browser. Use this actor when you need repeatable, filtered, structured exports across many search terms, locations or companies without maintaining the scraping and anti-bot logic yourself.

🎯 Recruiters and talent sourcing teams

Feed a list of startUrls combining role keywords and target locations, add experienceLevel: ["mid_senior"] and datePosted: "past_week" to surface fresh, relevant openings, then pull title, company, location and job.link into a sourcing tracker. numberOfApplicants helps triage which fresh postings still have a low-competition window.

📊 Sales teams tracking hiring signals

Run recurring searches on employmentType: ["full_time"] plus a keyword like "data engineer" across a watch-list of company URLs to catch which target accounts are actively hiring for roles that signal budget or a new initiative — a standard trigger event for outbound sales and account-based marketing.

🔬 Labour-market researchers and analysts

Compare workplaceType, minSalaryBand and location distributions across a metro area or industry to track how remote-vs-onsite mix or posted salary floors shift over time, using datePosted windows to build week-over-week snapshots.

🤖 AI agents and automated pipelines

Call the actor as a tool inside a job-matching agent or career-assistant RAG pipeline: pass a candidate's keywords and location, apply experienceLevel and minSalaryBand as hard constraints, and feed the returned description and criteria fields to an LLM for fit-scoring — no browser automation required on the agent's side.

🔼 Input sample

ParameterRequiredTypeDescriptionExample value
startUrlsYesarrayLinkedIn job search URLs, keywords, a company profile URL, or "keywords, location" strings. One item per line; filters below apply to every item.["software engineer, United States"]
sortOrderNostring (enum: relevant, recent; default relevant)Sort by most relevant or most recent."recent"
maxJobsNointeger (min 1, max 10000, default 10)Max jobs to scrape per input line. Real delivery per input is capped at roughly 1,000 jobs by LinkedIn's own search pagination depth.50
workplaceTypeNoarray (enum items: on_site, remote, hybrid; default [])LinkedIn's native workplace-type facet. Empty = no restriction.["remote", "hybrid"]
experienceLevelNoarray (enum items: internship, entry, associate, mid_senior, director; default [])LinkedIn's native experience-level facet. Empty = no restriction.["mid_senior"]
employmentTypeNoarray (enum items: full_time, part_time, contract, temporary, volunteer; default [])LinkedIn's native employment-type facet. Empty = no restriction.["full_time"]
datePostedNostring (enum: any, past_24h, past_week, past_month; default any)LinkedIn's native date-posted facet."past_week"
minSalaryBandNostring (enum: any, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 180000, 200000; default any)LinkedIn's native minimum annual salary (USD) facet. Coverage depends on how many results carry LinkedIn's own estimated or employer-provided salary data."120000"
proxyConfigurationNoobjectOptional Apify Proxy config. Runs with direct requests by default; enable proxy only if requests get blocked.{"useApifyProxy": true}
{
"startUrls": [
"software engineer, United States",
"https://www.linkedin.com/company/notion"
],
"sortOrder": "recent",
"maxJobs": 50,
"workplaceType": ["remote"],
"experienceLevel": ["mid_senior"],
"employmentType": ["full_time"],
"datePosted": "past_week",
"minSalaryBand": "120000",
"proxyConfiguration": {
"useApifyProxy": false
}
}

Common pitfall: maxJobs applies per line in startUrls, not to the whole run — five input lines at maxJobs: 1000 can deliver up to 5,000 jobs total, not 1,000. Also, a direct job URL/ID input is scraped as a single listing: it ignores maxJobs and the five facet filters entirely (they're still recorded in that row's appliedFilters for consistency, but none of them affect a single-job fetch).

🔽 Output sample

Every listing is pushed to the Apify dataset the moment it's scraped (live saving), as typed, normalized JSON with a consistent schema across runs. Export it as JSON, CSV, Excel, XML, or via the Apify API/apify_client.

{
"id": "3812456789",
"criteria": [
{ "title": "Seniority level", "value": "Mid-Senior level" },
{ "title": "Employment type", "value": "Full-time" },
{ "title": "Job function", "value": "Engineering" },
{ "title": "Industries", "value": "Software Development" }
],
"company": "Notion",
"location": "San Francisco, CA",
"title": "Senior Backend Engineer",
"link": "https://www.linkedin.com/company/notion",
"postedTimeAgo": "3 days ago",
"numberOfApplicants": "200 applicants",
"description": "We're looking for a Senior Backend Engineer to join our infrastructure team...",
"appliedFilters": {
"workplaceType": ["remote"],
"experienceLevel": ["mid_senior"],
"employmentType": ["full_time"],
"datePosted": "past_week",
"minSalaryBand": "$120000+"
},
"companyOrgId": "1234567",
"resolvedGeoId": null,
"job": {
"id": "3812456789",
"link": "https://www.linkedin.com/jobs/view/senior-backend-engineer-at-notion-3812456789",
"title": "Senior Backend Engineer",
"company": "Notion",
"location": "San Francisco, CA"
},
"scrapedAt": "2026-08-04T12:00:00.000Z"
}

Note: the actor does not extract a standalone parsed salary figure into its own field. minSalaryBand narrows the search to postings LinkedIn itself classifies as meeting that floor; the number, if disclosed, appears inside the free-text description rather than a dedicated salary key.

How do you filter and target specific job listings?

This actor's five native facet filters are combinable and apply to every line in startUrls, so the precision comes from stacking them rather than post-filtering a broad result set yourself.

  1. Free-text query vs. company URL — a "keywords, location" string searches LinkedIn's general job index; a linkedin.com/company/<slug> URL scopes the search to one employer by resolving its real numeric organization ID first, so you get that company's own postings instead of an unrelated firehose.
  2. Scope precisionlocation text in a "keywords, location" input is resolved to LinkedIn's internal geoId automatically, pinning the search to LinkedIn's own geographic entity rather than relying on fuzzy text matching alone.
  3. Facet narrowingworkplaceType, experienceLevel and employmentType are each multi-select arrays (OR'd within a facet, AND'd across facets), and datePosted/minSalaryBand add recency and compensation floors on top.
  4. Volume controlmaxJobs (1–10,000) caps how many listings to pull per input line, but LinkedIn's own guest search pagination depth caps real delivery at roughly 1,000 per line regardless of how high maxJobs is set.
{ "startUrls": ["product manager, Berlin, Germany"], "workplaceType": ["remote"], "experienceLevel": ["mid_senior", "director"], "minSalaryBand": "100000" }
{ "startUrls": ["https://www.linkedin.com/company/stripe"], "employmentType": ["full_time", "contract"], "datePosted": "past_month" }
{ "startUrls": ["data analyst, remote"], "datePosted": "past_24h", "sortOrder": "recent", "maxJobs": 25 }

▶️ Want to try other LinkedIn scrapers?

ScraperWhat it extracts
LinkedIn Profile Post Scraper (media & hashtag)LinkedIn profile posts filtered by media type and hashtag
Google Maps Extractor (reservation/order links)Local business listings with reviews and booking links
Tripadvisor Review Scraper (photo & visual filters)Hotel/attraction reviews with photo and rating filters
Otomoto.pl Scraper (dealer contact leads)Vehicle marketplace listings with dealer contact data

How to extract LinkedIn job data programmatically

This actor runs as a standard Apify Actor: one API call starts the run, and structured JSON comes back from the dataset — no LinkedIn login, cookies, or browser session to manage on your side.

Python example

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run_input = {
"startUrls": ["backend engineer, remote"],
"workplaceType": ["remote"],
"datePosted": "past_week",
"maxJobs": 100,
}
run = client.actor("<your-username>/linkedin-search-jobs-scraper-with-advanced-search-filters").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["company"], item["location"])

Export to spreadsheets or CRM

Use the Apify Console's "Export dataset" button, or the API's dataset export endpoint, to download results as CSV or Excel. Map title → Job Title, company → Company, location → Location, and job.link → Job URL when importing into a spreadsheet or CRM lead list.

Yes. LinkedIn job postings are public business content — employers publish them specifically so job seekers, recruiters and search engines can find them, and this actor reads only the same logged-out, publicly served pages any visitor's browser can load. Job listings are business/recruiting data (title, employer, location, description, criteria), not personal data about identifiable individuals, so this falls under LinkedIn's own Terms of Service and general database-rights considerations rather than GDPR/CCPA personal-data rules. If a job description happens to include a named individual's contact details, treat that incidental text with ordinary care. Consult legal counsel for commercial applications involving bulk storage or resale of scraped data.

❓ FAQ

Does the output flag jobs that have expired or been removed?

No, there is no separate "expired" flag. If a listing has been taken down, the detail-page scrape returns no title or company, and the actor silently skips that row rather than pushing an incomplete or empty record — so expired postings simply don't appear in your dataset, and you are not charged for them.

Can I get salary data along with the job listings?

Partially. minSalaryBand lets you filter to postings LinkedIn classifies as meeting a given annual floor, and the returned criteria and description fields may show pay details when the employer disclosed them on the page — but the actor does not parse a number into its own salary field. Coverage of salary data depends entirely on how many of LinkedIn's own postings in your result set carry LinkedIn-estimated or employer-provided pay data.

How accurate is the job data?

The actor returns each field exactly as it appears on the public LinkedIn job page at request time. Accuracy after that depends on how current the employer or LinkedIn kept the listing — always re-verify time-sensitive fields like numberOfApplicants and postedTimeAgo before using them in a live workflow.

How many job listings can I get per run?

maxJobs accepts 1 to 10,000, but it applies per line in startUrls, and real delivery per line is capped at roughly 1,000 jobs by LinkedIn's own guest-search pagination depth — the actor stops paginating once it runs out of new listings or hits that ceiling, whichever comes first. A run with multiple startUrls lines can still return well beyond 1,000 jobs in total.

How does the company-URL filter work, and why does it matter?

Pass a linkedin.com/company/<slug> URL in startUrls and the actor first scrapes that company's own profile page to resolve its real numeric LinkedIn organization ID, then uses that ID (not the URL slug) to scope the job search. This matters because LinkedIn's search silently ignores a slug passed directly as the company filter and returns an unrelated firehose of jobs instead of an error — a bug that also affects a f_C value pasted in from a raw search URL, which this actor detects and re-resolves the same way.

Does this scraper work with Claude, ChatGPT, and AI agent frameworks?

There is no dedicated MCP server for this actor. It is callable as a standard Apify Actor run via the Apify API or apify_client from any Python, JavaScript, or HTTP-capable agent framework, making its structured job output straightforward to wire into a custom tool call.

Can I use this without a LinkedIn account or API key?

Yes. The actor reads LinkedIn's logged-out, publicly served job search and job-detail pages, so no LinkedIn login, cookies, or developer account is required. You only need an Apify account and API token to run the actor itself.

Do I need to enable the proxy?

No, not by default — the actor runs with direct requests unless you turn on proxyConfiguration.useApifyProxy. Enable it only if you start seeing repeated 429/blocked responses in the run log; proxy usage may consume additional credits.

Conclusion

This actor turns LinkedIn's public job search into structured, filterable JSON — using LinkedIn's own native workplace, experience, employment, date-posted and salary facets, plus a working fix for company-scoped search that a URL slug alone can't deliver. It suits recruiters sourcing candidates, sales teams tracking hiring signals, and researchers or agents that need repeatable, structured job data without maintaining pagination and anti-bot logic themselves. Set your startUrls and facet filters and run it from the Apify Console or API to get your first filtered export.