LinkedIn Job Scraper avatar

LinkedIn Job Scraper

Pricing

from $8.00 / 1,000 results

Go to Apify Store
LinkedIn Job Scraper

LinkedIn Job Scraper

Extract the title, company, salary, posting date and full description of public LinkedIn job listings, searched by keyword and location.

Pricing

from $8.00 / 1,000 results

Rating

5.0

(2)

Developer

Rush

Rush

Maintained by Community

Actor stats

5

Bookmarked

179

Total users

3

Monthly active users

9 days ago

Last modified

Share

Collect public LinkedIn job listings by keyword and location. Use the results for job-market research, recruiting workflows, tracking which companies are hiring, and structured analysis.

Features

Each saved result includes the search keyword that first produced it, listing ID, title, job URL, and collection time. Company, location, posted date, and the following details are included when the listing makes them available:

  • Job description text
  • Seniority level, employment type, job function, and industries, as the listing labels them
  • Salary range, currency, and pay period, when the listing shows a pay range in its own pay section
  • Company page link
  • Email addresses and web links written in the description (links to LinkedIn itself are left out), and phone numbers the description introduces as one, such as after "Phone:" or "call us at"
  • Parsed city, state or region, and country

How to use

  1. Add one or more job-search keywords.
  2. Choose a location and any filters you need.
  3. Set the total result limit and start the Actor.

Input

FieldRequiredDescription
keywordsYesJob titles, skills, or company names. 1 to 10 searches; repeated entries are combined.
locationNoCity, region, or country. Default: United States.
datePostedNoAny time, past 24 hours, past week, or past month. Default: past week.
jobTypeNoFull-time, part-time, contract, temporary, or internship. Only listings that state a chosen type are saved.
experienceLevelNoInternship through executive level. Only listings that state a chosen level are saved; listings marked "Not Applicable" are left out.
limitNoTotal number of results to save across all searches, from 10 to 690. Default: 40.

API inputs can also set jobsPerKeyword (10 to 69), a limit for each search on its own. Each search then stops at that limit, even when another search runs out or cannot be completed. The total limit still applies (40 unless set) and is used up in the order the searches are listed, so set it to at least jobsPerKeyword × the number of searches; the run log names any search that was not reached because the total was already used up.

Example input

{
"keywords": ["software engineer", "data engineer"],
"location": "Taiwan",
"datePosted": "past-week",
"limit": 40
}

Output

Results are saved progressively to the Dataset as flat JSON records. The Output tab links to the job listings table, the complete data with every field, and a run summary.

{
"jobId": "4437461678",
"searchKeyword": "software engineer",
"title": "Software Engineer",
"companyName": "Example Company",
"companyUrl": "https://www.linkedin.com/company/example",
"locationRaw": "Taipei, Taipei City, Taiwan",
"locationCity": "Taipei",
"locationState": "Taipei City",
"locationCountry": "Taiwan",
"locationIsRemote": null,
"salaryMin": null,
"salaryMax": null,
"salaryCurrency": null,
"salaryPeriod": null,
"description": "Public job description text",
"seniorityLevel": "Mid-Senior level",
"employmentType": "Full-time",
"jobFunction": "Engineering",
"industries": "Manufacturing",
"emails": null,
"phones": null,
"urls": null,
"postedDate": "2026-07-14T00:00:00.000Z",
"jobUrl": "https://tw.linkedin.com/jobs/view/software-engineer-at-example-company-4437461678",
"applicationUrl": null,
"isPartial": false,
"missingFields": [],
"scrapedAt": "2026-07-14T01:00:00.000Z"
}

jobId identifies each listing. Links in jobUrl and companyUrl can start with a country prefix such as tw.linkedin.com, so use jobId to match the same listing across runs. An employer can publish the same role as a separate listing for each location; each has its own jobId and is saved as its own row. postedDate is the day the listing was posted (UTC); its time is always 00:00.

Fields are null when the listing does not publicly state them. Phone numbers are saved when the description introduces them as one, such as after "Phone:", "Tel." or "call us at". Some numbers and email addresses are not recognised, such as local numbers outside North America and addresses containing accented letters, so an empty phones or emails does not always mean the listing gives none; the full text is in description. A location given as a single name, such as a country or a metropolitan area, is kept in locationRaw only. A result is partial (isPartial: true) when it is missing one of four core details: company name, location, description, or posted date; missingFields lists which. Other empty fields, such as salary, do not make a result partial.

Salary fields come only from the pay range a listing shows in its own pay section. Many employers write their pay only in the description; for those listings the salary fields stay null and the pay text is in description.

The default table shows the most useful columns; the "Complete data" view has every field.

