LinkedIn Jobs Scraper – No Login avatar

LinkedIn Jobs Scraper – No Login

Pricing

$0.60 / 1,000 scraped jobs

Go to Apify Store
LinkedIn Jobs Scraper – No Login

LinkedIn Jobs Scraper – No Login

Scrape public LinkedIn jobs by keyword and location. Filter by date, job type, experience, workplace, Easy Apply, or under 10 applicants. Extract company, salary, applicant count, seniority, employment type, description, and job URL when available.

Pricing

$0.60 / 1,000 scraped jobs

Rating

0.0

(0)

Developer

DataScraperES

DataScraperES

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Run the Actor on Apify

Search public LinkedIn job listings by keyword and location and export one structured dataset item per unique job. Use filters for publication date, employment type, experience level, workplace type, Easy Apply, and jobs shown with fewer than 10 applicants.

The Actor can return lightweight search-card data or visit each public job page to add the full description, applicant text, seniority, employment type, job function, and industries.

What can you use it for?

  • Build or refresh a job board.
  • Monitor which roles competitors are hiring for.
  • Track remote, hybrid, or on-site demand by market.
  • Analyze salary, seniority, and employment-type trends.
  • Find newly published roles for recruiting or job-search workflows.
  • Send fresh job listings to a spreadsheet, database, CRM, webhook, or automation.

What data can you collect?

Each result can contain:

  • LinkedIn job ID and public job URL
  • Job title and location
  • Company name, LinkedIn company page, and logo
  • Publication date and relative posting age
  • Salary text when LinkedIn displays it
  • Applicant text when publicly available
  • Full public job description
  • Seniority level and employment type
  • Job function and industries
  • The keyword and location that discovered the job
  • Detail status and request metadata for transparent quality checks

Field availability depends on what LinkedIn publishes for each job. Missing optional values are returned as null; the Actor does not invent unavailable data.

Pricing

The Actor costs $0.0006 per unique job written to the dataset, equivalent to $0.60 per 1,000 jobs.

Dataset resultsPrice
25$0.015
100$0.06
500$0.30
1,000$0.60
5,000$3.00

There is no Actor start fee. You are not charged for duplicate jobs, retries, failed search requests, or searches that produce no dataset items.

A valid job card is still a billable result when optional detail fields cannot be recovered. In that case, the item is saved with status: "partial" and a detailStatus explaining which optional detail request failed.

Quick start

  1. Open the Actor's Input tab.
  2. Add one or more job-search keywords.
  3. Enter a location such as Spain, Madrid, United States, or Worldwide.
  4. Choose the maximum number of jobs for each keyword.
  5. Add optional filters.
  6. Keep Fetch full job details enabled when you need descriptions and job criteria.
  7. Click Start.
  8. Open the run's Dataset to preview or download the results.

No proxy, LinkedIn account, or cookie configuration is required from the user.

Input reference

FieldTypeRequiredDefaultDescription
keywordsstring arrayYesOne independent search per keyword. Accepts 1–50 unique values.
locationstringYesFree-text location understood by LinkedIn, such as a country, city, region, or Worldwide.
geoIdstringNoEmptyNumeric LinkedIn geographic ID. Use it when you need more exact geographic targeting.
maxItemsPerQueryintegerNo25Maximum jobs collected for each keyword, from 1 to 1,000. This is a limit, not a guaranteed result count.
datePostedstringNoanyPublication-age filter: any, past24Hours, pastWeek, or pastMonth.
jobTypesstring arrayNoAllFilter by full-time, part-time, contract, temporary, volunteer, internship, or other.
experienceLevelsstring arrayNoAllFilter from internship through executive level.
workplaceTypesstring arrayNoAllFilter by on-site, remote, or hybrid work.
easyApplyOnlybooleanNofalseReturn only jobs marked with LinkedIn Easy Apply.
under10ApplicantsOnlybooleanNofalseReturn only jobs shown as having fewer than 10 applicants.
includeJobDetailsbooleanNotrueFetch each public detail page. Disable it for faster search-card-only collection.

Accepted filter values

jobTypes:

fullTime, partTime, contract, temporary, volunteer, internship, other

experienceLevels:

internship, entryLevel, associate, midSenior, director, executive

workplaceTypes:

onSite, remote, hybrid

Input examples

Collect up to 25 software engineering jobs in Spain with full details:

{
"keywords": ["software engineer"],
"location": "Spain",
"maxItemsPerQuery": 25,
"includeJobDetails": true
}

Recent remote and hybrid jobs

Search two roles and keep jobs posted during the past week:

{
"keywords": ["data engineer", "analytics engineer"],
"location": "Europe",
"maxItemsPerQuery": 100,
"datePosted": "pastWeek",
"jobTypes": ["fullTime", "contract"],
"experienceLevels": ["associate", "midSenior"],
"workplaceTypes": ["remote", "hybrid"],
"includeJobDetails": true
}

