Use LinkedIn Job Listings with Salary & Company Data Scraper with Python
Collect LinkedIn job postings by keyword, location, or search URL, with parsed salary ranges, visa-sponsorship signals, and enriched employer profiles. No login required.
1. Choose the data you need
Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.
2. Prepare a source-based input
This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.
{
"easyApply": false,
"excludeStaffingAgencies": false,
"includeCompanyDetails": false,
"locations": [
"United States"
],
"maxItems": 3,
"requireRecruiter": false,
"requireSalary": false,
"scrapeJobDetails": false,
"searchQueries": [
"software engineer"
],
"splitLargeSearches": true,
"under10Applicants": false
}
Download input.example.json and save your reviewed copy as input.json.
| Field | Type | Required | Description |
|---|---|---|---|
searchQueries | array | optional | Job titles, skills or phrases to search for, one per line (e.g. 'data analyst', 'registered nurse'). Each keyword is searched in every location you list, and results are merged without duplicates. |
searchUrls | array | optional | Paste job search links copied from LinkedIn (linkedin.com/jobs/search/?...). The keywords, location and filters inside each link are kept. |
jobUrls | array | optional | Scrape specific job postings: paste job links (linkedin.com/jobs/view/...) or numeric job IDs. Postings that have been taken down are skipped. |
locations | array | optional | Cities, regions or countries in English (e.g. 'Germany', 'Austin, Texas', 'London Area, United Kingdom'). Every keyword is searched in each location. A location LinkedIn doesn't recognise is reported and skipped rather than silently searched as the United States. Leave empty to search worldwide. |
geoIds | array | optional | Optional numeric LinkedIn location IDs (the geoId value in a LinkedIn search link, e.g. 101282230 for Germany). Use these for exact places in any language. |
distance | string | optional | Search radius around a city-level location, in miles. |
timePosted | string | optional | Only jobs posted (or reposted) within this period. |
companies | array | optional | Only jobs from these employers. Enter company names (e.g. 'General Motors'), LinkedIn company or university page links, or numeric company IDs. Leave the keywords empty to get all of a company's open jobs. |
excludeCompanies | array | optional | Skip jobs from these employers (exact company name or LinkedIn company page link). |
easyApply | boolean | optional | Only jobs you can apply to directly on LinkedIn. |
under10Applicants | boolean | optional | Only jobs that have had fewer than 10 applicants so far. |
experienceLevel | string | optional | Only jobs listed at this seniority level on LinkedIn. Jobs that LinkedIn lists as 'Not Applicable' are left out when a level is chosen. |
jobType | string | optional | Only jobs with this employment type. |
industry | array | optional | Only jobs from employers in these LinkedIn industries. |
companySizes | array | optional | Only jobs from employers of these sizes, as listed on their LinkedIn page. Each employer's page is looked up once. Jobs whose employer size isn't listed are kept. |
excludeStaffingAgencies | boolean | optional | Skip jobs posted by employers in LinkedIn's 'Staffing and Recruiting' industry. |
requireSalary | boolean | optional | Only jobs that state their pay, either in LinkedIn's pay range box or in the job description. |
minYearlySalary | integer | optional | Skip jobs whose stated pay range tops out below this yearly amount. Hourly, weekly and monthly pay is converted to a yearly figure. The amount is compared in the job's own currency, so set 'Salary currency' to compare like with like. Jobs without a stated salary are kept unless 'Only jobs with a salary' is on. |
salaryCurrency | string | optional | Only jobs whose stated pay is in this currency. Also sets the currency of 'Minimum yearly salary'. Jobs without a stated salary are kept unless 'Only jobs with a salary' is on. |
requireRecruiter | boolean | optional | Only jobs where LinkedIn shows the person who posted the job. |
includeTitleKeywords | array | optional | Keep only jobs whose title contains at least one of these words (not case-sensitive). Useful because LinkedIn's keyword matching is broad. |
excludeTitleKeywords | array | optional | Skip jobs whose title contains any of these words, e.g. 'Senior' or 'Intern'. |
excludeJobIds | array | optional | Job IDs (the 'id' field of an earlier run) to leave out, so scheduled runs return only new postings. |
scrapeJobDetails | boolean | optional | Open each job to add the full description, salary, seniority, job type, industry, applicant count, recruiter and Easy Apply status. Turn off for a fast list of titles, companies, locations and dates only. Filters that need these details switch it on automatically. |
includeCompanyDetails | boolean | optional | Add each employer's LinkedIn profile: industry, size, headquarters, website, founding year, office locations, followers, tagline and description. Fetched once per company. |
enrichmentDepth | string | optional | Standard returns each job's core details. Extended also adds similar jobs, 'people also viewed' jobs, related searches and LinkedIn's numeric industry and title IDs, and asks LinkedIn again when the exact posting time is missing, so it takes longer per job. |
language | string | optional | Language LinkedIn uses for labels such as job type and seniority. Job descriptions stay in the language they were written in. Locations must still be typed in English. |
splitLargeSearches | boolean | optional | LinkedIn returns at most 1,000 jobs for one search. When a search reaches that limit, continue with the same search limited to the past month, week, 3 days and 24 hours, which surfaces many more jobs (duplicates removed). |
maxItems | integer | optional | Stop after saving this many jobs. A single keyword + location search returns at most 1,000 jobs; add keywords or locations to collect more. |
3. Start an Actor run
Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.
Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.
import json
import os
import urllib.request
# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
actor_input = json.load(stream)
token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
"https://api.apify.com/v2/acts/YBSMvzqGpJzFJ99qo/runs?timeout=120&maxTotalChargeUsd=0.50",
data=json.dumps(actor_input).encode("utf-8"),
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.
4. Inspect the actual results
Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.
LinkedIn job postings with parsed yearly salary ranges and their source, applicant counts, Easy Apply status, seniority, posting expiry dates when LinkedIn exposes them, recruiter, and the employer's LinkedIn profile (size, industry, founding year, offices).
Questions before you run
Which inputs are required?
No top-level fields are marked required in the published schema. Conditional requirements can still apply; check the README.
What does this guide verify?
The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.
What if the run request times out?
Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.
Generated from source build 7ypXd8icrntihghOf and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.