Run summary

The Output tab links to a run summary with these fields:

FieldMeaning
statusHow the run ended (see below).
requestedThe number of results this run worked toward.
savedResults saved to the Dataset.
partialSaved results marked isPartial, meaning a core detail is missing.
failedListings whose details could not be read by the end of the run, so they were not saved. A listing that one search could not read and another search saved is not counted.
keywordsCompleted / keywordsIncompleteSearches that finished, and searches that could not be completed. With jobsPerKeyword, a search that was not reached because the total was already used up is in neither.
setAsideListings not saved because they did not match the job type or experience level you chose.
startedAt / finishedAtWhen the run began collecting and when this summary was written. A run resurrected after it stopped early keeps its original start time.

status is one of:

  • succeeded: every result you asked for was saved, or every search ran out of listings (or reached its jobsPerKeyword limit) with nothing lost along the way.
  • partial: fewer results than you asked for were saved, and at least one of these happened: a search could not be completed, some listings could not be read, a saved result is missing a core detail, or the run ended early after saving some results.
  • stopped: the run was ended early, before saving any result: you stopped it, it reached its time limit or its maximum cost (the run log says which), or it failed (the run is marked as failed, and its status message says so).

FAQ

Why are some fields null?

Listings do not all publish the same details, and what a listing leaves unsaid stays null rather than guessed. The Output section explains where salary comes from and which empty fields mark a result as partial.

Why did I get fewer results than my limit?

  • Your filters. When you choose a job type or an experience level, a listing is saved only if it states one you chose. A listing that states something else, or nothing, is not saved, and one whose experience level reads "Not Applicable" is not saved once you choose any level. setAside in the run summary counts them.
  • A search ran out. When LinkedIn has no more listings for a search, the run log says so, and what that search did not use goes to your other searches. With jobsPerKeyword, each search still stops at its own limit.
  • A search could not be completed. It is counted in keywordsIncomplete, and the run log names it and says why.
  • Time ran out. Each run collects for up to 50 minutes at a time, or until its timeout if that is shorter. The run log then says how many were saved, and the progress is kept: resurrect the run (the Resurrect button on the run's page in Apify Console, or the API) to continue from where it stopped. Starting a new run begins the searches again from the start. The largest limits can need the same run resurrected more than once.
  • The run reached its maximum cost per run. The run log says so.

A run that stops at its time limit or at its maximum cost per run still ends as Succeeded, so for scheduled or API runs, check status and saved in the run summary. When every keyword matters, check keywordsIncomplete too: a run can save every result you asked for even when a search could not be completed. With jobsPerKeyword, a search that was not reached because the total was already used up is named only in the run log; set limit to at least jobsPerKeyword × the number of searches to reach every search. Resurrecting a run that already saved every result you asked for collects nothing more; start a new run for a search that could not be completed.

Why are locationIsRemote and applicationUrl usually empty?

Public listings rarely say how the work is arranged. locationIsRemote is true when a listing's location says Remote, false when it says Hybrid or On-site, and null when it says neither; locationRaw keeps the listing's own wording. On public listings the Apply button asks visitors to sign in to LinkedIn rather than linking to the employer's own page, so applicationUrl is normally empty; open jobUrl to reach the listing. The public search itself cannot be narrowed to remote jobs.

Why did my run end with no results?

If LinkedIn returns no listings for your searches, the run succeeds and the run log says so for each search; a broader keyword, location, or date range can help. If you chose a job type or an experience level, setAside in the run summary counts the listings that did not state one of your choices, and widening or removing that choice can help. If no search could be completed, the run is marked as failed and its status message says why. When LinkedIn did not make listings available at the time, trying again later may help.

Why do some results not mention my keyword?

When few or no listings match a search, LinkedIn can fill its results with other listings. They are saved like any other result, and searchKeyword shows which search produced each one. For example, a search for a company name can return that company's listings followed by other employers' listings, so check title and companyName when that matters.

Can I search several roles at once?

Yes. Add multiple keyword entries and set one total result limit. The Actor shares that limit across the searches; when a search runs out of listings, what it did not use goes to the others.

Can I export the results?

Yes. Apify Datasets support common structured export formats and API access.

Responsible use

This Actor collects information available on public job listing pages. You are responsible for using the results lawfully and for following applicable privacy, data-protection, employment, and platform requirements. Do not use contact data for unsolicited or prohibited outreach. Source availability and field coverage can change.

Explore more FuturizeRush Actors

LinkedIn Job Scraper, LinkedIn jobs, job listings, recruitment data, hiring research, salary data, Claude Code, OpenClaw, Gemini, Antigravity, Codex, ChatGPT