Easy Apply with fewer applicants

{
"keywords": ["SEO specialist"],
"location": "Madrid, Spain",
"maxItemsPerQuery": 50,
"datePosted": "past24Hours",
"easyApplyOnly": true,
"under10ApplicantsOnly": true,
"includeJobDetails": true
}

Faster card-only collection

Disable job details when you only need job discovery fields such as title, company, location, posting date, salary text, and URL:

{
"keywords": ["product manager", "project manager"],
"location": "United States",
"maxItemsPerQuery": 250,
"datePosted": "pastMonth",
"includeJobDetails": false
}

With includeJobDetails: false, these fields normally remain null: applicantsText, descriptionText, seniorityLevel, employmentType, jobFunction, and industries.

How limits and duplicates work

maxItemsPerQuery applies separately to every keyword. For example, three keywords with maxItemsPerQuery: 100 can inspect up to 300 job cards.

The final number can be lower because:

  • LinkedIn returned fewer matching public jobs.
  • The selected filters narrowed the search.
  • The same job appeared under multiple keywords.
  • A public search page was temporarily unavailable.

Jobs are deduplicated by LinkedIn job ID across the entire run. When the same job matches multiple keywords, it is written once and keeps the first searchKeyword that discovered it.

Output example

Each dataset item represents one unique LinkedIn job:

{
"success": true,
"status": "success",
"searchKeyword": "software engineer",
"searchLocation": "Spain",
"jobId": "1234567890",
"jobUrl": "https://www.linkedin.com/jobs/view/1234567890",
"title": "Software Engineer",
"companyName": "Example Corp",
"companyUrl": "https://www.linkedin.com/company/example",
"companyLogoUrl": "https://media.licdn.com/example-logo.png",
"location": "Madrid, Spain",
"postedDate": "2026-07-12",
"postedText": "1 day ago",
"salary": null,
"applicantsText": "47 applicants",
"descriptionText": "Build and maintain reliable services...",
"seniorityLevel": "Mid-Senior level",
"employmentType": "Full-time",
"jobFunction": "Engineering and Information Technology",
"industries": "Software Development",
"criteria": {
"seniorityLevel": "Mid-Senior level",
"employmentType": "Full-time"
},
"detailStatus": "success",
"detailHttpStatus": 200,
"detailAttempts": 1,
"scrapedAt": "2026-07-13T12:00:00Z"
}

Output field reference

FieldDescription
successtrue when all requested data for the item was collected successfully.
statussuccess or partial.
searchKeywordFirst keyword that discovered the job.
searchLocationLocation supplied in the Actor input.
jobIdLinkedIn's unique job identifier.
jobUrlCanonical public LinkedIn job URL.
titleJob title.
companyNameHiring company name.
companyUrlPublic LinkedIn company page when available.
companyLogoUrlCompany logo URL when available.
locationJob location displayed by LinkedIn.
postedDateParsed publication date when available.
postedTextRelative posting age, for example 1 day ago.
salaryPublic salary text when shown on the search card.
applicantsTextPublic applicant text from the job detail page.
descriptionTextFull public job description as plain text.
seniorityLevelLinkedIn seniority criterion.
employmentTypeFull-time, part-time, contract, internship, or another published type.
jobFunctionPublished job function.
industriesPublished industry information.
criteriaAll parsed job criteria as key-value pairs.
detailStatusResult of the optional job-detail request.
detailHttpStatusHTTP status returned by the detail request when available.
detailAttemptsNumber of attempts used for the detail request.
scrapedAtUTC timestamp when the item was created.

The external application destination is not guaranteed because LinkedIn does not consistently expose it in public job responses. jobUrl always points to the public LinkedIn job posting.

Understanding result status

  • status: "success": the requested result was collected successfully.
  • status: "partial": the valid search card was saved, but the optional detail page did not recover after bounded retries.
  • detailStatus: "not_requested": includeJobDetails was disabled.
  • detailStatus: "success": the public detail page was fetched and parsed.
  • Other detailStatus values identify temporary blocking, rate limiting, network failure, an unavailable job, an upstream error, or an unrecognized response.

Partial results retain the core job fields and can still be useful in job-discovery pipelines.

Downloading and integrating results

Open the run's Dataset tab to preview the results. Apify can export the dataset as JSON, JSONL, CSV, Excel, XML, RSS, or an HTML table.

The Actor output also provides:

  • results: API URL for the default dataset items.
  • summary: API URL for the non-sensitive SUMMARY record.

The summary contains query counts, output totals, successful and partial item counts, skipped duplicates, pagination totals, retries, and total duration.

Run with the Apify API

Replace YOUR_APIFY_TOKEN and the example input values as needed.

cURL

Run the Actor synchronously and return its dataset items:

curl -X POST \
"https://api.apify.com/v2/acts/datascraperes~linkedin-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"keywords": ["software engineer"],
"location": "Spain",
"maxItemsPerQuery": 25,
"datePosted": "pastWeek",
"includeJobDetails": true
}'

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datascraperes/linkedin-jobs-scraper").call(
run_input={
"keywords": ["software engineer", "data engineer"],
"location": "Spain",
"maxItemsPerQuery": 50,
"datePosted": "pastWeek",
"workplaceTypes": ["remote", "hybrid"],
"includeJobDetails": True,
}
)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], job["companyName"], job["jobUrl"])

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('datascraperes/linkedin-jobs-scraper').call({
keywords: ['software engineer', 'data engineer'],
location: 'Spain',
maxItemsPerQuery: 50,
datePosted: 'pastWeek',
workplaceTypes: ['remote', 'hybrid'],
includeJobDetails: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const job of items) {
console.log(job.title, job.companyName, job.jobUrl);
}

Apify CLI

Save your input as input.json, then run:

apify actors call datascraperes/linkedin-jobs-scraper \
--input-file input.json \
--output-dataset

The Actor's API tab in Apify Store also generates ready-to-run examples for the current Actor version.

Scheduling recurring searches

Use an Apify Schedule when you need fresh jobs every hour, day, or week:

  1. Save the desired Actor input as a Task.
  2. Create a Schedule for that Task.
  3. Use past24Hours or pastWeek to focus on fresh listings.
  4. Send completed-run results through a webhook or an Apify integration.
  5. Deduplicate across scheduled runs in your destination using jobId.

Deduplication inside the Actor applies to one run and its resurrection. Separate scheduled runs use separate datasets, so persistent monitoring systems should keep previously seen jobId values in their own database or automation.

Reliability and resuming runs

The Actor uses controlled concurrency, request pacing, retries with backoff, fresh proxy sessions after transient failures, pagination safety limits, and deduplication by job ID.

If an Apify run is resurrected with the same input, it restores its saved progress and avoids writing completed jobs again. Changing the input creates a new progress fingerprint and starts a new search.

Tips for better results

  • Use specific keywords such as senior React developer instead of a broad term such as developer.
  • Run separate searches for important title variations.
  • Use a precise location or geoId when the free-text location is ambiguous.
  • Use past24Hours or pastWeek for recurring monitoring.
  • Disable includeJobDetails when you only need discovery fields and want a faster run.
  • Keep full details enabled when descriptions, applicant text, seniority, job function, or industries are required.
  • Remember that salary and applicant information are not published for every job.

Troubleshooting

SituationExplanation and action
No resultsBroaden the keyword, location, or date filters and confirm that the same search has public LinkedIn results.
Fewer jobs than requestedmaxItemsPerQuery is a maximum. LinkedIn may expose fewer jobs, and duplicates are removed.
Some fields are nullThe employer or LinkedIn did not publish those optional fields, or full details were disabled.
Results have status: "partial"The core job card is valid, but an optional detail request failed after retries. Check detailStatus.
The run reports failed queriesReview the SUMMARY record. Retry later or split a large multi-keyword input into smaller runs.
Results repeat across scheduled runsDeduplicate in your destination using jobId; each scheduled run has its own dataset.
Location is inaccurateUse the full location name or provide a numeric LinkedIn geoId.
The input is rejectedCheck the exact enum values in the Input reference and keep maxItemsPerQuery between 1 and 1,000.

Limits and important notes

  • A maximum of 50 unique keywords is accepted per run.
  • Each keyword can request up to 1,000 public job cards.
  • The maximum is not guaranteed because it depends on public availability and selected filters.
  • Public page structure and field availability can change.
  • Closed or removed jobs can disappear between search and detail retrieval.
  • Salary, applicants, company page, logo, and job criteria are best-effort fields.
  • This Actor collects job-posting data, not private LinkedIn account data.

Local development

Clone the repository and create a Python 3.13 virtual environment:

git clone https://github.com/datacrawler-edu/actor-linkedin-jobs.git
cd actor-linkedin-jobs
python -m venv .venv

On Windows PowerShell:

.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements-dev.txt

Run the local quality gate:

python -m ruff check .
python -m ruff format --check .
python -m compileall -q src tests
python -m pytest -q
apify validate-schema

Real HTTP validation requires the private proxy URL at runtime. Never store a real credential in .env, source files, fixtures, logs, or Git history. See docs/PRODUCTION_RUNBOOK.md for the release procedure.

Project documentation

  • docs/PRODUCTION_RUNBOOK.md: secrets, release gate, deployment, monetization, and incident signals.
  • docs/VALIDATION_2026-07-13.md: local and remote validation evidence.
  • docs/HTTP_RESEARCH_2026-07-13.md: researched public endpoint and parser contract.
  • CHANGELOG.md: release history.

Responsible use

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation. LinkedIn is a registered trademark of its owner.

Use the data responsibly and ensure that your use complies with applicable laws, data-protection requirements, and the terms that apply to the source and your intended use case.